From 2581da1c26c9f92b66fddeb0af66fd82937a89fc Mon Sep 17 00:00:00 2001 From: PythEch Date: Sun, 24 Jan 2016 00:45:37 +0200 Subject: [PATCH] Make it compatible with 5.0 again Version detection may be flawed since it checks if the string decryptor method uses cgt.un instead of ceq for flags because the changes in 5.1 are subtle. --- .../Eazfuscator_NET/StringDecrypter.cs | 108 +++++++++++++++++- .../Eazfuscator_NET/VersionDetector.cs | 7 +- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs index ccdff446..11ca8c53 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs @@ -155,6 +155,12 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { stringMethod = method; realMethod = GetRealDecrypterMethod(method); isV50OrLater = true; + foreach (var inst in stringMethod.Body.Instructions) { + if (inst.OpCode.Code == Code.Cgt_Un) { + isV51OrLater = true; + break; + } + } } else stringMethod = method; @@ -422,7 +428,36 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { return -1; } - static Local GetFlagsLocal(MethodDef method, int index) { + Local GetFlagsLocal(MethodDef method, int index) { + if (isV51OrLater) + return GetFlagsLocalNew(method, index); + return GetFlagsLocalOld(method, index); + } + + // <= 5.0 + static Local GetFlagsLocalOld(MethodDef method, int index) { + var instrs = method.Body.Instructions; + if (index + 5 >= instrs.Count) + return null; + if (instrs[index++].OpCode.Code != Code.And) + return null; + if (instrs[index++].OpCode.Code != Code.Ldc_I4_0) + return null; + if (instrs[index++].OpCode.Code != Code.Ceq) + return null; + if (instrs[index++].OpCode.Code != Code.Ldc_I4_0) + return null; + if (instrs[index++].OpCode.Code != Code.Ceq) + return null; + var stloc = instrs[index++]; + if (!stloc.IsStloc()) + return null; + return stloc.GetLocal(method.Body.Variables); + } + + // 5.1+ + // Uses different OpCodes + static Local GetFlagsLocalNew(MethodDef method, int index) { var instrs = method.Body.Instructions; if (index + 5 >= instrs.Count) return null; @@ -695,7 +730,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { break; } } -done: ; +done: foreach (var val in fields.Values) { if (val == null) @@ -708,6 +743,75 @@ done: ; } bool EmulateDynocode(InstructionEmulator emu, ref int index) { + if (isV51OrLater) + return EmulateDynocodeNew(emu, ref index); + return EmulateDynocodeOld(emu, ref index); + } + + // <= 5.0 + bool EmulateDynocodeOld(InstructionEmulator emu, ref int index) { + var instrs = stringMethod.Body.Instructions; + var instr = instrs[index]; + + var ctor = instr.Operand as MethodDef; + if (ctor == null || ctor.MethodSig.GetParamCount() != 1 || ctor.MethodSig.Params[0].ElementType != ElementType.I4) + return false; + + if (index + 4 >= instrs.Count) + return false; + var ldloc = instrs[index + 3]; + var stfld = instrs[index + 4]; + if (!ldloc.IsLdloc() || stfld.OpCode.Code != Code.Stfld) + return false; + var enumerableField = stfld.Operand as FieldDef; + if (enumerableField == null) + return false; + + var initValue = emu.GetLocal(ldloc.GetLocal(stringMethod.Body.Variables)) as Int32Value; + if (initValue == null || !initValue.AllBitsValid()) + return false; + + int leaveIndex = FindLeave(instrs, index); + if (leaveIndex < 0) + return false; + var afterLoop = instrs[leaveIndex].Operand as Instruction; + if (afterLoop == null) + return false; + int newIndex = instrs.IndexOf(afterLoop); + var loopLocal = GetDCLoopLocal(index, newIndex); + if (loopLocal == null) + return false; + var initValue2 = emu.GetLocal(loopLocal) as Int32Value; + if (initValue2 == null || !initValue2.AllBitsValid()) + return false; + + int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32", "()"); + int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean", "()"); + if (loopStart < 0 || loopEnd < 0) + return false; + loopStart++; + loopEnd--; + + dynocode.Initialize(module); + var ctorArg = emu.Pop() as Int32Value; + if (ctorArg == null || !ctorArg.AllBitsValid()) + return false; + dynocode.CreateEnumerable(ctor, new object[] { ctorArg.Value }); + dynocode.WriteEnumerableField(enumerableField.MDToken.ToUInt32(), initValue.Value); + dynocode.CreateEnumerator(); + foreach (var val in dynocode) { + emu.Push(new Int32Value(val)); + for (int i = loopStart; i < loopEnd; i++) + emu.Emulate(instrs[i]); + } + + index = newIndex - 1; + return true; + } + + // 5.1+ + // the only changes are the indexes of ldloc and stfld + bool EmulateDynocodeNew(InstructionEmulator emu, ref int index) { var instrs = stringMethod.Body.Instructions; var instr = instrs[index]; diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs index 8623122e..eb7eb34c 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; +using dnlib.DotNet.Emit; using dnlib.DotNet; using de4dot.blocks; @@ -818,7 +819,11 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { decryptStringMethod.Body.ExceptionHandlers.Count == 1 && new LocalTypes(decryptStringMethod).All(locals50) && CheckTypeFields2(fields50)) { - return "5.0"; + foreach (var inst in stringDecrypter.Method.Body.Instructions) { + if (inst.OpCode.Code == Code.Cgt_Un) + return "5.1"; + } + return "5.0"; } }