Refactor
This commit is contained in:
parent
61bb3abdee
commit
6f807f2484
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user