From 88d1a8ab89c44fdc39f5657504e733703e08ab0e Mon Sep 17 00:00:00 2001 From: de4dot Date: Fri, 14 Dec 2012 12:39:06 +0100 Subject: [PATCH] Inline generic methods that DS added --- blocks/cflow/MethodCallInlinerBase.cs | 20 ++++++++++++- .../DeepSea/DsMethodCallInliner.cs | 30 +++++++++++++++---- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/blocks/cflow/MethodCallInlinerBase.cs b/blocks/cflow/MethodCallInlinerBase.cs index f81baba2..5f4537a2 100644 --- a/blocks/cflow/MethodCallInlinerBase.cs +++ b/blocks/cflow/MethodCallInlinerBase.cs @@ -104,6 +104,10 @@ namespace de4dot.blocks.cflow { return tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0); } + protected virtual Instruction onAfterLoadArg(MethodDef methodToInline, Instruction instr, ref int instrIndex) { + return instr; + } + protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) { int loadIndex = 0; int methodArgsCount = DotNetUtils.getArgsCount(methodToInline); @@ -133,6 +137,7 @@ namespace de4dot.blocks.cflow { return null; loadIndex++; instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex); + instr = onAfterLoadArg(methodToInline, instr, ref instrIndex); } if (instr == null || loadIndex != methodArgsCount - popLastArgs) return null; @@ -224,7 +229,7 @@ namespace de4dot.blocks.cflow { return false; for (int i = 0; i < methodArgs.Count; i++) { var methodArg = methodArgs[i]; - var methodToInlineArg = methodToInlineArgs[i].Type; + var methodToInlineArg = getArgType(methodToInline, methodToInlineArgs[i].Type); if (!isCompatibleType(i, methodArg, methodToInlineArg)) { if (i != 0 || !hasImplicitThis) return false; @@ -236,6 +241,19 @@ namespace de4dot.blocks.cflow { return true; } + static TypeSig getArgType(MethodDef method, TypeSig arg) { + if (arg.GetElementType() != ElementType.MVar) + return arg; + var mvar = (GenericMVar)arg; + foreach (var gp in method.GenericParameters) { + if (gp.Number != mvar.Number) + continue; + foreach (var gpc in gp.GenericParamConstraints) + return gpc.Constraint.ToTypeSig(); + } + return arg; + } + protected virtual bool isCompatibleType(int paramIndex, IType origType, IType newType) { return new SigComparer().Equals(origType, newType); } diff --git a/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs b/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs index 1fab08f5..3e9ab411 100644 --- a/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs +++ b/de4dot.code/deobfuscators/DeepSea/DsMethodCallInliner.cs @@ -51,8 +51,13 @@ namespace de4dot.code.deobfuscators.DeepSea { bool inlineMethod(Instruction callInstr, int instrIndex) { var method = callInstr.Operand as MethodDef; - if (method == null) - return false; + if (method == null) { + var ms = callInstr.Operand as MethodSpec; + if (ms != null) + method = ms.Method as MethodDef; + if (method == null) + return false; + } if (!canInline(method)) return false; @@ -69,6 +74,14 @@ namespace de4dot.code.deobfuscators.DeepSea { return true; } + protected override Instruction onAfterLoadArg(MethodDef methodToInline, Instruction instr, ref int instrIndex) { + if (instr.OpCode.Code != Code.Box) + return instr; + if (methodToInline.MethodSig.GetGenParamCount() == 0) + return instr; + return DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex); + } + bool inlineMethod(MethodDef methodToInline, int instrIndex, int const1, int const2) { this.methodToInline = methodToInline = cflowDeobfuscator.deobfuscate(methodToInline); @@ -271,8 +284,7 @@ done: bool emulateToReturn(int index, Instruction lastInstr) { int pushes, pops; lastInstr.CalculateStackUsage(false, out pushes, out pops); - for (int i = 0; i < pops; i++) - instructionEmulator.pop(); + instructionEmulator.pop(pops); returnValue = null; if (pushes != 0) { @@ -300,8 +312,6 @@ done: return false; if (method.Attributes != (MethodAttributes.Assembly | MethodAttributes.Static)) return false; - if (method.GenericParameters.Count > 0) - return false; if (method.Body.ExceptionHandlers.Count > 0) return false; @@ -309,6 +319,14 @@ done: int paramCount = parameters.Count; if (paramCount < 2) return false; + + if (method.GenericParameters.Count > 0) { + foreach (var gp in method.GenericParameters) { + if (gp.GenericParamConstraints.Count == 0) + return false; + } + } + var param1 = parameters[paramCount - 1]; var param2 = parameters[paramCount - 2]; if (!isIntType(param1.ElementType))