Inline generic methods that DS added

This commit is contained in:
de4dot 2012-12-14 12:39:06 +01:00
parent e2016f6b18
commit 88d1a8ab89
2 changed files with 43 additions and 7 deletions

View File

@ -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);
}

View File

@ -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))