diff --git a/blocks/cflow/BlockCflowDeobfuscator.cs b/blocks/cflow/BlockCflowDeobfuscator.cs index b7b02878..0bd06cf4 100644 --- a/blocks/cflow/BlockCflowDeobfuscator.cs +++ b/blocks/cflow/BlockCflowDeobfuscator.cs @@ -37,7 +37,10 @@ namespace de4dot.blocks.cflow { if (instructions.Count == 0) return false; for (int i = 0; i < instructions.Count - 1; i++) { - instructionEmulator.emulate(instructions[i].Instruction); + var instr = instructions[i].Instruction; + if (patchBoolCallMethod(instr, i)) + instr = instructions[i].Instruction; + instructionEmulator.emulate(instr); } switch (block.LastInstr.OpCode.Code) { @@ -72,6 +75,34 @@ namespace de4dot.blocks.cflow { } } + // This is a hack for .NET Reactor + bool patchBoolCallMethod(Instruction instr, int instrIndex) { + if (instr.OpCode.Code != Code.Call) + return false; + var method = instr.Operand as MethodDefinition; + if (method == null) + return false; + if (method.Parameters.Count > 0) + return false; + if (!MemberReferenceHelper.verifyType(method.MethodReturnType.ReturnType, "mscorlib", "System.Boolean")) + return false; + var body = method.Body; + if (body == null) + return false; + var instrs = body.Instructions; + if (instrs.Count > 10) + return false; + + var ldci4 = instrs[0]; + if (ldci4.OpCode.Code == Code.Br || ldci4.OpCode.Code == Code.Br_S) + ldci4 = (Instruction)ldci4.Operand; + if (ldci4 == null || !DotNetUtils.isLdcI4(ldci4) || ldci4.Next == null || ldci4.Next.OpCode.Code != Code.Ret) + return false; + int val = DotNetUtils.getLdcI4Value(ldci4); + block.Instructions[instrIndex] = new Instr(Instruction.Create(OpCodes.Ldc_I4, val)); + return true; + } + bool emulateBranch(int stackArgs, Bool3 cond) { if (cond == Bool3.Unknown) return false; diff --git a/blocks/cflow/BlocksCflowDeobfuscator.cs b/blocks/cflow/BlocksCflowDeobfuscator.cs index 40fc0b85..749e4ee9 100644 --- a/blocks/cflow/BlocksCflowDeobfuscator.cs +++ b/blocks/cflow/BlocksCflowDeobfuscator.cs @@ -22,7 +22,7 @@ using Mono.Cecil.Cil; namespace de4dot.blocks.cflow { public class BlocksCflowDeobfuscator { - BlockCflowDeobfuscator blockControlFlowDeobfuscator = new BlockCflowDeobfuscator(); + BlockCflowDeobfuscator blockCflowDeobfuscator = new BlockCflowDeobfuscator(); Blocks blocks; int numRemovedDeadBlocks; @@ -41,8 +41,8 @@ namespace de4dot.blocks.cflow { bool changed; do { changed = false; - changed |= removeDeadBlocks(); - changed |= mergeBlocks(); + removeDeadBlocks(); + mergeBlocks(); allBlocks.Clear(); allBlocks.AddRange(blocks.MethodBlocks.getAllBlocks()); @@ -51,8 +51,8 @@ namespace de4dot.blocks.cflow { var lastInstr = block.LastInstr; if (!DotNetUtils.isConditionalBranch(lastInstr.OpCode.Code) && lastInstr.OpCode.Code != Code.Switch) continue; - blockControlFlowDeobfuscator.init(block, blocks.Method.Parameters, blocks.Locals); - changed |= blockControlFlowDeobfuscator.deobfuscate(); + blockCflowDeobfuscator.init(block, blocks.Method.Parameters, blocks.Locals); + changed |= blockCflowDeobfuscator.deobfuscate(); } switchCflowDeobfuscator.init(blocks, allBlocks); diff --git a/de4dot.code/ObfuscatedFile.cs b/de4dot.code/ObfuscatedFile.cs index 26c75c80..b01ba8b0 100644 --- a/de4dot.code/ObfuscatedFile.cs +++ b/de4dot.code/ObfuscatedFile.cs @@ -442,7 +442,7 @@ namespace de4dot { Log.v("Deobfuscating methods"); var methodPrinter = new MethodPrinter(); - var cflowObfuscator = new BlocksCflowDeobfuscator(); + var cflowDeobfuscator = new BlocksCflowDeobfuscator(); foreach (var method in allMethods) { Log.v("Deobfuscating {0} ({1:X8})", method, method.MetadataToken.ToUInt32()); Log.indent(); @@ -452,9 +452,9 @@ namespace de4dot { deob.deobfuscateMethodBegin(blocks); if (options.ControlFlowDeobfuscation) { - cflowObfuscator.init(blocks); - cflowObfuscator.deobfuscate(); - int numDeadBlocks = cflowObfuscator.NumberOfRemovedDeadBlocks; + cflowDeobfuscator.init(blocks); + cflowDeobfuscator.deobfuscate(); + int numDeadBlocks = cflowDeobfuscator.NumberOfRemovedDeadBlocks; if (numDeadBlocks > 0) Log.v("Removed {0} dead block(s)", numDeadBlocks); }