diff --git a/blocks/DotNetUtils.cs b/blocks/DotNetUtils.cs index 0c310b86..dead4b31 100644 --- a/blocks/DotNetUtils.cs +++ b/blocks/DotNetUtils.cs @@ -23,6 +23,10 @@ using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Metadata; +//TODO: Remove these +using DN = dot10.DotNet; +using DNE = dot10.DotNet.Emit; + namespace de4dot.blocks { public enum FrameworkType { Unknown, @@ -635,6 +639,11 @@ namespace de4dot.blocks { return newMethod; } + // Copies most things but not everything + public static DN.MethodDef clone(DN.MethodDef method) { + return null; //TODO: + } + public static Instruction clone(Instruction instr) { return new Instruction { Offset = instr.Offset, @@ -707,6 +716,22 @@ namespace de4dot.blocks { bodyExceptionHandlers.Add(eh); } + + public static void restoreBody(DN.MethodDef method, IEnumerable instructions, IEnumerable exceptionHandlers) { + if (method == null || method.CilBody == null) + return; + + var bodyInstrs = method.CilBody.Instructions; + bodyInstrs.Clear(); + foreach (var instr in instructions) + bodyInstrs.Add(instr); + + var bodyExceptionHandlers = method.CilBody.ExceptionHandlers; + bodyExceptionHandlers.Clear(); + foreach (var eh in exceptionHandlers) + bodyExceptionHandlers.Add(eh); + } + public static void copyBodyFromTo(MethodDefinition fromMethod, MethodDefinition toMethod) { if (fromMethod == toMethod) return; @@ -1035,6 +1060,16 @@ namespace de4dot.blocks { return args; } + public static List getArgs(DN.IMethod method) { + var sig = method.MethodSig; + var args = new List(sig.Params.Count + 1); + if (sig.HasThis && !sig.ExplicitThis) + args.Add(method.DeclaringType); + foreach (var arg in sig.Params) + args.Add(arg); + return args; + } + public static TypeReference getArgType(MethodReference method, Instruction instr) { return getArgType(getArgs(method), instr); } @@ -1056,6 +1091,16 @@ namespace de4dot.blocks { return count; } + public static int getArgsCount(DN.IMethod method) { + var sig = method.MethodSig; + if (sig == null) + return 0; + int count = sig.Params.Count; + if (sig.HasThis && !sig.ExplicitThis) + count++; + return count; + } + public static Instruction createLdci4(int value) { if (value == -1) return Instruction.Create(OpCodes.Ldc_I4_M1); if (value == 0) return Instruction.Create(OpCodes.Ldc_I4_0); @@ -1113,6 +1158,25 @@ namespace de4dot.blocks { return null; } + public static DNE.Instruction getInstruction(IList instructions, ref int index) { + for (int i = 0; i < 10; i++) { + if (index < 0 || index >= instructions.Count) + return null; + var instr = instructions[index++]; + if (instr.OpCode.Code == DNE.Code.Nop) + continue; + if (instr.OpCode.OpCodeType == DNE.OpCodeType.Prefix) + continue; + if (instr == null || (instr.OpCode.Code != DNE.Code.Br && instr.OpCode.Code != DNE.Code.Br_S)) + return instr; + instr = instr.Operand as DNE.Instruction; + if (instr == null) + return null; + index = instructions.IndexOf(instr); + } + return null; + } + public static PropertyDefinition createPropertyDefinition(string name, TypeReference propType, MethodDefinition getter, MethodDefinition setter) { return new PropertyDefinition(name, PropertyAttributes.None, propType) { MetadataToken = nextPropertyToken(), diff --git a/blocks/FilterHandlerBlock.cs b/blocks/FilterHandlerBlock.cs index 24470c1a..63018be8 100644 --- a/blocks/FilterHandlerBlock.cs +++ b/blocks/FilterHandlerBlock.cs @@ -18,8 +18,6 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace de4dot.blocks { public class FilterHandlerBlock : ScopeBlock { diff --git a/blocks/ForwardScanOrder.cs b/blocks/ForwardScanOrder.cs index 5f4da69d..751608ca 100644 --- a/blocks/ForwardScanOrder.cs +++ b/blocks/ForwardScanOrder.cs @@ -19,8 +19,6 @@ using System; using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace de4dot.blocks { // This class makes sure that each block that is entered with a non-empty stack has at diff --git a/blocks/HandlerBlock.cs b/blocks/HandlerBlock.cs index 9b23d21b..7b53c88f 100644 --- a/blocks/HandlerBlock.cs +++ b/blocks/HandlerBlock.cs @@ -18,8 +18,6 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; namespace de4dot.blocks { // This is the block inside catch(xxx) { }. diff --git a/blocks/blocks.csproj b/blocks/blocks.csproj index 2a55027e..05726682 100644 --- a/blocks/blocks.csproj +++ b/blocks/blocks.csproj @@ -38,26 +38,26 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + diff --git a/blocks/cflow/BlockCflowDeobfuscator.cs b/blocks/cflow/BlockCflowDeobfuscator.cs index efc31a05..3060f828 100644 --- a/blocks/cflow/BlockCflowDeobfuscator.cs +++ b/blocks/cflow/BlockCflowDeobfuscator.cs @@ -18,7 +18,7 @@ */ using System; -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { class BlockCflowDeobfuscator : BlockDeobfuscator, IBranchHandler { @@ -33,7 +33,7 @@ namespace de4dot.blocks.cflow { protected override bool deobfuscate(Block block) { this.block = block; - if (!DotNetUtils.isConditionalBranch(block.LastInstr.OpCode.Code) && block.LastInstr.OpCode.Code != Code.Switch) + if (!block.LastInstr.isConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch) return false; instructionEmulator.init(blocks); diff --git a/blocks/cflow/BlocksCflowDeobfuscator.cs b/blocks/cflow/BlocksCflowDeobfuscator.cs index 0c9a2236..d21e6ad9 100644 --- a/blocks/cflow/BlocksCflowDeobfuscator.cs +++ b/blocks/cflow/BlocksCflowDeobfuscator.cs @@ -18,8 +18,7 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { public class BlocksCflowDeobfuscator { diff --git a/blocks/cflow/BranchEmulator.cs b/blocks/cflow/BranchEmulator.cs index ab605146..f0a89639 100644 --- a/blocks/cflow/BranchEmulator.cs +++ b/blocks/cflow/BranchEmulator.cs @@ -17,7 +17,7 @@ along with de4dot. If not, see . */ -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { public interface IBranchHandler { diff --git a/blocks/cflow/CachedCflowDeobfuscator.cs b/blocks/cflow/CachedCflowDeobfuscator.cs index c3a8bd86..f19b03b6 100644 --- a/blocks/cflow/CachedCflowDeobfuscator.cs +++ b/blocks/cflow/CachedCflowDeobfuscator.cs @@ -18,14 +18,14 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { // Only deobfuscates a method once. A copy of the method (now deobfuscated) is returned. public class CachedCflowDeobfuscator { BlocksCflowDeobfuscator cflowDeobfuscator = new BlocksCflowDeobfuscator(); - Dictionary deobfuscated = new Dictionary(); + Dictionary deobfuscated = new Dictionary(); public CachedCflowDeobfuscator() { } @@ -43,12 +43,12 @@ namespace de4dot.blocks.cflow { cflowDeobfuscator.add(blocksDeobfuscator); } - public MethodDefinition deobfuscate(MethodDefinition method) { - MethodDefinition deobfuscatedMethod; + public MethodDef deobfuscate(MethodDef method) { + MethodDef deobfuscatedMethod; if (deobfuscated.TryGetValue(method, out deobfuscatedMethod)) return deobfuscatedMethod; - if (method.Body == null || method.Body.Instructions.Count == 0) { + if (method.CilBody == null || method.CilBody.Instructions.Count == 0) { deobfuscated[method] = method; return method; } diff --git a/blocks/cflow/CflowDeobfuscator.cs b/blocks/cflow/CflowDeobfuscator.cs index 3af00398..2ca7454c 100644 --- a/blocks/cflow/CflowDeobfuscator.cs +++ b/blocks/cflow/CflowDeobfuscator.cs @@ -18,8 +18,8 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { public class CflowDeobfuscator : ICflowDeobfuscator { @@ -32,18 +32,18 @@ namespace de4dot.blocks.cflow { cflowDeobfuscator.add(blocksDeobfuscator); } - public void deobfuscate(MethodDefinition method) { + public void deobfuscate(MethodDef method) { deobfuscate(method, (blocks) => { cflowDeobfuscator.init(blocks); cflowDeobfuscator.deobfuscate(); }); } - static bool hasNonEmptyBody(MethodDefinition method) { - return method.Body != null && method.Body.Instructions.Count > 0; + static bool hasNonEmptyBody(MethodDef method) { + return method.CilBody != null && method.CilBody.Instructions.Count > 0; } - void deobfuscate(MethodDefinition method, Action handler) { + void deobfuscate(MethodDef method, Action handler) { if (hasNonEmptyBody(method)) { var blocks = new Blocks(method); diff --git a/blocks/cflow/ConstantsFolder.cs b/blocks/cflow/ConstantsFolder.cs index 327a0288..473efcb8 100644 --- a/blocks/cflow/ConstantsFolder.cs +++ b/blocks/cflow/ConstantsFolder.cs @@ -19,19 +19,19 @@ using System; using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; using de4dot.blocks; namespace de4dot.blocks.cflow { // Very simple constants folder which is all that's needed at the moment class ConstantsFolder : BlockDeobfuscator { InstructionEmulator instructionEmulator = new InstructionEmulator(); - List args; + IList args; protected override void init(List allBlocks) { base.init(allBlocks); - args = DotNetUtils.getParameters(blocks.Method); + args = blocks.Method.Parameters; } protected override bool deobfuscate(Block block) { @@ -49,7 +49,7 @@ namespace de4dot.blocks.cflow { case Code.Ldarg_2: case Code.Ldarg_3: case Code.Ldarg_S: - changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(DotNetUtils.getParameter(args, instr.Instruction))); + changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(instr.Instruction.GetParameter(args))); break; case Code.Ldloc: @@ -58,17 +58,17 @@ namespace de4dot.blocks.cflow { case Code.Ldloc_2: case Code.Ldloc_3: case Code.Ldloc_S: - changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(DotNetUtils.getLocalVar(blocks.Locals, instr.Instruction))); + changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(instr.Instruction.GetLocal(blocks.Locals))); break; case Code.Ldarga: case Code.Ldarga_S: - instructionEmulator.makeArgUnknown((ParameterDefinition)instr.Operand); + instructionEmulator.makeArgUnknown((Parameter)instr.Operand); break; case Code.Ldloca: case Code.Ldloca_S: - instructionEmulator.makeLocalUnknown((VariableDefinition)instr.Operand); + instructionEmulator.makeLocalUnknown((Local)instr.Operand); break; } @@ -89,7 +89,7 @@ namespace de4dot.blocks.cflow { var intValue = (Int32Value)value; if (!intValue.allBitsValid()) return false; - block.Instructions[index] = new Instr(DotNetUtils.createLdci4(intValue.value)); + block.Instructions[index] = new Instr(Instruction.CreateLdcI4(intValue.value)); return true; } else if (value.isInt64()) { diff --git a/blocks/cflow/DeadCodeRemover.cs b/blocks/cflow/DeadCodeRemover.cs index 410a62cc..07b1f77d 100644 --- a/blocks/cflow/DeadCodeRemover.cs +++ b/blocks/cflow/DeadCodeRemover.cs @@ -18,7 +18,7 @@ */ using System.Collections.Generic; -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { // Removes dead code that is the result of one of our optimizations, or created by the @@ -185,7 +185,7 @@ namespace de4dot.blocks.cflow { case Code.Ldc_I8: case Code.Ldc_R4: case Code.Ldc_R8: - case Code.Ldelem_Any: + case Code.Ldelem: case Code.Ldelem_I: case Code.Ldelem_I1: case Code.Ldelem_I2: @@ -237,7 +237,6 @@ namespace de4dot.blocks.cflow { case Code.Mul_Ovf_Un: case Code.Neg: case Code.Newarr: - case Code.No: case Code.Nop: case Code.Not: case Code.Or: @@ -257,7 +256,7 @@ namespace de4dot.blocks.cflow { case Code.Sub_Ovf: case Code.Sub_Ovf_Un: case Code.Switch: - case Code.Tail: + case Code.Tailcall: case Code.Throw: case Code.Unaligned: case Code.Unbox: @@ -276,7 +275,7 @@ namespace de4dot.blocks.cflow { case Code.Newobj: case Code.Starg: case Code.Starg_S: - case Code.Stelem_Any: + case Code.Stelem: case Code.Stelem_I: case Code.Stelem_I1: case Code.Stelem_I2: @@ -380,7 +379,7 @@ namespace de4dot.blocks.cflow { } static void calculateStackUsage(Instruction instr, bool methodHasReturnValue, out int pushes, out int pops) { - DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); + instr.CalculateStackUsage(false, out pushes, out pops); } } } diff --git a/blocks/cflow/DeadStoreRemover.cs b/blocks/cflow/DeadStoreRemover.cs index 3d7f870c..27174878 100644 --- a/blocks/cflow/DeadStoreRemover.cs +++ b/blocks/cflow/DeadStoreRemover.cs @@ -19,7 +19,7 @@ using System; using System.Collections.Generic; -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { // Removes dead stores by replacing the stloc with a pop. Other optimizations will notice it's @@ -80,7 +80,7 @@ namespace de4dot.blocks.cflow { void findLoadStores() { foreach (var block in allBlocks) { foreach (var instr in block.Instructions) { - VariableDefinition local; + Local local; AccessFlags flags; switch (instr.OpCode.Code) { case Code.Ldloc: @@ -105,7 +105,7 @@ namespace de4dot.blocks.cflow { case Code.Ldloca_S: case Code.Ldloca: - local = instr.Operand as VariableDefinition; + local = instr.Operand as Local; flags = AccessFlags.Read | AccessFlags.Write; break; @@ -128,7 +128,7 @@ namespace de4dot.blocks.cflow { var instructions = block.Instructions; for (int i = 0; i < instructions.Count; i++) { var instr = instructions[i]; - VariableDefinition local; + Local local; switch (instr.OpCode.Code) { case Code.Stloc: case Code.Stloc_S: diff --git a/blocks/cflow/ICflowDeobfuscator.cs b/blocks/cflow/ICflowDeobfuscator.cs index a4c083b7..d5897254 100644 --- a/blocks/cflow/ICflowDeobfuscator.cs +++ b/blocks/cflow/ICflowDeobfuscator.cs @@ -17,10 +17,10 @@ along with de4dot. If not, see . */ -using Mono.Cecil; +using dot10.DotNet; namespace de4dot.blocks.cflow { public interface ICflowDeobfuscator { - void deobfuscate(MethodDefinition method); + void deobfuscate(MethodDef method); } } diff --git a/blocks/cflow/InstructionEmulator.cs b/blocks/cflow/InstructionEmulator.cs index 129ef60e..d27616b4 100644 --- a/blocks/cflow/InstructionEmulator.cs +++ b/blocks/cflow/InstructionEmulator.cs @@ -42,11 +42,9 @@ namespace de4dot.blocks.cflow { init(method); } -#if PORT public void init(Blocks blocks) { init(blocks.Method); } -#endif public void init(MethodDef method) { this.parameterDefs = method.Parameters; @@ -234,7 +232,6 @@ namespace de4dot.blocks.cflow { return valueStack.peek(); } -#if PORT public void emulate(IEnumerable instructions) { foreach (var instr in instructions) emulate(instr.Instruction); @@ -244,7 +241,6 @@ namespace de4dot.blocks.cflow { for (int i = start; i < end; i++) emulate(instructions[i].Instruction); } -#endif public void emulate(Instruction instr) { switch (instr.OpCode.Code) { diff --git a/blocks/cflow/MethodCallInliner.cs b/blocks/cflow/MethodCallInliner.cs index 91ab747f..3bb4d91e 100644 --- a/blocks/cflow/MethodCallInliner.cs +++ b/blocks/cflow/MethodCallInliner.cs @@ -18,8 +18,8 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { public class MethodCallInliner : MethodCallInlinerBase { @@ -40,12 +40,12 @@ namespace de4dot.blocks.cflow { return changed; } - protected virtual bool canInline(MethodDefinition method) { - if (method.GenericParameters.Count > 0) + protected virtual bool canInline(MethodDef method) { + if (method.GenericParams.Count > 0) return false; if (method == blocks.Method) return false; - if (!MemberReferenceHelper.compareTypes(method.DeclaringType, blocks.Method.DeclaringType)) + if (!new SigComparer().Equals(method.DeclaringType, blocks.Method.DeclaringType)) return false; if (method.IsStatic) @@ -56,13 +56,13 @@ namespace de4dot.blocks.cflow { } bool inlineMethod(Instruction callInstr, int instrIndex) { - var methodToInline = callInstr.Operand as MethodDefinition; + var methodToInline = callInstr.Operand as MethodDef; if (methodToInline == null) return false; if (!canInline(methodToInline)) return false; - var body = methodToInline.Body; + var body = methodToInline.CilBody; if (body == null) return false; @@ -113,10 +113,10 @@ namespace de4dot.blocks.cflow { } } - protected override bool isCompatibleType(int paramIndex, TypeReference origType, TypeReference newType) { - if (MemberReferenceHelper.compareTypes(origType, newType)) + protected override bool isCompatibleType(int paramIndex, IType origType, IType newType) { + if (new SigComparer().Equals(origType, newType)) return true; - if (newType.IsValueType || origType.IsValueType) + if (isValueType(newType) || isValueType(origType)) return false; return newType.FullName == "System.Object"; } diff --git a/blocks/cflow/MethodCallInlinerBase.cs b/blocks/cflow/MethodCallInlinerBase.cs index b8d20296..4e0b3d44 100644 --- a/blocks/cflow/MethodCallInlinerBase.cs +++ b/blocks/cflow/MethodCallInlinerBase.cs @@ -18,8 +18,8 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { public abstract class MethodCallInlinerBase : IBlocksDeobfuscator { @@ -60,7 +60,7 @@ namespace de4dot.blocks.cflow { this.patchIndex = patchIndex; this.afterIndex = afterIndex; this.lastInstr = lastInstr; - this.clonedInstr = new Instr(DotNetUtils.clone(lastInstr)); + this.clonedInstr = new Instr(lastInstr.Clone()); } public void patch(Block block) { @@ -68,7 +68,7 @@ namespace de4dot.blocks.cflow { } } - protected bool inlineLoadMethod(int patchIndex, MethodDefinition methodToInline, Instruction loadInstr, int instrIndex) { + protected bool inlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex) { if (!isReturn(methodToInline, instrIndex)) return false; @@ -76,19 +76,19 @@ namespace de4dot.blocks.cflow { for (int i = 0; i < methodArgsCount; i++) block.insert(patchIndex++, Instruction.Create(OpCodes.Pop)); - block.Instructions[patchIndex] = new Instr(DotNetUtils.clone(loadInstr)); + block.Instructions[patchIndex] = new Instr(loadInstr.Clone()); return true; } - protected bool inlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex) { + protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) { return inlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0); } - protected bool inlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs) { + protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) { return patchMethod(methodToInline, tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, popLastArgs)); } - protected bool patchMethod(MethodDefinition methodToInline, InstructionPatcher patcher) { + protected bool patchMethod(MethodDef methodToInline, InstructionPatcher patcher) { if (patcher == null) return false; @@ -99,11 +99,11 @@ namespace de4dot.blocks.cflow { return true; } - protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex) { + protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) { return tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0); } - protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs) { + protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) { int loadIndex = 0; int methodArgsCount = DotNetUtils.getArgsCount(methodToInline); bool foundLdarga = false; @@ -128,10 +128,10 @@ namespace de4dot.blocks.cflow { if (!isLdarg) break; - if (DotNetUtils.getArgIndex(instr) != loadIndex) + if (instr.GetParameterIndex() != loadIndex) return null; loadIndex++; - instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex); + instr = DotNetUtils.getInstruction(methodToInline.CilBody.Instructions, ref instrIndex); } if (instr == null || loadIndex != methodArgsCount - popLastArgs) return null; @@ -140,11 +140,11 @@ namespace de4dot.blocks.cflow { if (foundLdarga) return null; var callInstr = instr; - var calledMethod = callInstr.Operand as MethodReference; + var calledMethod = callInstr.Operand as IMethod; if (calledMethod == null) return null; - if (!isCompatibleType(-1, calledMethod.MethodReturnType.ReturnType, methodToInline.MethodReturnType.ReturnType)) + if (!isCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType)) return null; if (!checkSameMethods(calledMethod, methodToInline, popLastArgs)) @@ -156,19 +156,19 @@ namespace de4dot.blocks.cflow { if (foundLdarga) return null; var newobjInstr = instr; - var ctor = newobjInstr.Operand as MethodReference; + var ctor = newobjInstr.Operand as IMethod; if (ctor == null) return null; - if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodReturnType.ReturnType)) + if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType)) return null; - var methodArgs = DotNetUtils.getArgs(methodToInline); + var methodArgs = methodToInline.Parameters; var calledMethodArgs = DotNetUtils.getArgs(ctor); - if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count) + if (methodArgs.Length + 1 - popLastArgs != calledMethodArgs.Count) return null; for (int i = 1; i < calledMethodArgs.Count; i++) { - if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1])) + if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type)) return null; } @@ -186,25 +186,26 @@ namespace de4dot.blocks.cflow { return null; } - protected virtual bool isReturn(MethodDefinition methodToInline, int instrIndex) { - var instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex); + protected virtual bool isReturn(MethodDef methodToInline, int instrIndex) { + var instr = DotNetUtils.getInstruction(methodToInline.CilBody.Instructions, ref instrIndex); return instr != null && instr.OpCode.Code == Code.Ret; } - protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline) { + protected bool checkSameMethods(IMethod method, MethodDef methodToInline) { return checkSameMethods(method, methodToInline, 0); } - protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline, int ignoreLastMethodToInlineArgs) { - var methodToInlineArgs = DotNetUtils.getArgs(methodToInline); + protected bool checkSameMethods(IMethod method, MethodDef methodToInline, int ignoreLastMethodToInlineArgs) { + var methodToInlineArgs = methodToInline.Parameters; var methodArgs = DotNetUtils.getArgs(method); - if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count) + bool hasImplicitThis = method.MethodSig.HasThis && !method.MethodSig.ExplicitThis; + if (methodToInlineArgs.Length - ignoreLastMethodToInlineArgs != methodArgs.Count) return false; for (int i = 0; i < methodArgs.Count; i++) { var methodArg = methodArgs[i]; - var methodToInlineArg = methodToInlineArgs[i]; + var methodToInlineArg = methodToInlineArgs[i].Type; if (!isCompatibleType(i, methodArg, methodToInlineArg)) { - if (i != 0 || !method.HasImplicitThis) + if (i != 0 || !hasImplicitThis) return false; if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg)) return false; @@ -214,17 +215,24 @@ namespace de4dot.blocks.cflow { return true; } - protected virtual bool isCompatibleType(int paramIndex, TypeReference origType, TypeReference newType) { - return MemberReferenceHelper.compareTypes(origType, newType); + protected virtual bool isCompatibleType(int paramIndex, IType origType, IType newType) { + return new SigComparer().Equals(origType, newType); } - static bool isCompatibleValueThisPtr(TypeReference origType, TypeReference newType) { - var newByRef = newType as ByReferenceType; + static bool isCompatibleValueThisPtr(IType origType, IType newType) { + var newByRef = newType as ByRefSig; if (newByRef == null) return false; - if (!newByRef.ElementType.IsValueType || !origType.IsValueType) + if (!isValueType(newByRef.Next) || !isValueType(origType)) return false; - return MemberReferenceHelper.compareTypes(origType, newByRef.ElementType); + return new SigComparer().Equals(origType, newByRef.Next); + } + + protected static bool isValueType(IType type) { + if (type == null) + return false; + //TODO: + return false; } } } diff --git a/blocks/cflow/StLdlocFixer.cs b/blocks/cflow/StLdlocFixer.cs index 3e6a69c8..771f76c2 100644 --- a/blocks/cflow/StLdlocFixer.cs +++ b/blocks/cflow/StLdlocFixer.cs @@ -18,12 +18,13 @@ */ using System.Collections.Generic; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { // Replace stloc + ldloc with dup + stloc class StLdlocFixer : BlockDeobfuscator { - IList locals; + IList locals; protected override void init(List allBlocks) { base.init(allBlocks); @@ -49,7 +50,7 @@ namespace de4dot.blocks.cflow { if (!instructions[i + 1].isLdloc()) break; var local = Instr.getLocalVar(locals, instr); - if (local.VariableType.FullName != "System.Boolean") + if (local.Type.ElementType != ElementType.Boolean) continue; if (local != Instr.getLocalVar(locals, instructions[i + 1])) break; diff --git a/blocks/cflow/SwitchCflowDeobfuscator.cs b/blocks/cflow/SwitchCflowDeobfuscator.cs index ae61943e..a72484ee 100644 --- a/blocks/cflow/SwitchCflowDeobfuscator.cs +++ b/blocks/cflow/SwitchCflowDeobfuscator.cs @@ -19,7 +19,8 @@ using System; using System.Collections.Generic; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { class SwitchCflowDeobfuscator : BlockDeobfuscator { @@ -64,7 +65,7 @@ namespace de4dot.blocks.cflow { } bool isSwitchType2(Block switchBlock) { - VariableDefinition local = null; + Local local = null; foreach (var instr in switchBlock.Instructions) { if (!instr.isLdloc()) continue; @@ -178,7 +179,7 @@ namespace de4dot.blocks.cflow { // swblk: // ldloc N // switch (......) - bool deobfuscateLdloc(IList switchTargets, Block switchFallThrough, Block block, VariableDefinition switchVariable) { + bool deobfuscateLdloc(IList switchTargets, Block switchFallThrough, Block block, Local switchVariable) { bool changed = false; foreach (var source in new List(block.Sources)) { if (isBranchBlock(source)) { @@ -366,18 +367,18 @@ namespace de4dot.blocks.cflow { return changed; } - static Block createBlock(Dictionary consts, Block fallThrough) { + static Block createBlock(Dictionary consts, Block fallThrough) { var block = new Block(); foreach (var kv in consts) { - block.Instructions.Add(new Instr(DotNetUtils.createLdci4(kv.Value))); + block.Instructions.Add(new Instr(Instruction.CreateLdcI4(kv.Value))); block.Instructions.Add(new Instr(Instruction.Create(OpCodes.Stloc, kv.Key))); } fallThrough.Parent.add(block); return block; } - Dictionary getBccLocalConstants(Block block) { - var dict = new Dictionary(); + Dictionary getBccLocalConstants(Block block) { + var dict = new Dictionary(); var instrs = block.Instructions; for (int i = 0; i < instrs.Count; i++) { var instr = instrs[i]; @@ -397,7 +398,7 @@ namespace de4dot.blocks.cflow { dict.Remove(local); } else if (instr.OpCode.Code == Code.Ldloca || instr.OpCode.Code == Code.Ldloca_S) { - var local = instr.Operand as VariableDefinition; + var local = instr.Operand as Local; if (local != null) dict.Remove(local); } diff --git a/dot10 b/dot10 index 526604c8..e543043a 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit 526604c81df777accde4e45327cffcba954c356c +Subproject commit e543043aff5f9f14484038d0d7bb3850b8d1d2c9