From 9ed55629e6024d309ec19abed72549f74f547e35 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 12 Oct 2011 19:47:51 +0200 Subject: [PATCH] Print deobfuscated method if -vv --- cecil | 2 +- de4dot.code/Log.cs | 17 +++- de4dot.code/ObfuscatedFile.cs | 151 ++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 5 deletions(-) diff --git a/cecil b/cecil index 6771f0f3..56c51312 160000 --- a/cecil +++ b/cecil @@ -1 +1 @@ -Subproject commit 6771f0f303228463c924de0634a8dbd5fa59bd47 +Subproject commit 56c51312b7efb755194a76612bf0c41c517f0360 diff --git a/de4dot.code/Log.cs b/de4dot.code/Log.cs index db0bb1d9..14ddf210 100644 --- a/de4dot.code/Log.cs +++ b/de4dot.code/Log.cs @@ -33,23 +33,32 @@ namespace de4dot { veryverbose, } public static LogLevel logLevel = LogLevel.normal; + public static string indentString = ""; + + public static bool isAtLeast(LogLevel ll) { + return logLevel >= ll; + } + + static void initIndentString() { + indentString = new string(' ', indentLevel * indentSize); + } public static void indent() { indentLevel++; + initIndentString(); } public static void deIndent() { if (indentLevel <= 0) throw new ApplicationException("Can't de-indent!"); indentLevel--; + initIndentString(); } public static void log(LogLevel l, string format, params object[] args) { - if (l > logLevel) + if (!isAtLeast(l)) return; - string indent = new string(' ', indentLevel * indentSize); - if (l <= LogLevel.warning) - indent = ""; + var indent = l <= LogLevel.warning ? "" : indentString; Console.WriteLine(indent + format, args); } diff --git a/de4dot.code/ObfuscatedFile.cs b/de4dot.code/ObfuscatedFile.cs index 99ef2565..e4905e12 100644 --- a/de4dot.code/ObfuscatedFile.cs +++ b/de4dot.code/ObfuscatedFile.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Text; using Mono.Cecil; using Mono.Cecil.Cil; using de4dot.deobfuscators; @@ -439,6 +440,7 @@ namespace de4dot { deob.DeobfuscatedFile = null; Log.v("Deobfuscating methods"); + var methodPrinter = new MethodPrinter(); foreach (var method in allMethods) { Log.v("Deobfuscating {0} ({1:X8})", method, method.MetadataToken.ToUInt32()); Log.indent(); @@ -461,6 +463,14 @@ namespace de4dot { IList allExceptionHandlers; blocks.getCode(out allInstructions, out allExceptionHandlers); DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers); + + const Log.LogLevel dumpLogLevel = Log.LogLevel.veryverbose; + if (Log.isAtLeast(dumpLogLevel)) { + Log.log(dumpLogLevel, "Deobfuscated code:"); + Log.indent(); + methodPrinter.print(dumpLogLevel, allInstructions, allExceptionHandlers); + Log.deIndent(); + } } removeNoInliningAttribute(method); @@ -469,6 +479,147 @@ namespace de4dot { } } + class MethodPrinter { + Log.LogLevel logLevel; + IList allInstructions; + IList allExceptionHandlers; + Dictionary targets = new Dictionary(); + + class ExInfo { + public List tryStarts = new List(); + public List tryEnds = new List(); + public List filterStarts = new List(); + public List handlerStarts = new List(); + public List handlerEnds = new List(); + } + Dictionary exInfos = new Dictionary(); + ExInfo lastExInfo; + + public void print(Log.LogLevel logLevel, IList allInstructions, IList allExceptionHandlers) { + try { + this.logLevel = logLevel; + this.allInstructions = allInstructions; + this.allExceptionHandlers = allExceptionHandlers; + lastExInfo = new ExInfo(); + print(); + } + finally { + this.allInstructions = null; + this.allExceptionHandlers = null; + targets.Clear(); + exInfos.Clear(); + lastExInfo = null; + } + } + + void initTargets() { + foreach (var instr in allInstructions) { + switch (instr.OpCode.OperandType) { + case OperandType.ShortInlineBrTarget: + case OperandType.InlineBrTarget: + var targetInstr = instr.Operand as Instruction; + if (targetInstr != null) + targets[targetInstr] = true; + break; + + case OperandType.InlineSwitch: + foreach (var targetInstr2 in (Instruction[])instr.Operand) { + if (targetInstr2 != null) + targets[targetInstr2] = true; + } + break; + } + } + } + + void initExHandlers() { + foreach (var ex in allExceptionHandlers) { + if (ex.TryStart != null) { + getExInfo(ex.TryStart).tryStarts.Add(ex); + getExInfo(ex.TryEnd).tryEnds.Add(ex); + } + if (ex.FilterStart != null) + getExInfo(ex.FilterStart).filterStarts.Add(ex); + if (ex.HandlerStart != null) { + getExInfo(ex.HandlerStart).handlerStarts.Add(ex); + getExInfo(ex.HandlerEnd).handlerEnds.Add(ex); + } + } + } + + ExInfo getExInfo(Instruction instruction) { + if (instruction == null) + return lastExInfo; + ExInfo exInfo; + if (!exInfos.TryGetValue(instruction, out exInfo)) + exInfos[instruction] = exInfo = new ExInfo(); + return exInfo; + } + + void print() { + initTargets(); + initExHandlers(); + + Log.indent(); + foreach (var instr in allInstructions) { + ExInfo exInfo; + if (exInfos.TryGetValue(instr, out exInfo)) + printExInfo(exInfo); + if (targets.ContainsKey(instr)) { + Log.deIndent(); + Log.log(logLevel, "{0}:", instr.GetLabelString()); + Log.indent(); + } + var instrString = instr.GetOpCodeString(); + var operandString = instr.GetOperandString(); + var memberReference = instr.Operand as MemberReference; + if (operandString == "") + Log.log(logLevel, "{0}", instrString); + else if (memberReference != null) + Log.log(logLevel, "{0,-9} {1} // {2:X8}", instrString, operandString, memberReference.MetadataToken.ToUInt32()); + else + Log.log(logLevel, "{0,-9} {1}", instrString, operandString); + } + printExInfo(lastExInfo); + Log.deIndent(); + } + + void printExInfo(ExInfo exInfo) { + Log.deIndent(); + foreach (var ex in exInfo.tryStarts) + Log.log(logLevel, "// try start: {0}", getExceptionString(ex)); + foreach (var ex in exInfo.tryEnds) + Log.log(logLevel, "// try end: {0}", getExceptionString(ex)); + foreach (var ex in exInfo.filterStarts) + Log.log(logLevel, "// filter start: {0}", getExceptionString(ex)); + foreach (var ex in exInfo.handlerStarts) + Log.log(logLevel, "// handler start: {0}", getExceptionString(ex)); + foreach (var ex in exInfo.handlerEnds) + Log.log(logLevel, "// handler end: {0}", getExceptionString(ex)); + Log.indent(); + } + + string getExceptionString(ExceptionHandler ex) { + var sb = new StringBuilder(); + if (ex.TryStart != null) + sb.Append(string.Format("TRY: {0}-{1}", getOffset(ex.TryStart), getOffset(ex.TryEnd))); + if (ex.FilterStart != null) + sb.Append(string.Format(", FILTER: {0}", getOffset(ex.FilterStart))); + if (ex.HandlerStart != null) + sb.Append(string.Format(", HANDLER: {0}-{1}", getOffset(ex.HandlerStart), getOffset(ex.HandlerEnd))); + sb.Append(string.Format(", TYPE: {0}", ex.HandlerType)); + if (ex.CatchType != null) + sb.Append(string.Format(", CATCH: {0}", ex.CatchType)); + return sb.ToString(); + } + + string getOffset(Instruction instr) { + if (instr == null) + return "END"; + return string.Format("{0:X4}", instr.Offset); + } + } + bool hasNonEmptyBody(MethodDefinition method) { return method.HasBody && method.Body.Instructions.Count > 0; }