From 1cdac23681db967a90db6a642e83dd5de7a9cd55 Mon Sep 17 00:00:00 2001 From: de4dot Date: Sun, 23 Mar 2014 07:39:55 +0100 Subject: [PATCH] Support Eazfuscator.NET 4.2 - 4.3 --- .../Eazfuscator_NET/DynocodeService.cs | 73 ++++++++++++++++-- .../Eazfuscator_NET/StringDecrypter.cs | 8 +- .../Eazfuscator_NET/VersionDetector.cs | 74 ++++++++++++++++++- 3 files changed, 144 insertions(+), 11 deletions(-) diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/DynocodeService.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/DynocodeService.cs index 06371ab5..31cdb538 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/DynocodeService.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/DynocodeService.cs @@ -31,8 +31,10 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { public const int MSG_CALL_MOVE_NEXT = 4; Module reflObfModule; - IEnumerable ienumerable = null; - IEnumerator ienumerator = null; + object ienumerable = null; + object ienumerator = null; + MethodInfo mi_get_Current; + MethodInfo mi_MoveNext; [CreateUserGenericService] public static IUserGenericService Create() { @@ -72,7 +74,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { var ctor = reflObfModule.ResolveMethod((int)ctorToken) as ConstructorInfo; if (ctor == null) throw new ApplicationException(string.Format("Invalid ctor with token: {0:X8}", ctorToken)); - ienumerable = (IEnumerable)ctor.Invoke(args); + ienumerable = ctor.Invoke(args); } void WriteEnumerableField(uint fieldToken, object value) { @@ -83,15 +85,74 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { } void CreateEnumerator() { - ienumerator = ienumerable.GetEnumerator(); + 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 ienumerator.Current; + return (int)mi_get_Current.Invoke(ienumerator, null); } bool CallMoveNext() { - return ienumerator.MoveNext(); + return (bool)mi_MoveNext.Invoke(ienumerator, null); } public void Dispose() { diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs index da60a999..8bece13c 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs @@ -696,8 +696,8 @@ done: ; if (initValue2 == null || !initValue2.AllBitsValid()) return false; - int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32 System.Collections.Generic.IEnumerator`1::get_Current()"); - int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean System.Collections.IEnumerator::MoveNext()"); + int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32", "()"); + int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean", "()"); if (loopStart < 0 || loopEnd < 0) return false; loopStart++; @@ -720,7 +720,7 @@ done: ; return true; } - static int GetIndexOfCall(IList instrs, int startIndex, int endIndex, string fullMethodName) { + static int GetIndexOfCall(IList instrs, int startIndex, int endIndex, string returnType, string parameters) { if (startIndex < 0 || endIndex < 0) return -1; for (int i = startIndex; i < endIndex; i++) { @@ -728,7 +728,7 @@ done: ; if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt) continue; var method = instr.Operand as IMethod; - if (method == null || method.FullName != fullMethodName) + if (!DotNetUtils.IsMethod(method, returnType, parameters)) continue; return i; diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs index 980d9d03..9e6e6e73 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs @@ -722,13 +722,85 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { decryptStringMethod.Body.ExceptionHandlers.Count >= 2 && new LocalTypes(decryptStringMethod).All(locals35) && CheckTypeFields2(fields35)) { - return "3.5 - 4.1"; + return "3.5 - 4.2"; + } + + ///////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + + var fields43 = new string[] { + GetNestedTypeName(0), + GetNestedTypeName(1), + "System.Byte[]", + "System.Int16", + "System.Int32", + "System.Byte[]", + "System.Int32", + "System.Int32", + GetNestedTypeName(2), + }; + var locals43 = CreateLocalsArray( + "System.Boolean", + "System.Byte", + "System.Byte[]", + "System.Char[]", + FindEnumeratorName(decryptStringMethod), + GetNestedTypeName(0), + "System.Diagnostics.StackFrame", + "System.Diagnostics.StackTrace", + "System.Int16", + "System.Int32", + "System.Int64", + "System.IO.Stream", + "System.Reflection.Assembly", + "System.Reflection.AssemblyName", + "System.Reflection.MethodBase", + "System.String", + "System.Text.StringBuilder", + "System.Type" + ); + var olocals43 = CreateLocalsArray( + "System.Int32" + ); + if (otherMethods.Count == 1 && + decryptStringType.NestedTypes.Count == 3 && + DotNetUtils.IsMethod(otherMethods[0], "System.Void", "(System.Byte[],System.Int32,System.Byte[])") && + otherMethods[0].IsPrivate && + otherMethods[0].IsStatic && + new LocalTypes(otherMethods[0]).Exactly(olocals43) && + decryptStringMethod.IsNoInlining && + decryptStringMethod.IsAssembly && + !decryptStringMethod.IsSynchronized && + decryptStringMethod.Body.MaxStack >= 1 && + decryptStringMethod.Body.MaxStack <= 8 && + decryptStringMethod.Body.ExceptionHandlers.Count >= 2 && + new LocalTypes(decryptStringMethod).All(locals43) && + CheckTypeFields2(fields43)) { + return "4.3"; } } return null; } + static string FindEnumeratorName(MethodDef method) { + foreach (var local in method.Body.Variables) { + var gis = local.Type as GenericInstSig; + if (gis == null) + continue; + if (gis.FullName == "System.Collections.Generic.IEnumerator`1") + continue; + if (gis.GenericArguments.Count != 1) + continue; + if (gis.GenericArguments[0].GetFullName() != "System.Int32") + continue; + + return gis.FullName; + } + return null; + } + TypeDef GetNestedType(int n) { var type = stringDecrypter.Type;