/* Copyright (C) 2011-2015 de4dot@gmail.com This file is part of de4dot. de4dot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. de4dot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with de4dot. If not, see . */ using System; using System.Collections.Generic; using System.Reflection; using AssemblyData; namespace de4dot.code.deobfuscators.Eazfuscator_NET { class DynocodeService : IUserGenericService { public const int MSG_CREATE_ENUMERABLE = 0; public const int MSG_WRITE_ENUMERABLE_FIELD = 1; public const int MSG_CREATE_ENUMERATOR = 2; public const int MSG_CALL_GET_CURRENT = 3; public const int MSG_CALL_MOVE_NEXT = 4; Module reflObfModule; object ienumerable = null; object ienumerator = null; MethodInfo mi_get_Current; MethodInfo mi_MoveNext; [CreateUserGenericService] public static IUserGenericService Create() { return new DynocodeService(); } public void AssemblyLoaded(Assembly assembly) { this.reflObfModule = assembly.ManifestModule; } public object HandleMessage(int msg, object[] args) { switch (msg) { case MSG_CREATE_ENUMERABLE: CreateEnumerable((uint)args[0], args[1] as object[]); return true; case MSG_WRITE_ENUMERABLE_FIELD: WriteEnumerableField((uint)args[0], args[1] as object); return true; case MSG_CREATE_ENUMERATOR: CreateEnumerator(); return true; case MSG_CALL_GET_CURRENT: return CallGetCurrent(); case MSG_CALL_MOVE_NEXT: return CallMoveNext(); default: throw new ApplicationException(string.Format("Invalid msg: {0:X8}", msg)); } } void CreateEnumerable(uint ctorToken, object[] args) { var ctor = reflObfModule.ResolveMethod((int)ctorToken) as ConstructorInfo; if (ctor == null) throw new ApplicationException(string.Format("Invalid ctor with token: {0:X8}", ctorToken)); ienumerable = ctor.Invoke(args); } void WriteEnumerableField(uint fieldToken, object value) { var field = reflObfModule.ResolveField((int)fieldToken); if (field == null) throw new ApplicationException(string.Format("Invalid field: {0:X8}", fieldToken)); field.SetValue(ienumerable, value); } void CreateEnumerator() { foreach (var method in ienumerable.GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (method.GetParameters().Length != 0) continue; var retType = method.ReturnType; if (!retType.IsGenericType) continue; var genArgs = retType.GetGenericArguments(); if (genArgs.Length != 1) continue; if (genArgs[0] != typeof(int)) continue; if (!FindEnumeratorMethods(retType)) continue; ienumerator = method.Invoke(ienumerable, null); return; } throw new ApplicationException("No GetEnumerator() method found"); } bool FindEnumeratorMethods(Type type) { mi_get_Current = null; mi_MoveNext = null; foreach (var method in ienumerable.GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (Is_get_Current(method)) { if (mi_get_Current != null) return false; mi_get_Current = method; continue; } if (Is_MoveNext(method)) { if (mi_MoveNext != null) return false; mi_MoveNext = method; continue; } } return mi_get_Current != null && mi_MoveNext != null; } static bool Is_get_Current(MethodInfo method) { if (method.GetParameters().Length != 0) return false; if (method.ReturnType != typeof(int)) return false; return true; } static bool Is_MoveNext(MethodInfo method) { if (method.GetParameters().Length != 0) return false; if (method.ReturnType != typeof(bool)) return false; return true; } int CallGetCurrent() { return (int)mi_get_Current.Invoke(ienumerator, null); } bool CallMoveNext() { return (bool)mi_MoveNext.Invoke(ienumerator, null); } public void Dispose() { } } }