This commit is contained in:
de4dot 2012-05-02 10:45:18 +02:00
parent 61bb3abdee
commit 6f807f2484

View File

@ -49,9 +49,25 @@ namespace de4dot.blocks.cflow {
protected abstract bool deobfuscateInternal();
protected class InstructionPatcher {
readonly int patchIndex;
public readonly int afterIndex;
public readonly Instruction lastInstr;
readonly Instr clonedInstr;
public InstructionPatcher(int patchIndex, int afterIndex, Instruction lastInstr) {
this.patchIndex = patchIndex;
this.afterIndex = afterIndex;
this.lastInstr = lastInstr;
this.clonedInstr = new Instr(DotNetUtils.clone(lastInstr));
}
public void patch(Block block) {
block.Instructions[patchIndex] = clonedInstr;
}
}
protected bool inlineLoadMethod(int patchIndex, MethodDefinition methodToInline, Instruction loadInstr, int instrIndex) {
var instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
if (instr == null || instr.OpCode.Code != Code.Ret)
if (!isReturn(methodToInline, instrIndex))
return false;
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
@ -63,6 +79,21 @@ namespace de4dot.blocks.cflow {
}
protected bool inlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs = 0) {
return patchMethod(methodToInline, tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, popLastArgs));
}
protected bool patchMethod(MethodDefinition methodToInline, InstructionPatcher patcher) {
if (patcher == null)
return false;
if (!isReturn(methodToInline, patcher.afterIndex))
return false;
patcher.patch(block);
return true;
}
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs = 0) {
int loadIndex = 0;
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
bool foundLdarga = false;
@ -88,75 +119,66 @@ namespace de4dot.blocks.cflow {
break;
if (DotNetUtils.getArgIndex(instr) != loadIndex)
return false;
return null;
loadIndex++;
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
}
if (instr == null || loadIndex != methodArgsCount - popLastArgs)
return false;
return null;
if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt) {
if (foundLdarga)
return false;
return null;
var callInstr = instr;
var calledMethod = callInstr.Operand as MethodReference;
if (calledMethod == null)
return false;
return null;
if (!isCompatibleType(-1, calledMethod.MethodReturnType.ReturnType, methodToInline.MethodReturnType.ReturnType))
return false;
return null;
if (!checkSameMethods(calledMethod, methodToInline, popLastArgs))
return false;
return null;
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
if (instr == null || instr.OpCode.Code != Code.Ret)
return false;
block.Instructions[patchIndex] = new Instr(DotNetUtils.clone(callInstr));
return true;
return new InstructionPatcher(patchIndex, instrIndex, callInstr);
}
else if (instr.OpCode.Code == Code.Newobj) {
if (foundLdarga)
return false;
return null;
var newobjInstr = instr;
var ctor = newobjInstr.Operand as MethodReference;
if (ctor == null)
return false;
return null;
if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodReturnType.ReturnType))
return false;
return null;
var methodArgs = DotNetUtils.getArgs(methodToInline);
var calledMethodArgs = DotNetUtils.getArgs(ctor);
if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
return false;
return null;
for (int i = 1; i < calledMethodArgs.Count; i++) {
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1]))
return false;
return null;
}
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
if (instr == null || instr.OpCode.Code != Code.Ret)
return false;
block.Instructions[patchIndex] = new Instr(DotNetUtils.clone(newobjInstr));
return true;
return new InstructionPatcher(patchIndex, instrIndex, newobjInstr);
}
else if (instr.OpCode.Code == Code.Ldfld || instr.OpCode.Code == Code.Ldflda ||
instr.OpCode.Code == Code.Ldftn || instr.OpCode.Code == Code.Ldvirtftn) {
var ldInstr = instr;
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
if (instr == null || instr.OpCode.Code != Code.Ret)
return false;
if (methodArgsCount != 1)
return false;
block.Instructions[patchIndex] = new Instr(DotNetUtils.clone(ldInstr));
return true;
return null;
return new InstructionPatcher(patchIndex, instrIndex, ldInstr);
}
return false;
return null;
}
protected virtual bool isReturn(MethodDefinition methodToInline, int instrIndex) {
var instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
return instr != null && instr.OpCode.Code == Code.Ret;
}
protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline, int ignoreLastMethodToInlineArgs = 0) {