From c65b76583c1e920c493078d1e29664d234afc420 Mon Sep 17 00:00:00 2001 From: de4dot Date: Tue, 20 Dec 2011 20:11:05 +0100 Subject: [PATCH] Add CflowDeobfuscator --- blocks/blocks.csproj | 2 + blocks/cflow/BlocksCflowDeobfuscator.cs | 3 +- blocks/cflow/CflowDeobfuscator.cs | 62 +++++++++++++++++++++++++ blocks/cflow/ICflowDeobfuscator.cs | 26 +++++++++++ blocks/cflow/MethodCallInliner.cs | 14 +++++- 5 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 blocks/cflow/CflowDeobfuscator.cs create mode 100644 blocks/cflow/ICflowDeobfuscator.cs diff --git a/blocks/blocks.csproj b/blocks/blocks.csproj index 63da0cbe..23a0464b 100644 --- a/blocks/blocks.csproj +++ b/blocks/blocks.csproj @@ -38,9 +38,11 @@ + + diff --git a/blocks/cflow/BlocksCflowDeobfuscator.cs b/blocks/cflow/BlocksCflowDeobfuscator.cs index 6081f665..93ba2d15 100644 --- a/blocks/cflow/BlocksCflowDeobfuscator.cs +++ b/blocks/cflow/BlocksCflowDeobfuscator.cs @@ -33,6 +33,7 @@ namespace de4dot.blocks.cflow { MethodCallInliner methodCallInliner = new MethodCallInliner(); public bool InlineMethods { get; set; } + public bool InlineInstanceMethods { get; set; } public void init(Blocks blocks) { this.blocks = blocks; @@ -54,7 +55,7 @@ namespace de4dot.blocks.cflow { if (InlineMethods) { foreach (var block in allBlocks) { - methodCallInliner.init(blocks, block); + methodCallInliner.init(blocks, block, InlineInstanceMethods); changed |= methodCallInliner.deobfuscate(); } } diff --git a/blocks/cflow/CflowDeobfuscator.cs b/blocks/cflow/CflowDeobfuscator.cs new file mode 100644 index 00000000..41d6a932 --- /dev/null +++ b/blocks/cflow/CflowDeobfuscator.cs @@ -0,0 +1,62 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System.Collections.Generic; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace de4dot.blocks.cflow { + public class CflowDeobfuscator : ICflowDeobfuscator { + BlocksCflowDeobfuscator cflowDeobfuscator = new BlocksCflowDeobfuscator(); + + public bool InlineMethods { get; set; } + public bool InlineInstanceMethods { get; set; } + + public CflowDeobfuscator() { + InlineMethods = true; + InlineInstanceMethods = false; + } + + public void deobfuscateCflow(MethodDefinition method) { + deobfuscate(method, (blocks) => { + cflowDeobfuscator.InlineMethods = InlineMethods; + cflowDeobfuscator.InlineInstanceMethods = InlineInstanceMethods; + cflowDeobfuscator.init(blocks); + cflowDeobfuscator.deobfuscate(); + }); + } + + static bool hasNonEmptyBody(MethodDefinition method) { + return method.Body != null && method.Body.Instructions.Count > 0; + } + + void deobfuscate(MethodDefinition method, Action handler) { + if (hasNonEmptyBody(method)) { + var blocks = new Blocks(method); + + handler(blocks); + + IList allInstructions; + IList allExceptionHandlers; + blocks.getCode(out allInstructions, out allExceptionHandlers); + DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers); + } + } + } +} diff --git a/blocks/cflow/ICflowDeobfuscator.cs b/blocks/cflow/ICflowDeobfuscator.cs new file mode 100644 index 00000000..a34fdd01 --- /dev/null +++ b/blocks/cflow/ICflowDeobfuscator.cs @@ -0,0 +1,26 @@ +/* + Copyright (C) 2011 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using Mono.Cecil; + +namespace de4dot.blocks.cflow { + public interface ICflowDeobfuscator { + void deobfuscateCflow(MethodDefinition method); + } +} diff --git a/blocks/cflow/MethodCallInliner.cs b/blocks/cflow/MethodCallInliner.cs index 5d6e3879..2b537879 100644 --- a/blocks/cflow/MethodCallInliner.cs +++ b/blocks/cflow/MethodCallInliner.cs @@ -29,11 +29,13 @@ namespace de4dot.blocks.cflow { Blocks blocks; Block block; int iteration; + bool inlineInstanceMethods; - public void init(Blocks blocks, Block block) { + public void init(Blocks blocks, Block block, bool inlineInstanceMethods) { this.blocks = blocks; this.block = block; this.iteration = 0; + this.inlineInstanceMethods = inlineInstanceMethods; } public bool deobfuscate() { @@ -50,6 +52,14 @@ namespace de4dot.blocks.cflow { return changed; } + bool canInline(MethodDefinition method) { + if (method.IsStatic) + return true; + if (method.IsVirtual) + return false; + return inlineInstanceMethods; + } + bool inlineMethod(Instruction callInstr, int instrIndex) { var method = callInstr.Operand as MethodDefinition; if (method == null) @@ -57,7 +67,7 @@ namespace de4dot.blocks.cflow { if (MemberReferenceHelper.compareMethodReferenceAndDeclaringType(method, blocks.Method)) return false; - if (!method.IsStatic) + if (!canInline(method)) return false; var body = method.Body; if (body == null)