From f5f97393c24e81d1f639fe1fce611bea5f5cdc58 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 13:26:36 +0100 Subject: [PATCH 001/133] Add dot10 submodule --- .gitmodules | 3 +++ dot10 | 1 + 2 files changed, 4 insertions(+) create mode 160000 dot10 diff --git a/.gitmodules b/.gitmodules index af49613a..625f21bd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "cecil"] path = cecil url = git@github.com:0xd4d/cecil.git +[submodule "dot10"] + path = dot10 + url = e:/work/dot10.git diff --git a/dot10 b/dot10 new file mode 160000 index 00000000..80ac6ba4 --- /dev/null +++ b/dot10 @@ -0,0 +1 @@ +Subproject commit 80ac6ba43c0ec9a044f850422415e3d2ad795d28 From 0f18ad36cbce79a6055a75d71ba7953e2d392c87 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 13:47:50 +0100 Subject: [PATCH 002/133] Add dot10 --- de4dot.sln | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/de4dot.sln b/de4dot.sln index f6106896..e4fc951c 100644 --- a/de4dot.sln +++ b/de4dot.sln @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "de4dot.cui", "de4dot.cui\de EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "de4dot.mdecrypt", "de4dot.mdecrypt\de4dot.mdecrypt.csproj", "{5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dot10", "dot10\src\dot10.csproj", "{FDFC1237-143F-4919-8318-4926901F4639}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -941,6 +943,78 @@ Global {5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}.winphone_Release|Mixed Platforms.Build.0 = Release|Any CPU {5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}.winphone_Release|Win32.ActiveCfg = Release|Any CPU {5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}.winphone_Release|x86.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Win32.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Debug|x86.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Debug|Win32.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Debug|x86.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Release|Any CPU.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Release|Mixed Platforms.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Release|Win32.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_2_0_Release|x86.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Debug|Win32.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Debug|x86.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Release|Any CPU.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Release|Mixed Platforms.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Release|Win32.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_3_5_Release|x86.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Debug|Win32.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Debug|x86.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Release|Any CPU.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Release|Mixed Platforms.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Release|Win32.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.net_4_0_Release|x86.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Release|Win32.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.Release|x86.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Debug|Win32.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Debug|x86.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Release|Any CPU.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Release|Mixed Platforms.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Release|Win32.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.silverlight_Release|x86.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Debug|Win32.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Debug|x86.ActiveCfg = Debug|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Release|Any CPU.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Release|Mixed Platforms.Build.0 = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Release|Win32.ActiveCfg = Release|Any CPU + {FDFC1237-143F-4919-8318-4926901F4639}.winphone_Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From ee7826576c606266bee9900a936d8cdb6c1d7a33 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 13:48:12 +0100 Subject: [PATCH 003/133] Sort project file --- de4dot.code/de4dot.code.csproj | 96 +++++++++++++++++----------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index cd366ade..074c942d 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -53,6 +53,7 @@ + @@ -67,22 +68,6 @@ - - - - - - - - - - - - - - - - @@ -108,68 +93,77 @@ - + + + - - + - + + + + + + + + + - - - - - - - + + + + + + + @@ -179,26 +173,20 @@ + - - - - - + - - - @@ -212,19 +200,34 @@ + + + + + + + - + - + + + + + + + + + @@ -232,14 +235,6 @@ - - - - - - - - @@ -256,6 +251,12 @@ + + + + + + @@ -263,10 +264,10 @@ + - @@ -274,7 +275,6 @@ - @@ -302,11 +302,11 @@ + - From 6f73696cc5b3844e94d604860c79772f89455312 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 16:54:20 +0100 Subject: [PATCH 004/133] Port ..... --- blocks/blocks.csproj | 38 +- blocks/cflow/InstructionEmulator.cs | 143 ++++--- de4dot.code/ObfuscatedFile.cs | 8 + de4dot.code/de4dot.code.csproj | 360 +++++++++--------- de4dot.code/deobfuscators/ArrayFinder.cs | 44 +-- de4dot.code/deobfuscators/DeobfuscatorBase.cs | 4 +- de4dot.code/deobfuscators/IDeobfuscator.cs | 2 + de4dot.cui/Program.cs | 2 + dot10 | 2 +- 9 files changed, 309 insertions(+), 294 deletions(-) diff --git a/blocks/blocks.csproj b/blocks/blocks.csproj index eff0ba86..2a55027e 100644 --- a/blocks/blocks.csproj +++ b/blocks/blocks.csproj @@ -38,29 +38,29 @@ - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - @@ -68,8 +68,8 @@ - + @@ -99,6 +99,10 @@ {D68133BD-1E63-496E-9EDE-4FBDBF77B486} Mono.Cecil + + {FDFC1237-143F-4919-8318-4926901F4639} + dot10 + diff --git a/blocks/cflow/InstructionEmulator.cs b/blocks/cflow/InstructionEmulator.cs index 6ca70268..129ef60e 100644 --- a/blocks/cflow/InstructionEmulator.cs +++ b/blocks/cflow/InstructionEmulator.cs @@ -19,39 +19,38 @@ using System; using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Metadata; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks.cflow { public class InstructionEmulator { ValueStack valueStack = new ValueStack(); Dictionary protectedStackValues = new Dictionary(); - IList parameterDefinitions; - IList variableDefinitions; + IList parameterDefs; + IList localDefs; List args = new List(); List locals = new List(); - int argBase; - MethodDefinition prev_method; + MethodDef prev_method; List cached_args = new List(); List cached_locals = new List(); - int cached_argBase; public InstructionEmulator() { } - public InstructionEmulator(MethodDefinition method) { + public InstructionEmulator(MethodDef method) { init(method); } +#if PORT public void init(Blocks blocks) { init(blocks.Method); } +#endif - public void init(MethodDefinition method) { - this.parameterDefinitions = method.Parameters; - this.variableDefinitions = method.Body.Variables; + public void init(MethodDef method) { + this.parameterDefs = method.Parameters; + this.localDefs = method.CilBody.LocalList; valueStack.init(); protectedStackValues.Clear(); @@ -59,20 +58,14 @@ namespace de4dot.blocks.cflow { prev_method = method; cached_args.Clear(); - cached_argBase = 0; - if (method.HasImplicitThis) { - cached_argBase = 1; - cached_args.Add(new UnknownValue()); - } - for (int i = 0; i < parameterDefinitions.Count; i++) - cached_args.Add(getUnknownValue(parameterDefinitions[i].ParameterType)); + for (int i = 0; i < parameterDefs.Count; i++) + cached_args.Add(getUnknownValue(parameterDefs[i].Type)); cached_locals.Clear(); - for (int i = 0; i < variableDefinitions.Count; i++) - cached_locals.Add(getUnknownValue(variableDefinitions[i].VariableType)); + for (int i = 0; i < localDefs.Count; i++) + cached_locals.Add(getUnknownValue(localDefs[i].Type)); } - argBase = cached_argBase; args.Clear(); args.AddRange(cached_args); locals.Clear(); @@ -83,10 +76,14 @@ namespace de4dot.blocks.cflow { protectedStackValues[value] = true; } - static Value getUnknownValue(TypeReference typeReference) { - if (typeReference == null) + static Value getUnknownValue(ITypeDefOrRef type) { + return getUnknownValue(type.ToTypeSig(false)); + } + + static Value getUnknownValue(TypeSig type) { + if (type == null) return new UnknownValue(); - switch (typeReference.EType) { + switch (type.ElementType) { case ElementType.Boolean: return Int32Value.createUnknownBool(); case ElementType.I1: return Int32Value.createUnknown(); case ElementType.U1: return Int32Value.createUnknownUInt8(); @@ -100,13 +97,13 @@ namespace de4dot.blocks.cflow { return new UnknownValue(); } - Value truncateValue(Value value, TypeReference typeReference) { - if (typeReference == null) + Value truncateValue(Value value, TypeSig type) { + if (type == null) return value; if (protectedStackValues.ContainsKey(value)) return value; - switch (typeReference.EType) { + switch (type.ElementType) { case ElementType.Boolean: if (value.isInt32()) return ((Int32Value)value).toBoolean(); @@ -167,27 +164,22 @@ namespace de4dot.blocks.cflow { return getValue(args, i); } - int index(ParameterDefinition arg) { - return arg.Sequence; + public Value getArg(Parameter arg) { + return getArg(arg.Number); } - public Value getArg(ParameterDefinition arg) { - return getArg(index(arg)); - } - - TypeReference getArgType(int index) { - index -= argBase; - if (0 <= index && index < parameterDefinitions.Count) - return parameterDefinitions[index].ParameterType; + TypeSig getArgType(int index) { + if (0 <= index && index < parameterDefs.Count) + return parameterDefs[index].Type; return null; } - public void setArg(ParameterDefinition arg, Value value) { - setArg(index(arg), value); + public void setArg(Parameter arg, Value value) { + setArg(arg.Number, value); } - public void makeArgUnknown(ParameterDefinition arg) { - setArg(arg, getUnknownArg(index(arg))); + public void makeArgUnknown(Parameter arg) { + setArg(arg, getUnknownArg(arg.Number)); } void setArg(int index, Value value) { @@ -203,26 +195,26 @@ namespace de4dot.blocks.cflow { return getValue(locals, i); } - public Value getLocal(VariableDefinition local) { - return getLocal(local.Index); + public Value getLocal(Local local) { + return getLocal(local.Number); } - public void setLocal(VariableDefinition local, Value value) { - setLocal(local.Index, value); + public void setLocal(Local local, Value value) { + setLocal(local.Number, value); } - public void makeLocalUnknown(VariableDefinition local) { - setLocal(local.Index, getUnknownLocal(local.Index)); + public void makeLocalUnknown(Local local) { + setLocal(local.Number, getUnknownLocal(local.Number)); } void setLocal(int index, Value value) { if (0 <= index && index < locals.Count) - locals[index] = truncateValue(value, variableDefinitions[index].VariableType); + locals[index] = truncateValue(value, localDefs[index].Type); } Value getUnknownLocal(int index) { - if (0 <= index && index < variableDefinitions.Count) - return getUnknownValue(variableDefinitions[index].VariableType); + if (0 <= index && index < localDefs.Count) + return getUnknownValue(localDefs[index].Type); return new UnknownValue(); } @@ -242,6 +234,7 @@ namespace de4dot.blocks.cflow { return valueStack.peek(); } +#if PORT public void emulate(IEnumerable instructions) { foreach (var instr in instructions) emulate(instr.Instruction); @@ -251,35 +244,36 @@ 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) { case Code.Starg: - case Code.Starg_S: emulate_Starg((ParameterDefinition)instr.Operand); break; + case Code.Starg_S: emulate_Starg((Parameter)instr.Operand); break; case Code.Stloc: - case Code.Stloc_S: emulate_Stloc(((VariableDefinition)instr.Operand).Index); break; + case Code.Stloc_S: emulate_Stloc(((Local)instr.Operand).Number); break; case Code.Stloc_0: emulate_Stloc(0); break; case Code.Stloc_1: emulate_Stloc(1); break; case Code.Stloc_2: emulate_Stloc(2); break; case Code.Stloc_3: emulate_Stloc(3); break; case Code.Ldarg: - case Code.Ldarg_S: valueStack.push(getArg((ParameterDefinition)instr.Operand)); break; + case Code.Ldarg_S: valueStack.push(getArg((Parameter)instr.Operand)); break; case Code.Ldarg_0: valueStack.push(getArg(0)); break; case Code.Ldarg_1: valueStack.push(getArg(1)); break; case Code.Ldarg_2: valueStack.push(getArg(2)); break; case Code.Ldarg_3: valueStack.push(getArg(3)); break; case Code.Ldloc: - case Code.Ldloc_S: valueStack.push(getLocal((VariableDefinition)instr.Operand)); break; + case Code.Ldloc_S: valueStack.push(getLocal((Local)instr.Operand)); break; case Code.Ldloc_0: valueStack.push(getLocal(0)); break; case Code.Ldloc_1: valueStack.push(getLocal(1)); break; case Code.Ldloc_2: valueStack.push(getLocal(2)); break; case Code.Ldloc_3: valueStack.push(getLocal(3)); break; case Code.Ldarga: - case Code.Ldarga_S: emulate_Ldarga((ParameterDefinition)instr.Operand); break; + case Code.Ldarga_S: emulate_Ldarga((Parameter)instr.Operand); break; case Code.Ldloca: - case Code.Ldloca_S: emulate_Ldloca(((VariableDefinition)instr.Operand).Index); break; + case Code.Ldloca_S: emulate_Ldloca(((Local)instr.Operand).Number); break; case Code.Dup: valueStack.copyTop(); break; @@ -369,7 +363,7 @@ namespace de4dot.blocks.cflow { case Code.Ldelem_U1: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt8()); break; case Code.Ldelem_U2: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt16()); break; case Code.Ldelem_U4: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break; - case Code.Ldelem_Any:valueStack.pop(2); valueStack.push(getUnknownValue(instr.Operand as TypeReference)); break; + case Code.Ldelem: valueStack.pop(2); valueStack.push(getUnknownValue(instr.Operand as ITypeDefOrRef)); break; case Code.Ldind_I1: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldind_I2: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; @@ -457,7 +451,6 @@ namespace de4dot.blocks.cflow { case Code.Mkrefany: case Code.Newarr: case Code.Newobj: - case Code.No: case Code.Nop: case Code.Pop: case Code.Readonly: @@ -465,7 +458,7 @@ namespace de4dot.blocks.cflow { case Code.Refanyval: case Code.Ret: case Code.Rethrow: - case Code.Stelem_Any: + case Code.Stelem: case Code.Stelem_I: case Code.Stelem_I1: case Code.Stelem_I2: @@ -486,7 +479,7 @@ namespace de4dot.blocks.cflow { case Code.Stobj: case Code.Stsfld: case Code.Switch: - case Code.Tail: + case Code.Tailcall: case Code.Throw: case Code.Unaligned: case Code.Volatile: @@ -498,7 +491,7 @@ namespace de4dot.blocks.cflow { void updateStack(Instruction instr) { int pushes, pops; - DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); + instr.CalculateStackUsage(out pushes, out pops); if (pops == -1) valueStack.clear(); else { @@ -847,15 +840,15 @@ namespace de4dot.blocks.cflow { valueStack.pushUnknown(); } - void emulate_Starg(ParameterDefinition arg) { - setArg(index(arg), valueStack.pop()); + void emulate_Starg(Parameter arg) { + setArg(arg.Number, valueStack.pop()); } void emulate_Stloc(int index) { setLocal(index, valueStack.pop()); } - void emulate_Ldarga(ParameterDefinition arg) { + void emulate_Ldarga(Parameter arg) { valueStack.pushUnknown(); makeArgUnknown(arg); } @@ -866,19 +859,19 @@ namespace de4dot.blocks.cflow { } void emulate_Call(Instruction instr) { - emulate_Call(instr, (MethodReference)instr.Operand); + emulate_Call(instr, (IMethod)instr.Operand); } void emulate_Callvirt(Instruction instr) { - emulate_Call(instr, (MethodReference)instr.Operand); + emulate_Call(instr, (IMethod)instr.Operand); } - void emulate_Call(Instruction instr, MethodReference method) { + void emulate_Call(Instruction instr, IMethod method) { int pushes, pops; - DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); + instr.CalculateStackUsage(out pushes, out pops); valueStack.pop(pops); if (pushes == 1) - valueStack.push(getUnknownValue(method.MethodReturnType.ReturnType)); + valueStack.push(getUnknownValue(method.MethodSig.RetType)); else valueStack.push(pushes); } @@ -903,16 +896,16 @@ namespace de4dot.blocks.cflow { void emulate_Ldfld(Instruction instr) { var val1 = valueStack.pop(); - emulateLoadField(instr.Operand as FieldReference); + emulateLoadField(instr.Operand as IField); } void emulate_Ldsfld(Instruction instr) { - emulateLoadField(instr.Operand as FieldReference); + emulateLoadField(instr.Operand as IField); } - void emulateLoadField(FieldReference fieldReference) { - if (fieldReference != null) - valueStack.push(getUnknownValue(fieldReference.FieldType)); + void emulateLoadField(IField field) { + if (field != null) + valueStack.push(getUnknownValue(field.FieldSig.Type)); else valueStack.pushUnknown(); } diff --git a/de4dot.code/ObfuscatedFile.cs b/de4dot.code/ObfuscatedFile.cs index 88b33c45..42892714 100644 --- a/de4dot.code/ObfuscatedFile.cs +++ b/de4dot.code/ObfuscatedFile.cs @@ -527,14 +527,18 @@ namespace de4dot.code { Log.v("Deobfuscating methods"); var methodPrinter = new MethodPrinter(); +#if PORT var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators); +#endif foreach (var method in getAllMethods()) { Log.v("Deobfuscating {0} ({1:X8})", Utils.removeNewlines(method), method.MetadataToken.ToUInt32()); Log.indent(); int oldIndentLevel = Log.indentLevel; try { +#if PORT deobfuscate(method, cflowDeobfuscator, methodPrinter); +#endif } catch (ApplicationException) { throw; @@ -569,6 +573,7 @@ namespace de4dot.code { } } +#if PORT void deobfuscate(MethodDefinition method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter) { if (!hasNonEmptyBody(method)) return; @@ -613,6 +618,7 @@ namespace de4dot.code { Log.deIndent(); } } +#endif bool hasNonEmptyBody(MethodDefinition method) { return method.HasBody && method.Body.Instructions.Count > 0; @@ -726,9 +732,11 @@ namespace de4dot.code { return; deobfuscate(method, "Deobfuscating control flow", (blocks) => { +#if PORT var cflowDeobfuscator = new BlocksCflowDeobfuscator(deob.BlocksDeobfuscators); cflowDeobfuscator.init(blocks); cflowDeobfuscator.deobfuscate(); +#endif }); } diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 074c942d..eb9089bf 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -57,166 +57,166 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - - - - - - - - - + + + + + + + + + + @@ -224,46 +224,46 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -341,6 +341,10 @@ {5C93C5E2-196F-4877-BF65-96FEBFCEFCA1} de4dot.mdecrypt + + {FDFC1237-143F-4919-8318-4926901F4639} + dot10 + diff --git a/de4dot.code/deobfuscators/ArrayFinder.cs b/de4dot.code/deobfuscators/ArrayFinder.cs index e15ddbc0..458afe8f 100644 --- a/de4dot.code/deobfuscators/ArrayFinder.cs +++ b/de4dot.code/deobfuscators/ArrayFinder.cs @@ -18,26 +18,26 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; using de4dot.blocks; using de4dot.blocks.cflow; namespace de4dot.code.deobfuscators { static class ArrayFinder { - public static List getArrays(MethodDefinition method) { + public static List getArrays(MethodDef method) { return getArrays(method, null); } - public static List getArrays(MethodDefinition method, TypeReference arrayElemntType) { + public static List getArrays(MethodDef method, IType arrayElementType) { var arrays = new List(); - var instrs = method.Body.Instructions; + var instrs = method.CilBody.Instructions; for (int i = 0; i < instrs.Count; i++) { - TypeReference type; + IType type; var ary = getArray(instrs, ref i, out type); if (ary == null) break; - if (arrayElemntType != null && !MemberReferenceHelper.compareTypes(type, arrayElemntType)) + if (arrayElementType != null && !new SigComparer().Equals(type, arrayElementType)) continue; arrays.Add(ary); @@ -45,7 +45,7 @@ namespace de4dot.code.deobfuscators { return arrays; } - public static byte[] getArray(IList instrs, ref int index, out TypeReference type) { + public static byte[] getArray(IList instrs, ref int index, out IType type) { for (int i = index; i < instrs.Count - 2; i++) { var newarr = instrs[i++]; if (newarr.OpCode.Code != Code.Newarr) @@ -57,12 +57,12 @@ namespace de4dot.code.deobfuscators { var ldtoken = instrs[i++]; if (ldtoken.OpCode.Code != Code.Ldtoken) continue; - var field = ldtoken.Operand as FieldDefinition; + var field = ldtoken.Operand as FieldDef; if (field == null || field.InitialValue == null) continue; index = i - 3; - type = newarr.Operand as TypeReference; + type = newarr.Operand as IType; return field.InitialValue; } @@ -71,14 +71,14 @@ namespace de4dot.code.deobfuscators { return null; } - public static byte[] getInitializedByteArray(MethodDefinition method, int arraySize) { + public static byte[] getInitializedByteArray(MethodDef method, int arraySize) { int newarrIndex = findNewarr(method, arraySize); if (newarrIndex < 0) return null; return getInitializedByteArray(arraySize, method, ref newarrIndex); } - public static byte[] getInitializedByteArray(int arraySize, MethodDefinition method, ref int newarrIndex) { + public static byte[] getInitializedByteArray(int arraySize, MethodDef method, ref int newarrIndex) { var resultValueArray = getInitializedArray(arraySize, method, ref newarrIndex, Code.Stelem_I1); var resultArray = new byte[resultValueArray.Length]; @@ -91,7 +91,7 @@ namespace de4dot.code.deobfuscators { return resultArray; } - public static short[] getInitializedInt16Array(int arraySize, MethodDefinition method, ref int newarrIndex) { + public static short[] getInitializedInt16Array(int arraySize, MethodDef method, ref int newarrIndex) { var resultValueArray = getInitializedArray(arraySize, method, ref newarrIndex, Code.Stelem_I2); var resultArray = new short[resultValueArray.Length]; @@ -104,7 +104,7 @@ namespace de4dot.code.deobfuscators { return resultArray; } - public static int[] getInitializedInt32Array(int arraySize, MethodDefinition method, ref int newarrIndex) { + public static int[] getInitializedInt32Array(int arraySize, MethodDef method, ref int newarrIndex) { var resultValueArray = getInitializedArray(arraySize, method, ref newarrIndex, Code.Stelem_I4); var resultArray = new int[resultValueArray.Length]; @@ -117,7 +117,7 @@ namespace de4dot.code.deobfuscators { return resultArray; } - public static uint[] getInitializedUInt32Array(int arraySize, MethodDefinition method, ref int newarrIndex) { + public static uint[] getInitializedUInt32Array(int arraySize, MethodDef method, ref int newarrIndex) { var resultArray = getInitializedInt32Array(arraySize, method, ref newarrIndex); if (resultArray == null) return null; @@ -128,14 +128,14 @@ namespace de4dot.code.deobfuscators { return ary; } - public static Value[] getInitializedArray(int arraySize, MethodDefinition method, ref int newarrIndex, Code stelemOpCode) { + public static Value[] getInitializedArray(int arraySize, MethodDef method, ref int newarrIndex, Code stelemOpCode) { var resultValueArray = new Value[arraySize]; var emulator = new InstructionEmulator(method); var theArray = new UnknownValue(); emulator.push(theArray); - var instructions = method.Body.Instructions; + var instructions = method.CilBody.Instructions; int i; for (i = newarrIndex + 1; i < instructions.Count; i++) { var instr = instructions[i]; @@ -183,7 +183,7 @@ done: return resultValueArray; } - static int findNewarr(MethodDefinition method, int arraySize) { + static int findNewarr(MethodDef method, int arraySize) { for (int i = 0; ; i++) { int size; if (!findNewarr(method, ref i, out size)) @@ -193,17 +193,17 @@ done: } } - public static bool findNewarr(MethodDefinition method, ref int i, out int size) { - var instructions = method.Body.Instructions; + public static bool findNewarr(MethodDef method, ref int i, out int size) { + var instructions = method.CilBody.Instructions; for (; i < instructions.Count; i++) { var instr = instructions[i]; if (instr.OpCode.Code != Code.Newarr || i < 1) continue; var ldci4 = instructions[i - 1]; - if (!DotNetUtils.isLdcI4(ldci4)) + if (!ldci4.IsLdcI4()) continue; - size = DotNetUtils.getLdcI4Value(ldci4); + size = ldci4.GetLdcI4Value(); return true; } diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs index 90f15741..8da39331 100644 --- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs +++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs @@ -95,6 +95,7 @@ namespace de4dot.code.deobfuscators { get { return Operations.DecryptStrings != OpDecryptString.None && staticStringInliner.InlinedAllCalls; } } +#if PORT public virtual IEnumerable BlocksDeobfuscators { get { var list = new List(); @@ -103,6 +104,7 @@ namespace de4dot.code.deobfuscators { return list; } } +#endif public DeobfuscatorBase(OptionsBase optionsBase) { this.optionsBase = optionsBase; @@ -821,7 +823,7 @@ namespace de4dot.code.deobfuscators { return false; } - public static int toInt32(bool b) { + protected static int toInt32(bool b) { return b ? 1 : 0; } } diff --git a/de4dot.code/deobfuscators/IDeobfuscator.cs b/de4dot.code/deobfuscators/IDeobfuscator.cs index e13fe2ec..47fde0aa 100644 --- a/de4dot.code/deobfuscators/IDeobfuscator.cs +++ b/de4dot.code/deobfuscators/IDeobfuscator.cs @@ -62,7 +62,9 @@ namespace de4dot.code.deobfuscators { StringFeatures StringFeatures { get; } RenamingOptions RenamingOptions { get; } DecrypterType DefaultDecrypterType { get; } +#if PORT IEnumerable BlocksDeobfuscators { get; } +#endif // This is non-null only in detect() and deobfuscateBegin(). IDeobfuscatedFile DeobfuscatedFile { get; set; } diff --git a/de4dot.cui/Program.cs b/de4dot.cui/Program.cs index 5a0a6c70..738a6fa8 100644 --- a/de4dot.cui/Program.cs +++ b/de4dot.cui/Program.cs @@ -37,6 +37,7 @@ namespace de4dot.cui { static IList createDeobfuscatorInfos() { return new List { new de4dot.code.deobfuscators.Unknown.DeobfuscatorInfo(), +#if PORT new de4dot.code.deobfuscators.Babel_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CliSecure.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeFort.DeobfuscatorInfo(), @@ -57,6 +58,7 @@ namespace de4dot.cui { new de4dot.code.deobfuscators.SmartAssembly.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Spices_Net.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Xenocode.DeobfuscatorInfo(), +#endif }; } diff --git a/dot10 b/dot10 index 80ac6ba4..c7a83ee8 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit 80ac6ba43c0ec9a044f850422415e3d2ad795d28 +Subproject commit c7a83ee87964d694a1e87ed9feb6cbc054226295 From 04e1568c61f0361ae2b6b43d2359a820fa5a9ef7 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 17:09:58 +0100 Subject: [PATCH 005/133] Port ConstantsReader --- de4dot.code/deobfuscators/ConstantsReader.cs | 65 +++++++++++--------- dot10 | 2 +- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/de4dot.code/deobfuscators/ConstantsReader.cs b/de4dot.code/deobfuscators/ConstantsReader.cs index c8642e81..c1c40002 100644 --- a/de4dot.code/deobfuscators/ConstantsReader.cs +++ b/de4dot.code/deobfuscators/ConstantsReader.cs @@ -18,18 +18,17 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Metadata; +using dot10.DotNet; +using dot10.DotNet.Emit; using de4dot.blocks; namespace de4dot.code.deobfuscators { class ConstantsReader { protected IInstructions instructions; - protected IList locals; - protected Dictionary localsValuesInt32 = new Dictionary(); - protected Dictionary localsValuesInt64 = new Dictionary(); - protected Dictionary localsValuesDouble = new Dictionary(); + protected IList locals; + protected Dictionary localsValuesInt32 = new Dictionary(); + protected Dictionary localsValuesInt64 = new Dictionary(); + protected Dictionary localsValuesDouble = new Dictionary(); bool emulateConvInstrs; public interface IInstructions { @@ -53,6 +52,7 @@ namespace de4dot.code.deobfuscators { } } +#if PORT class ListInstrs : IInstructions { IList instrs; @@ -68,6 +68,7 @@ namespace de4dot.code.deobfuscators { this.instrs = instrs; } } +#endif public bool EmulateConvInstructions { get { return emulateConvInstrs; } @@ -91,6 +92,7 @@ namespace de4dot.code.deobfuscators { : this(new ListInstructions(instrs), emulateConvInstrs) { } +#if PORT public ConstantsReader(IList instrs) : this(new ListInstrs(instrs)) { } @@ -98,34 +100,37 @@ namespace de4dot.code.deobfuscators { public ConstantsReader(IList instrs, bool emulateConvInstrs) : this(new ListInstrs(instrs), emulateConvInstrs) { } +#endif - public ConstantsReader(MethodDefinition method) - : this(method.Body.Instructions) { - this.locals = method.Body.Variables; + public ConstantsReader(MethodDef method) + : this(method.CilBody.Instructions) { + this.locals = method.CilBody.LocalList; } - public ConstantsReader(IList instrs, IList locals) +#if PORT + public ConstantsReader(IList instrs, IList locals) : this(instrs) { this.locals = locals; } +#endif - public void setConstantInt32(VariableDefinition local, int value) { + public void setConstantInt32(Local local, int value) { localsValuesInt32[local] = value; } - public void setConstantInt32(VariableDefinition local, uint value) { + public void setConstantInt32(Local local, uint value) { setConstantInt32(local, (int)value); } - public void setConstantInt64(VariableDefinition local, long value) { + public void setConstantInt64(Local local, long value) { localsValuesInt64[local] = value; } - public void setConstantInt64(VariableDefinition local, ulong value) { + public void setConstantInt64(Local local, ulong value) { setConstantInt64(local, (long)value); } - public void setConstantDouble(VariableDefinition local, double value) { + public void setConstantDouble(Local local, double value) { localsValuesDouble[local] = value; } @@ -143,13 +148,13 @@ namespace de4dot.code.deobfuscators { } public bool isLoadConstantInt32(Instruction instr) { - if (DotNetUtils.isLdcI4(instr)) + if (instr.IsLdcI4()) return true; - if (DotNetUtils.isLdloc(instr)) { + if (instr.IsLdloc()) { int tmp; return getLocalConstantInt32(instr, out tmp); } - if (DotNetUtils.isLdarg(instr)) { + if (instr.IsLdarg()) { int tmp; return getArgConstantInt32(instr, out tmp); } @@ -159,11 +164,11 @@ namespace de4dot.code.deobfuscators { public bool isLoadConstantInt64(Instruction instr) { if (instr.OpCode.Code == Code.Ldc_I8) return true; - if (DotNetUtils.isLdloc(instr)) { + if (instr.IsLdloc()) { long tmp; return getLocalConstantInt64(instr, out tmp); } - if (DotNetUtils.isLdarg(instr)) { + if (instr.IsLdarg()) { long tmp; return getArgConstantInt64(instr, out tmp); } @@ -173,11 +178,11 @@ namespace de4dot.code.deobfuscators { public bool isLoadConstantDouble(Instruction instr) { if (instr.OpCode.Code == Code.Ldc_R8) return true; - if (DotNetUtils.isLdloc(instr)) { + if (instr.IsLdloc()) { double tmp; return getLocalConstantDouble(instr, out tmp); } - if (DotNetUtils.isLdarg(instr)) { + if (instr.IsLdarg()) { double tmp; return getArgConstantDouble(instr, out tmp); } @@ -309,7 +314,7 @@ namespace de4dot.code.deobfuscators { case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_M1: - stack.Push(new ConstantInfo(index, DotNetUtils.getLdcI4Value(instr))); + stack.Push(new ConstantInfo(index, instr.GetLdcI4Value())); break; case Code.Add: @@ -698,10 +703,10 @@ done: value = 0; if (locals == null) return false; - var local = DotNetUtils.getLocalVar(locals, instr); + var local = instr.GetLocal(locals); if (local == null) return false; - if (local.VariableType.EType != ElementType.I4 && local.VariableType.EType != ElementType.U4) + if (local.Type.ElementType != ElementType.I4 && local.Type.ElementType != ElementType.U4) return false; return localsValuesInt32.TryGetValue(local, out value); } @@ -715,10 +720,10 @@ done: value = 0; if (locals == null) return false; - var local = DotNetUtils.getLocalVar(locals, instr); + var local = instr.GetLocal(locals); if (local == null) return false; - if (local.VariableType.EType != ElementType.I8 && local.VariableType.EType != ElementType.U8) + if (local.Type.ElementType != ElementType.I8 && local.Type.ElementType != ElementType.U8) return false; return localsValuesInt64.TryGetValue(local, out value); } @@ -732,10 +737,10 @@ done: value = 0; if (locals == null) return false; - var local = DotNetUtils.getLocalVar(locals, instr); + var local = instr.GetLocal(locals); if (local == null) return false; - if (local.VariableType.EType != ElementType.R8) + if (local.Type.ElementType != ElementType.R8) return false; return localsValuesDouble.TryGetValue(local, out value); } diff --git a/dot10 b/dot10 index c7a83ee8..ec483110 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit c7a83ee87964d694a1e87ed9feb6cbc054226295 +Subproject commit ec48311025fd4e9a56da7881857d90eaa0e3b5ca From 301a2fab97e1a38c8c7048463d1edd1b82b8c035 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 17:43:51 +0100 Subject: [PATCH 006/133] Port more code --- blocks/Block.cs | 4 ++-- blocks/Blocks.cs | 30 +++++++++++++++--------------- blocks/CodeGenerator.cs | 18 +++++++++--------- blocks/ForwardScanOrder.cs | 2 +- blocks/Instr.cs | 26 +++++++++++++------------- blocks/InstructionListParser.cs | 2 +- blocks/ScopeBlock.cs | 2 +- blocks/TryHandlerBlock.cs | 12 ++++++------ dot10 | 2 +- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/blocks/Block.cs b/blocks/Block.cs index 1142e016..73e1d748 100644 --- a/blocks/Block.cs +++ b/blocks/Block.cs @@ -19,7 +19,7 @@ using System; using System.Collections.Generic; -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks { public class Block : BaseBlock { @@ -269,7 +269,7 @@ namespace de4dot.blocks { for (int i = 0; i < instrs.Count; i++) { var instr = instrs[i]; if (instr.OpCode != OpCodes.Nop) - dest.Add(clone ? new Instr(DotNetUtils.clone(instr.Instruction)) : instr); + dest.Add(clone ? new Instr(instr.Instruction.Clone()) : instr); } } diff --git a/blocks/Blocks.cs b/blocks/Blocks.cs index 8b7afb0d..25800f79 100644 --- a/blocks/Blocks.cs +++ b/blocks/Blocks.cs @@ -19,35 +19,35 @@ using System; using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks { public class Blocks { - MethodDefinition method; - IList locals; + MethodDef method; + IList locals; MethodBlocks methodBlocks; public MethodBlocks MethodBlocks { get { return methodBlocks; } } - public IList Locals { + public IList Locals { get { return locals; } } - public MethodDefinition Method { + public MethodDef Method { get { return method; } } - public Blocks(MethodDefinition method) { + public Blocks(MethodDef method) { this.method = method; updateBlocks(); } public void updateBlocks() { - var body = method.Body; - locals = body.Variables; + var body = method.CilBody; + locals = body.LocalList; methodBlocks = new InstructionListParser(body.Instructions, body.ExceptionHandlers).parse(); } @@ -79,11 +79,11 @@ namespace de4dot.blocks { if (locals.Count == 0) return 0; - var usedLocals = new Dictionary>(); + var usedLocals = new Dictionary>(); foreach (var block in methodBlocks.getAllBlocks()) { for (int i = 0; i < block.Instructions.Count; i++) { var instr = block.Instructions[i]; - VariableDefinition local; + Local local; switch (instr.OpCode.Code) { case Code.Ldloc: case Code.Ldloc_S: @@ -102,7 +102,7 @@ namespace de4dot.blocks { case Code.Ldloca_S: case Code.Ldloca: - local = (VariableDefinition)instr.Operand; + local = (Local)instr.Operand; break; default: @@ -122,7 +122,7 @@ namespace de4dot.blocks { } int newIndex = -1; - var newLocals = new List(usedLocals.Count); + var newLocals = new List(usedLocals.Count); foreach (var local in usedLocals.Keys) { newIndex++; newLocals.Add(local); @@ -137,7 +137,7 @@ namespace de4dot.blocks { return numRemoved; } - static Instruction optimizeLocalInstr(Instr instr, VariableDefinition local, uint newIndex) { + static Instruction optimizeLocalInstr(Instr instr, Local local, uint newIndex) { switch (instr.OpCode.Code) { case Code.Ldloc: case Code.Ldloc_S: @@ -194,7 +194,7 @@ namespace de4dot.blocks { } catch (NullReferenceException) { //TODO: Send this message to the log - Console.WriteLine("Null ref exception! Invalid metadata token in code? Method: {0:X8}: {1}", method.MetadataToken.ToUInt32(), method.FullName); + Console.WriteLine("Null ref exception! Invalid metadata token in code? Method: {0:X8}: {1}", method.MDToken.Raw, method.FullName); return; } } diff --git a/blocks/CodeGenerator.cs b/blocks/CodeGenerator.cs index 1db3d945..04bf88cc 100644 --- a/blocks/CodeGenerator.cs +++ b/blocks/CodeGenerator.cs @@ -19,8 +19,8 @@ using System; using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks { class CodeGenerator { @@ -45,11 +45,11 @@ namespace de4dot.blocks { public int filterStart; public int handlerStart; public int handlerEnd; - public TypeReference catchType; - public ExceptionHandlerType handlerType; + public ITypeDefOrRef catchType; + public ExceptionClause handlerType; public ExceptionInfo(int tryStart, int tryEnd, int filterStart, - int handlerStart, int handlerEnd, TypeReference catchType, - ExceptionHandlerType handlerType) { + int handlerStart, int handlerEnd, ITypeDefOrRef catchType, + ExceptionClause handlerType) { if (tryStart > tryEnd || filterStart > handlerStart || tryStart < 0 || tryEnd < 0 || filterStart < 0 || handlerStart < 0 || handlerEnd < 0) throw new ApplicationException("Invalid start/end/filter/handler indexes"); @@ -99,10 +99,10 @@ namespace de4dot.blocks { } void recalculateInstructionOffsets(IList allInstructions) { - int offset = 0; + uint offset = 0; foreach (var instr in allInstructions) { instr.Offset = offset; - offset += instr.GetSize(); + offset += (uint)instr.GetSize(); } } @@ -137,7 +137,7 @@ namespace de4dot.blocks { if (getShortBranch(instruction, out opcode)) { const int instrSize = 5; // It's a long branch instruction var target = (Instruction)instruction.Operand; - int distance = target == null ? int.MaxValue : target.Offset - (instruction.Offset + instrSize); + int distance = target == null ? int.MaxValue : (int)(target.Offset - (instruction.Offset + instrSize)); if (-0x80 <= distance && distance <= 0x7F) { instruction.OpCode = opcode; changed = true; diff --git a/blocks/ForwardScanOrder.cs b/blocks/ForwardScanOrder.cs index 3ba0635d..5f4da69d 100644 --- a/blocks/ForwardScanOrder.cs +++ b/blocks/ForwardScanOrder.cs @@ -52,7 +52,7 @@ namespace de4dot.blocks { int stack = stackStart; foreach (var instr in block.Instructions) - DotNetUtils.updateStack(instr.Instruction, ref stack, false); + instr.Instruction.UpdateStack(ref stack, false); stackEnd = stack; } } diff --git a/blocks/Instr.cs b/blocks/Instr.cs index 536a9c9c..9afb9c27 100644 --- a/blocks/Instr.cs +++ b/blocks/Instr.cs @@ -18,8 +18,8 @@ */ using System; -using Mono.Cecil.Cil; using System.Collections.Generic; +using dot10.DotNet.Emit; namespace de4dot.blocks { public class Instr { @@ -44,8 +44,8 @@ namespace de4dot.blocks { // Returns the variable or null if it's not a ldloc/stloc instruction. It does not return // a local variable if it's a ldloca/ldloca.s instruction. - public static VariableDefinition getLocalVar(IList locals, Instr instr) { - return DotNetUtils.getLocalVar(locals, instr.Instruction); + public static Local getLocalVar(IList locals, Instr instr) { + return instr.Instruction.GetLocal(locals); } static public bool isFallThrough(OpCode opCode) { @@ -104,23 +104,23 @@ namespace de4dot.blocks { } public bool isLdcI4() { - return DotNetUtils.isLdcI4(OpCode.Code); + return instruction.IsLdcI4(); } public int getLdcI4Value() { - return DotNetUtils.getLdcI4Value(instruction); + return instruction.GetLdcI4Value(); } public bool isLdarg() { - return DotNetUtils.isLdarg(instruction); + return instruction.IsLdarg(); } public bool isStloc() { - return DotNetUtils.isStloc(instruction); + return instruction.IsStloc(); } public bool isLdloc() { - return DotNetUtils.isLdloc(instruction); + return instruction.IsLdloc(); } public bool isNop() { @@ -132,23 +132,23 @@ namespace de4dot.blocks { } public bool isLeave() { - return DotNetUtils.isLeave(instruction); + return instruction.IsLeave(); } public bool isBr() { - return DotNetUtils.isBr(instruction); + return instruction.IsBr(); } public bool isBrfalse() { - return DotNetUtils.isBrfalse(instruction); + return instruction.IsBrfalse(); } public bool isBrtrue() { - return DotNetUtils.isBrtrue(instruction); + return instruction.IsBrtrue(); } public bool isConditionalBranch() { - return DotNetUtils.isConditionalBranch(OpCode.Code); + return instruction.IsConditionalBranch(); } public bool getFlippedBranchOpCode(out OpCode opcode) { diff --git a/blocks/InstructionListParser.cs b/blocks/InstructionListParser.cs index 33288f03..82de56e3 100644 --- a/blocks/InstructionListParser.cs +++ b/blocks/InstructionListParser.cs @@ -19,7 +19,7 @@ using System; using System.Collections.Generic; -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks { class InstructionListParser { diff --git a/blocks/ScopeBlock.cs b/blocks/ScopeBlock.cs index 2ca81c95..677bd4b8 100644 --- a/blocks/ScopeBlock.cs +++ b/blocks/ScopeBlock.cs @@ -19,7 +19,7 @@ using System; using System.Collections.Generic; -using Mono.Cecil.Cil; +using dot10.DotNet.Emit; namespace de4dot.blocks { // A normal branch may not transfer out of a protected block (try block), filter handler, diff --git a/blocks/TryHandlerBlock.cs b/blocks/TryHandlerBlock.cs index 1fc7b5b8..a2e8bf9e 100644 --- a/blocks/TryHandlerBlock.cs +++ b/blocks/TryHandlerBlock.cs @@ -17,8 +17,8 @@ along with de4dot. If not, see . */ -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; namespace de4dot.blocks { // Contains the filter handler block and the catch handler block. @@ -27,14 +27,14 @@ namespace de4dot.blocks { HandlerBlock handlerBlock = new HandlerBlock(); // State for an ExceptionHandler instance - TypeReference catchType; - ExceptionHandlerType handlerType; + ITypeDefOrRef catchType; + ExceptionClause handlerType; - public TypeReference CatchType { + public ITypeDefOrRef CatchType { get { return catchType; } } - public ExceptionHandlerType HandlerType { + public ExceptionClause HandlerType { get { return handlerType; } } diff --git a/dot10 b/dot10 index ec483110..526604c8 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit ec48311025fd4e9a56da7881857d90eaa0e3b5ca +Subproject commit 526604c81df777accde4e45327cffcba954c356c From 8022a445a9af3a9770b5064af3af8a24944da320 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 18:52:50 +0100 Subject: [PATCH 007/133] Port the remaining classes in blocks --- blocks/DotNetUtils.cs | 64 +++++++++++++++++++++ blocks/FilterHandlerBlock.cs | 2 - blocks/ForwardScanOrder.cs | 2 - blocks/HandlerBlock.cs | 2 - blocks/blocks.csproj | 32 +++++------ blocks/cflow/BlockCflowDeobfuscator.cs | 4 +- blocks/cflow/BlocksCflowDeobfuscator.cs | 3 +- blocks/cflow/BranchEmulator.cs | 2 +- blocks/cflow/CachedCflowDeobfuscator.cs | 12 ++-- blocks/cflow/CflowDeobfuscator.cs | 12 ++-- blocks/cflow/ConstantsFolder.cs | 18 +++--- blocks/cflow/DeadCodeRemover.cs | 11 ++-- blocks/cflow/DeadStoreRemover.cs | 8 +-- blocks/cflow/ICflowDeobfuscator.cs | 4 +- blocks/cflow/InstructionEmulator.cs | 4 -- blocks/cflow/MethodCallInliner.cs | 20 +++---- blocks/cflow/MethodCallInlinerBase.cs | 74 ++++++++++++++----------- blocks/cflow/StLdlocFixer.cs | 7 ++- blocks/cflow/SwitchCflowDeobfuscator.cs | 17 +++--- dot10 | 2 +- 20 files changed, 181 insertions(+), 119 deletions(-) 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 From 2e0aa36362e0e267ad2b22b5bc11ffa79d4cc906 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 21:07:57 +0100 Subject: [PATCH 008/133] Fix more code in blocks --- blocks/DotNetUtils.cs | 6 +- blocks/MemberDefDict.cs | 736 ++++++++++++++++++++++++++++++++ blocks/MemberReferenceHelper.cs | 48 ++- blocks/Utils.cs | 21 +- blocks/blocks.csproj | 1 + dot10 | 2 +- 6 files changed, 786 insertions(+), 28 deletions(-) create mode 100644 blocks/MemberDefDict.cs diff --git a/blocks/DotNetUtils.cs b/blocks/DotNetUtils.cs index dead4b31..740beb2e 100644 --- a/blocks/DotNetUtils.cs +++ b/blocks/DotNetUtils.cs @@ -39,7 +39,7 @@ namespace de4dot.blocks { class TypeCache { ModuleDefinition module; - TypeDefinitionDict typeRefToDef = new TypeDefinitionDict(); + de4dot.blocks.OLD_REMOVE.TypeDefinitionDict typeRefToDef = new de4dot.blocks.OLD_REMOVE.TypeDefinitionDict(); public TypeCache(ModuleDefinition module) { this.module = module; @@ -83,11 +83,11 @@ namespace de4dot.blocks { } public class CallCounter { - Dictionary calls = new Dictionary(); + Dictionary calls = new Dictionary(); public void add(MethodReference calledMethod) { int count; - var key = new MethodReferenceAndDeclaringTypeKey(calledMethod); + var key = new de4dot.blocks.OLD_REMOVE.MethodReferenceAndDeclaringTypeKey(calledMethod); calls.TryGetValue(key, out count); calls[key] = count + 1; } diff --git a/blocks/MemberDefDict.cs b/blocks/MemberDefDict.cs new file mode 100644 index 00000000..5f6d8059 --- /dev/null +++ b/blocks/MemberDefDict.cs @@ -0,0 +1,736 @@ +/* + Copyright (C) 2011-2012 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 dot10.DotNet; + +namespace de4dot.blocks { + public class TypeDefinitionDict { + Dictionary tokenToValue = new Dictionary(); + Dictionary tokenToKey = new Dictionary(); + Dictionary refToValue = new Dictionary(TypeEqualityComparer.Instance); + Dictionary refToKey = new Dictionary(); + + public int Count { + get { return tokenToValue.Count; } + } + + public IEnumerable getKeys() { + return tokenToKey.Values; + } + + public IEnumerable getValues() { + return tokenToValue.Values; + } + + ScopeAndTokenKey getTokenKey(TypeDef typeDef) { + return new ScopeAndTokenKey(typeDef); + } + + public TValue find(IType typeRef) { + TValue value; + var typeDef = typeRef as TypeDef; + if (typeDef != null) + tokenToValue.TryGetValue(getTokenKey(typeDef), out value); + else if (typeRef != null) + refToValue.TryGetValue(typeRef, out value); + else + value = default(TValue); + return value; + } + + public TValue findAny(IType type) { + TValue value; + var typeDef = type as TypeDef; + if (typeDef != null && tokenToValue.TryGetValue(getTokenKey(typeDef), out value)) + return value; + + refToValue.TryGetValue(type, out value); + return value; + } + + public void add(TypeDef typeDef, TValue value) { + var tokenKey = getTokenKey(typeDef); + tokenToValue[tokenKey] = value; + tokenToKey[tokenKey] = typeDef; + + if (!refToValue.ContainsKey(typeDef) || + getAccessibilityOrder(typeDef) < getAccessibilityOrder(refToKey[typeDef])) { + refToKey[typeDef] = typeDef; + refToValue[typeDef] = value; + } + } + + // Order: public, family, assembly, private + static int[] accessibilityOrder = new int[8] { + 40, // NotPublic + 0, // Public + 10, // NestedPublic + 70, // NestedPrivate + 20, // NestedFamily + 50, // NestedAssembly + 60, // NestedFamANDAssem + 30, // NestedFamORAssem + }; + static int getAccessibilityOrder(TypeDef typeDef) { + return accessibilityOrder[(int)typeDef.Flags & 7]; + } + + public void onTypesRenamed() { + var newTypeRefToValue = new Dictionary(refToValue.Count); + foreach (var kvp in refToValue) + newTypeRefToValue[kvp.Key] = kvp.Value; + refToValue = newTypeRefToValue; + } + } + + public abstract class FieldDefinitionDictBase { + Dictionary tokenToValue = new Dictionary(); + Dictionary tokenToKey = new Dictionary(); + Dictionary refToValue = new Dictionary(); + Dictionary refToKey = new Dictionary(); + + public int Count { + get { return tokenToValue.Count; } + } + + public IEnumerable getKeys() { + return tokenToKey.Values; + } + + public IEnumerable getValues() { + return tokenToValue.Values; + } + + ScopeAndTokenKey getTokenKey(FieldDef fieldDef) { + return new ScopeAndTokenKey(fieldDef); + } + + protected abstract IFieldReferenceKey getReferenceKey(IField fieldRef); + + public TValue find(IField fieldRef) { + TValue value; + var fieldDef = fieldRef as FieldDef; + if (fieldDef != null) + tokenToValue.TryGetValue(getTokenKey(fieldDef), out value); + else + refToValue.TryGetValue(getReferenceKey(fieldRef), out value); + return value; + } + + public TValue findAny(IField fieldRef) { + TValue value; + var fieldDef = fieldRef as FieldDef; + if (fieldDef != null && tokenToValue.TryGetValue(getTokenKey(fieldDef), out value)) + return value; + + refToValue.TryGetValue(getReferenceKey(fieldRef), out value); + return value; + } + + public void add(FieldDef fieldDef, TValue value) { + var tokenKey = getTokenKey(fieldDef); + tokenToValue[tokenKey] = value; + tokenToKey[tokenKey] = fieldDef; + + var refKey = getReferenceKey(fieldDef); + if (!refToValue.ContainsKey(refKey) || + getAccessibilityOrder(fieldDef) < getAccessibilityOrder(refToKey[refKey])) { + refToKey[refKey] = fieldDef; + refToValue[refKey] = value; + } + } + + // Order: public, family, assembly, private + static int[] accessibilityOrder = new int[8] { + 60, // CompilerControlled + 50, // Private + 40, // FamANDAssem + 30, // Assembly + 10, // Family + 20, // FamORAssem + 0, // Public + 70, // + }; + static int getAccessibilityOrder(FieldDef fieldDefinition) { + return accessibilityOrder[(int)fieldDefinition.Flags & 7]; + } + + public void onTypesRenamed() { + var newFieldRefToDef = new Dictionary(refToValue.Count); + foreach (var kvp in refToValue) + newFieldRefToDef[getReferenceKey((FieldDef)kvp.Key.FieldReference)] = kvp.Value; + refToValue = newFieldRefToDef; + } + } + + public class FieldDefinitionDict : FieldDefinitionDictBase { + protected override IFieldReferenceKey getReferenceKey(IField fieldRef) { + return new FieldReferenceKey(fieldRef); + } + } + + public class FieldDefinitionAndDeclaringTypeDict : FieldDefinitionDictBase { + protected override IFieldReferenceKey getReferenceKey(IField fieldRef) { + return new FieldReferenceAndDeclaringTypeKey(fieldRef); + } + } + + public abstract class MethodDefinitionDictBase { + Dictionary tokenToValue = new Dictionary(); + Dictionary tokenToKey = new Dictionary(); + Dictionary refToValue = new Dictionary(); + Dictionary refToKey = new Dictionary(); + + public int Count { + get { return tokenToValue.Count; } + } + + public IEnumerable getKeys() { + return tokenToKey.Values; + } + + public IEnumerable getValues() { + return tokenToValue.Values; + } + + ScopeAndTokenKey getTokenKey(MethodDef methodDef) { + return new ScopeAndTokenKey(methodDef); + } + + protected abstract IMethodReferenceKey getReferenceKey(IMethod methodRef); + + public TValue find(IMethod methodRef) { + TValue value; + var methodDef = methodRef as MethodDef; + if (methodDef != null) + tokenToValue.TryGetValue(getTokenKey(methodDef), out value); + else + refToValue.TryGetValue(getReferenceKey(methodRef), out value); + return value; + } + + public TValue findAny(IMethod methodRef) { + TValue value; + var methodDef = methodRef as MethodDef; + if (methodDef != null && tokenToValue.TryGetValue(getTokenKey(methodDef), out value)) + return value; + + refToValue.TryGetValue(getReferenceKey(methodRef), out value); + return value; + } + + public void add(MethodDef methodDef, TValue value) { + var tokenKey = getTokenKey(methodDef); + tokenToValue[tokenKey] = value; + tokenToKey[tokenKey] = methodDef; + + var refKey = getReferenceKey(methodDef); + if (!refToValue.ContainsKey(refKey) || + getAccessibilityOrder(methodDef) < getAccessibilityOrder(refToKey[refKey])) { + refToKey[refKey] = methodDef; + refToValue[refKey] = value; + } + } + + // Order: public, family, assembly, private + static int[] accessibilityOrder = new int[8] { + 60, // CompilerControlled + 50, // Private + 40, // FamANDAssem + 30, // Assembly + 10, // Family + 20, // FamORAssem + 0, // Public + 70, // + }; + static int getAccessibilityOrder(MethodDef methodDefinition) { + return accessibilityOrder[(int)methodDefinition.Flags & 7]; + } + + public void onTypesRenamed() { + var newFieldRefToDef = new Dictionary(refToValue.Count); + foreach (var kvp in refToValue) + newFieldRefToDef[getReferenceKey((MethodDef)kvp.Key.MethodReference)] = kvp.Value; + refToValue = newFieldRefToDef; + } + } + + public class MethodDefinitionDict : MethodDefinitionDictBase { + protected override IMethodReferenceKey getReferenceKey(IMethod methodRef) { + return new MethodReferenceKey(methodRef); + } + } + + public class MethodDefinitionAndDeclaringTypeDict : MethodDefinitionDictBase { + protected override IMethodReferenceKey getReferenceKey(IMethod methodRef) { + return new MethodReferenceAndDeclaringTypeKey(methodRef); + } + } + + public abstract class EventDefinitionDictBase { + Dictionary tokenToValue = new Dictionary(); + Dictionary tokenToKey = new Dictionary(); + Dictionary refToValue = new Dictionary(); + + public int Count { + get { return tokenToValue.Count; } + } + + public IEnumerable getKeys() { + return tokenToKey.Values; + } + + public IEnumerable getValues() { + return tokenToValue.Values; + } + + ScopeAndTokenKey getTokenKey(EventDef eventReference) { + return new ScopeAndTokenKey(eventReference); + } + + protected abstract IEventReferenceKey getReferenceKey(EventDef eventRef); + + public TValue find(EventDef eventRef) { + TValue value; + tokenToValue.TryGetValue(getTokenKey(eventRef), out value); + return value; + } + + public TValue findAny(EventDef eventRef) { + TValue value; + if (tokenToValue.TryGetValue(getTokenKey(eventRef), out value)) + return value; + + refToValue.TryGetValue(getReferenceKey(eventRef), out value); + return value; + } + + public void add(EventDef eventDef, TValue value) { + var tokenKey = getTokenKey(eventDef); + tokenToValue[tokenKey] = value; + tokenToKey[tokenKey] = eventDef; + + refToValue[getReferenceKey(eventDef)] = value; + } + + public void onTypesRenamed() { + var newFieldRefToDef = new Dictionary(refToValue.Count); + foreach (var kvp in refToValue) + newFieldRefToDef[getReferenceKey((EventDef)kvp.Key.EventDef)] = kvp.Value; + refToValue = newFieldRefToDef; + } + } + + public class EventDefinitionDict : EventDefinitionDictBase { + protected override IEventReferenceKey getReferenceKey(EventDef eventRef) { + return new EventReferenceKey(eventRef); + } + } + + public class EventDefinitionAndDeclaringTypeDict : EventDefinitionDictBase { + protected override IEventReferenceKey getReferenceKey(EventDef eventRef) { + return new EventReferenceAndDeclaringTypeKey(eventRef); + } + } + + public abstract class PropertyDefinitionDictBase { + Dictionary tokenToValue = new Dictionary(); + Dictionary tokenToKey = new Dictionary(); + Dictionary refToValue = new Dictionary(); + + public int Count { + get { return tokenToValue.Count; } + } + + public IEnumerable getKeys() { + return tokenToKey.Values; + } + + public IEnumerable getValues() { + return tokenToValue.Values; + } + + ScopeAndTokenKey getTokenKey(PropertyDef propertyReference) { + return new ScopeAndTokenKey(propertyReference); + } + + protected abstract IPropertyReferenceKey getReferenceKey(PropertyDef propertyReference); + + public TValue find(PropertyDef propRef) { + TValue value; + tokenToValue.TryGetValue(getTokenKey(propRef), out value); + return value; + } + + public TValue findAny(PropertyDef propRef) { + TValue value; + if (tokenToValue.TryGetValue(getTokenKey(propRef), out value)) + return value; + + refToValue.TryGetValue(getReferenceKey(propRef), out value); + return value; + } + + public void add(PropertyDef propDef, TValue value) { + var tokenKey = getTokenKey(propDef); + tokenToValue[tokenKey] = value; + tokenToKey[tokenKey] = propDef; + + refToValue[getReferenceKey(propDef)] = value; + } + + public void onTypesRenamed() { + var newFieldRefToDef = new Dictionary(refToValue.Count); + foreach (var kvp in refToValue) + newFieldRefToDef[getReferenceKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value; + refToValue = newFieldRefToDef; + } + } + + public class PropertyDefinitionDict : PropertyDefinitionDictBase { + protected override IPropertyReferenceKey getReferenceKey(PropertyDef propRef) { + return new PropertyReferenceKey(propRef); + } + } + + public class PropertyDefinitionAndDeclaringTypeDict : PropertyDefinitionDictBase { + protected override IPropertyReferenceKey getReferenceKey(PropertyDef propRef) { + return new PropertyReferenceAndDeclaringTypeKey(propRef); + } + } + + public class ScopeAndTokenKey { + readonly IScope scope; + readonly uint token; + + public ScopeAndTokenKey(TypeDef type) + : this(type.OwnerModule, type.MDToken.Raw) { + } + + public ScopeAndTokenKey(FieldDef field) + : this(field.DeclaringType == null ? null : field.DeclaringType.OwnerModule, field.MDToken.Raw) { + } + + public ScopeAndTokenKey(MethodDef method) + : this(method.DeclaringType == null ? null : method.DeclaringType.OwnerModule, method.MDToken.Raw) { + } + + public ScopeAndTokenKey(PropertyDef prop) + : this(prop.DeclaringType == null ? null : prop.DeclaringType.OwnerModule, prop.MDToken.Raw) { + } + + public ScopeAndTokenKey(EventDef evt) + : this(evt.DeclaringType == null ? null : evt.DeclaringType.OwnerModule, evt.MDToken.Raw) { + } + + public ScopeAndTokenKey(IScope scope, uint token) { + this.scope = scope; + this.token = token; + } + + public override int GetHashCode() { + return (int)token + GetHashCode(scope); + } + + public override bool Equals(object obj) { + var other = obj as ScopeAndTokenKey; + if (other == null) + return false; + return token == other.token && + Equals(scope, other.scope); + } + + public override string ToString() { + return string.Format("{0:X8} {1}", token, scope); + } + + static bool Equals(IScope a, IScope b) { + if (a == b) + return true; + if (a == null || b == null) + return false; + return getCanonicalizedScopeName(a) == getCanonicalizedScopeName(b); + } + + static int GetHashCode(IScope a) { + if (a == null) + return 0; + return getCanonicalizedScopeName(a).GetHashCode(); + } + + static string getAssemblyName(IScope a) { + switch (a.ScopeType) { + case ScopeType.AssemblyRef: + return ((AssemblyRef)a).Name.String; + case ScopeType.ModuleDef: + var asm = ((ModuleDef)a).Assembly; + if (asm != null) + return asm.Name.String; + break; + } + return null; + } + + static string getCanonicalizedScopeName(IScope a) { + if (a == null) + return string.Empty; + var asmName = getAssemblyName(a); + if (asmName != null) { + // The version number should be ignored. Older code may reference an old version of + // the assembly, but if the newer one has been loaded, that one is used. + return asmName.ToUpperInvariant(); + } + return a.ScopeName.ToUpperInvariant(); + } + } + + public interface IFieldReferenceKey { + IField FieldReference { get; } + } + + public interface IMethodReferenceKey { + IMethod MethodReference { get; } + } + + public interface IEventReferenceKey { + EventDef EventDef { get; } + } + + public interface IPropertyReferenceKey { + PropertyDef PropertyDef { get; } + } + + public class FieldReferenceKey : IFieldReferenceKey { + readonly IField fieldRef; + + public IField FieldReference { + get { return fieldRef; } + } + + public FieldReferenceKey(IField fieldRef) { + this.fieldRef = fieldRef; + } + + public override int GetHashCode() { + return new SigComparer().GetHashCode(fieldRef); + } + + public override bool Equals(object obj) { + var other = obj as FieldReferenceKey; + if (other == null) + return false; + return new SigComparer().Equals(fieldRef, other.fieldRef); + } + + public override string ToString() { + return fieldRef.ToString(); + } + } + + public class MethodReferenceKey : IMethodReferenceKey { + readonly IMethod methodRef; + + public IMethod MethodReference { + get { return methodRef; } + } + + public MethodReferenceKey(IMethod methodRef) { + this.methodRef = methodRef; + } + + public override int GetHashCode() { + return new SigComparer().GetHashCode(methodRef); + } + + public override bool Equals(object obj) { + var other = obj as MethodReferenceKey; + if (other == null) + return false; + return new SigComparer().Equals(methodRef, other.methodRef); + } + + public override string ToString() { + return methodRef.ToString(); + } + } + + public class FieldReferenceAndDeclaringTypeKey : IFieldReferenceKey { + readonly IField fieldRef; + + public IField FieldReference { + get { return fieldRef; } + } + + public FieldReferenceAndDeclaringTypeKey(IField fieldRef) { + this.fieldRef = fieldRef; + } + + public override int GetHashCode() { + return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).GetHashCode(fieldRef); + } + + public override bool Equals(object obj) { + var other = obj as FieldReferenceAndDeclaringTypeKey; + if (other == null) + return false; + return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(fieldRef, other.fieldRef); + } + + public override string ToString() { + return fieldRef.ToString(); + } + } + + public class MethodReferenceAndDeclaringTypeKey : IMethodReferenceKey { + readonly IMethod methodRef; + + public IMethod MethodReference { + get { return methodRef; } + } + + public MethodReferenceAndDeclaringTypeKey(IMethod methodRef) { + this.methodRef = methodRef; + } + + public override int GetHashCode() { + return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).GetHashCode(methodRef); + } + + public override bool Equals(object obj) { + var other = obj as MethodReferenceAndDeclaringTypeKey; + if (other == null) + return false; + return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(methodRef, other.methodRef); + } + + public override string ToString() { + return methodRef.ToString(); + } + } + + public class EventReferenceKey : IEventReferenceKey { + readonly EventDef eventRef; + + public EventDef EventDef { + get { return eventRef; } + } + + public EventReferenceKey(EventDef eventRef) { + this.eventRef = eventRef; + } + + public override int GetHashCode() { + return new SigComparer().GetHashCode(eventRef); + } + + public override bool Equals(object obj) { + var other = obj as EventReferenceKey; + if (other == null) + return false; + return new SigComparer().Equals(eventRef, other.eventRef); + } + + public override string ToString() { + return eventRef.ToString(); + } + } + + public class EventReferenceAndDeclaringTypeKey : IEventReferenceKey { + readonly EventDef eventRef; + + public EventDef EventDef { + get { return eventRef; } + } + + public EventReferenceAndDeclaringTypeKey(EventDef eventRef) { + this.eventRef = eventRef; + } + + public override int GetHashCode() { + return new SigComparer(SigComparerOptions.CompareEventDeclaringType).GetHashCode(eventRef); + } + + public override bool Equals(object obj) { + var other = obj as EventReferenceAndDeclaringTypeKey; + if (other == null) + return false; + return new SigComparer(SigComparerOptions.CompareEventDeclaringType).Equals(eventRef, other.eventRef); + } + + public override string ToString() { + return eventRef.ToString(); + } + } + + public class PropertyReferenceKey : IPropertyReferenceKey { + readonly PropertyDef propRef; + + public PropertyDef PropertyDef { + get { return propRef; } + } + + public PropertyReferenceKey(PropertyDef propRef) { + this.propRef = propRef; + } + + public override int GetHashCode() { + return new SigComparer().GetHashCode(propRef); + } + + public override bool Equals(object obj) { + var other = obj as PropertyReferenceKey; + if (other == null) + return false; + return new SigComparer().Equals(propRef, other.propRef); + } + + public override string ToString() { + return propRef.ToString(); + } + } + + public class PropertyReferenceAndDeclaringTypeKey : IPropertyReferenceKey { + readonly PropertyDef propRef; + + public PropertyDef PropertyDef { + get { return propRef; } + } + + public PropertyReferenceAndDeclaringTypeKey(PropertyDef propRef) { + this.propRef = propRef; + } + + public override int GetHashCode() { + return new SigComparer(SigComparerOptions.ComparePropertyDeclaringType).GetHashCode(propRef); + } + + public override bool Equals(object obj) { + var other = obj as PropertyReferenceAndDeclaringTypeKey; + if (other == null) + return false; + return new SigComparer(SigComparerOptions.ComparePropertyDeclaringType).Equals(propRef, other.propRef); + } + + public override string ToString() { + return propRef.ToString(); + } + } +} diff --git a/blocks/MemberReferenceHelper.cs b/blocks/MemberReferenceHelper.cs index 7a33691a..4a7c323d 100644 --- a/blocks/MemberReferenceHelper.cs +++ b/blocks/MemberReferenceHelper.cs @@ -22,29 +22,7 @@ using System.Collections.Generic; using Mono.Cecil; using Mono.Cecil.Metadata; -namespace de4dot.blocks { - public enum CecilType { - ArrayType, - ByReferenceType, - EventDefinition, - FieldDefinition, - FieldReference, - FunctionPointerType, - GenericInstanceMethod, - GenericInstanceType, - GenericParameter, - MethodDefinition, - MethodReference, - OptionalModifierType, - PinnedType, - PointerType, - PropertyDefinition, - RequiredModifierType, - SentinelType, - TypeDefinition, - TypeReference, - } - +namespace de4dot.blocks.OLD_REMOVE { public class TypeDefinitionDict { Dictionary tokenToValue = new Dictionary(); Dictionary tokenToKey = new Dictionary(); @@ -782,6 +760,30 @@ namespace de4dot.blocks { return methodRef.ToString(); } } +} + +namespace de4dot.blocks { + public enum CecilType { + ArrayType, + ByReferenceType, + EventDefinition, + FieldDefinition, + FieldReference, + FunctionPointerType, + GenericInstanceMethod, + GenericInstanceType, + GenericParameter, + MethodDefinition, + MethodReference, + OptionalModifierType, + PinnedType, + PointerType, + PropertyDefinition, + RequiredModifierType, + SentinelType, + TypeDefinition, + TypeReference, + } public static class MemberReferenceHelper { static Dictionary typeToCecilTypeDict = new Dictionary(); diff --git a/blocks/Utils.cs b/blocks/Utils.cs index da1d63ca..ab5b7ad5 100644 --- a/blocks/Utils.cs +++ b/blocks/Utils.cs @@ -1,4 +1,23 @@ -using System.Collections.Generic; +/* + Copyright (C) 2011-2012 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.Collections.Generic; namespace de4dot.blocks { internal delegate TResult Func(); diff --git a/blocks/blocks.csproj b/blocks/blocks.csproj index 05726682..7d7a2f48 100644 --- a/blocks/blocks.csproj +++ b/blocks/blocks.csproj @@ -68,6 +68,7 @@ + diff --git a/dot10 b/dot10 index e543043a..d6f36e4d 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit e543043aff5f9f14484038d0d7bb3850b8d1d2c9 +Subproject commit d6f36e4d8d75354483f57a4808dd0e2fe75c94aa From 8d87fa02bcf0b0865b4973af9eac872e9bcab2a6 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 31 Oct 2012 22:44:54 +0100 Subject: [PATCH 009/133] Port more code --- AssemblyData/AssemblyData.csproj | 4 + .../methodsrewriter/AssemblyResolver.cs | 42 ++-- AssemblyData/methodsrewriter/CodeGenerator.cs | 32 +-- .../methodsrewriter/IMethodsRewriter.cs | 1 - AssemblyData/methodsrewriter/MField.cs | 10 +- AssemblyData/methodsrewriter/MMethod.cs | 12 +- AssemblyData/methodsrewriter/MModule.cs | 52 ++--- AssemblyData/methodsrewriter/MType.cs | 34 +-- .../methodsrewriter/MethodsRewriter.cs | 57 +++-- AssemblyData/methodsrewriter/Resolver.cs | 156 +++++++------- AssemblyData/methodsrewriter/ResolverUtils.cs | 196 ++---------------- .../methodsrewriter/TypeInstanceResolver.cs | 28 +-- AssemblyData/methodsrewriter/TypeResolver.cs | 19 +- dot10 | 2 +- 14 files changed, 243 insertions(+), 402 deletions(-) diff --git a/AssemblyData/AssemblyData.csproj b/AssemblyData/AssemblyData.csproj index 0a917298..2a16b332 100644 --- a/AssemblyData/AssemblyData.csproj +++ b/AssemblyData/AssemblyData.csproj @@ -78,6 +78,10 @@ {5C93C5E2-196F-4877-BF65-96FEBFCEFCA1} de4dot.mdecrypt + + {FDFC1237-143F-4919-8318-4926901F4639} + dot10 +