private void Window_Loaded(object sender, RoutedEventArgs e) { ilOutput = TextColorWriterToDecompilerOutput.Create(new RichTextBoxTextColorOutput(ILView, ManualMode.Theme)); exprOutput = new RichTextBoxTextColorOutput(ExprView, ManualMode.Theme); ILView.Document.PageWidth = 1000; method = DotNetUtils.Clone(((IMethodNode)(((object[])this.DataContext)[0])).MethodDef); Blocks blocks = new Blocks(method); CancellationToken token = default(CancellationToken); cflowDeobfuscator = new CflowDeobfuscator(); cflowDeobfuscator.Initialize(blocks, token); cflowDeobfuscator.CheckBlocks(); for (int i = 0; i < cflowDeobfuscator.UnsolvedBlocks.Count(); i++) { BlocksListView.Items.Add("Block " + i.ToString()); } if (BlocksListView.Items.Count > 0) { BlocksListView.SelectedIndex = 0; } else { Consts.IsEnabled = false; Value.IsEnabled = false; SetButton.IsEnabled = false; SolveButton.IsEnabled = false; MsgBox.Instance.Show("There is no unpredictable control transfers in this method"); } }
public MethodDef Deobfuscate(MethodDef method) { MethodDef deobfuscatedMethod; if (deobfuscated.TryGetValue(method, out deobfuscatedMethod)) { return(deobfuscatedMethod); } if (method.Body == null || method.Body.Instructions.Count == 0) { deobfuscated[method] = method; return(method); } deobfuscatedMethod = DotNetUtils.Clone(method); deobfuscated[method] = deobfuscatedMethod; var blocks = new Blocks(deobfuscatedMethod); Deobfuscate(blocks); IList <Instruction> allInstructions; IList <ExceptionHandler> allExceptionHandlers; blocks.GetCode(out allInstructions, out allExceptionHandlers); DotNetUtils.RestoreBody(deobfuscatedMethod, allInstructions, allExceptionHandlers); return(deobfuscatedMethod); }
private static void DeadCodeHandler(MethodDef method, CancellationToken token) { List <Block> allBlocks = new List <Block>(); IList <Instruction> allInstructions; IList <ExceptionHandler> allExceptionHandlers; ILAstDeadCode deadCodeRemover = new ILAstDeadCode(); List <Instruction> deadInstructions = new List <Instruction>(); deadCodeRemover.RemoveDeadCode(method, deadInstructions); if (!DeFlowSettings.Settings.Remove) { foreach (var instr in deadInstructions) { uint rva = (uint)method.RVA; uint baseRva = rva == 0 ? 0 : rva + method.Body.HeaderSize; long baseOffs = baseRva == 0 ? 0 : method.Module.ToFileOffset(baseRva) ?? 0; ulong fileOffset = (ulong)baseOffs + instr.Offset; DeadInstructions.DeadInstrsList.Add(new DeadInstr((ulong)baseOffs, instr.Offset, method.Module.Location)); } } else { var tempMethod = DotNetUtils.Clone(method); var blocks = new Blocks(tempMethod); blocks.MethodBlocks.GetAllBlocks(allBlocks); foreach (var block in allBlocks) { foreach (var instr in deadInstructions) { var indx = block.Instructions.FindIndex(x => x.Instruction.Offset == instr.Offset && x.Instruction.OpCode == instr.OpCode && x.Instruction.Operand == instr.Operand); if (indx != -1) { block.Instructions.RemoveAt(indx); block.Instructions.Insert(indx, new Instr(OpCodes.Nop.ToInstruction())); } } } if (DeFlowSettings.Settings.Nops) { foreach (Block block in allBlocks) { if (block.Instructions.Count() > 1) { block.Instructions.RemoveAll(x => x.Instruction.OpCode == OpCodes.Nop); } } } blocks.GetCode(out allInstructions, out allExceptionHandlers); DotNetUtils.RestoreBody(tempMethod, (IEnumerable <Instruction>)allInstructions, (IEnumerable <ExceptionHandler>)allExceptionHandlers); RestoreMethod(method, tempMethod); } }
public static void Deobfuscate(MethodDef method, CancellationToken token) { bool result; CflowDeobfuscator cflowDeobfuscator = new CflowDeobfuscator(); IList <Instruction> allInstructions; IList <ExceptionHandler> allExceptionHandlers; MethodDef tempMethod = DotNetUtils.Clone(method); Blocks blocks = new Blocks(tempMethod); cflowDeobfuscator.Initialize(blocks, token); result = cflowDeobfuscator.Deobfuscate(); blocks.GetCode(out allInstructions, out allExceptionHandlers); DotNetUtils.RestoreBody(tempMethod, (IEnumerable <Instruction>)allInstructions, (IEnumerable <ExceptionHandler>)allExceptionHandlers); RestoreMethod(method, tempMethod); if (result) { DeadCodeHandler(method, token); } }
public static void DeobfuscateAssisted(MethodDef method, CancellationToken token, Context ctx, BoolExpr expr, Block block) { CflowDeobfuscator cflowDeobfuscator = new CflowDeobfuscator(); IList <Instruction> allInstructions; IList <ExceptionHandler> allExceptionHandlers; MethodDef tempMethod = DotNetUtils.Clone(method); Blocks blocks = new Blocks(tempMethod); cflowDeobfuscator.Initialize(blocks, token); List <Block> allBlocks = new List <Block>(); blocks.MethodBlocks.GetAllBlocks(allBlocks); var newBlock = allBlocks.Find(x => x.FirstInstr.Instruction.Offset == block.FirstInstr.Instruction.Offset); cflowDeobfuscator.SolveBlockAssisted(ctx, expr, newBlock); blocks.GetCode(out allInstructions, out allExceptionHandlers); DotNetUtils.RestoreBody(tempMethod, (IEnumerable <Instruction>)allInstructions, (IEnumerable <ExceptionHandler>)allExceptionHandlers); RestoreMethod(method, tempMethod); DeadCodeHandler(method, token); }
public void Execute() { if (token.IsCancellationRequested) { // it means its called from Redo command token = default(CancellationToken); } try { methods.Add(methodNode.MethodDef); origMethodBodys.Add(methodNode.MethodDef.MethodBody); isBodyModified.Add(methodAnnotations.IsBodyModified(methodNode.MethodDef)); methodAnnotations.SetBodyModified(methodNode.MethodDef, true); var method = methodNode.MethodDef; if (method.Body.Instructions.Any(x => x.OpCode.Code == Code.Call && x.Operand is MethodDef)) { //At first lets restore all methods called from this method for (int i = 0; i < method.Body.Instructions.Count(); i++) { if (method.Body.Instructions[i].OpCode.Code == Code.Call && method.Body.Instructions[i].Operand is MethodDef && (method.Body.Instructions[i].Operand as MethodDef).Body != null) { methods.Add(method.Body.Instructions[i].Operand as MethodDef); origMethodBodys.Add((method.Body.Instructions[i].Operand as MethodDef).MethodBody); isBodyModified.Add(methodAnnotations.IsBodyModified(method.Body.Instructions[i].Operand as MethodDef)); methodAnnotations.SetBodyModified(method.Body.Instructions[i].Operand as MethodDef, true); MethodDeobfuscator.Deobfuscate(method.Body.Instructions[i].Operand as MethodDef, token); } } var tempMethod = DotNetUtils.Clone(method); var blocks = new Blocks(tempMethod); List <Block> allBlocks = new List <Block>(); blocks.MethodBlocks.GetAllBlocks(allBlocks); foreach (var block in allBlocks) { for (int i = 0; i < block.Instructions.Count; i++) { var instruction = block.Instructions[i]; if (instruction.OpCode.Code == Code.Call && instruction.Operand is MethodDef && (instruction.Operand as MethodDef).Body != null) { // Remove empty method if ((instruction.Operand as MethodDef).Body.Instructions.All(x => x.OpCode.Code == Code.Nop || x.OpCode.Code == Code.Ret)) { block.Instructions.RemoveAt(i); //TODO: remove all inner empty methods, but better to have addititonal command for it tho } // Inline proxy method if ((instruction.Operand as MethodDef).Body.Instructions.All(x => IsOkOpcode(x.OpCode.Code))) { var inlined = GetInstruction((instruction.Operand as MethodDef).Body.Instructions); if (inlined != null) { block.Instructions.RemoveAt(i); block.Instructions.Insert(i, new Instr(new Instruction(inlined.OpCode, inlined.Operand))); } } } } } IList <Instruction> allInstructions; IList <ExceptionHandler> allExceptionHandlers; blocks.GetCode(out allInstructions, out allExceptionHandlers); DotNetUtils.RestoreBody(tempMethod, (IEnumerable <Instruction>)allInstructions, (IEnumerable <ExceptionHandler>)allExceptionHandlers); MethodDeobfuscator.RestoreMethod(method, tempMethod); } } catch (OperationCanceledException) { } }
protected override void GetCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) { var contexts = (List <Context>)context; var ctx = contexts.First(c => c.FieldToken == field.MDToken.ToInt32()); var originalMethod = DotNetUtils.Clone(ctx .CreateMethod); // backup original method and restore because changes are not universal DeobfuscateIfNeeded(ctx.CreateMethod); var instructions = ctx.CreateMethod.Body.Instructions; var variables = ctx.CreateMethod.Body.Variables; var parameters = ctx.CreateMethod.Parameters; instructions.SimplifyMacros(variables, parameters); var sigData = module.ReadBlob(ctx.FieldToken); var extraDataToken = GetExtraDataToken(sigData); var modifierMDToken = ((CModOptSig)field.FieldType).Modifier.MDToken.ToInt32(); ReplaceMetadataToken(ref instructions, modifierMDToken, variables[0]); ReplaceFieldNameChars(ref instructions, field.Name, variables[0]); InlineArrays(ref instructions, extraDataToken, variables[1], variables[2]); RemoveDecrementorBlock(ref instructions, variables[2]); var firstInstruction = GetEmulationStartIndex(instructions, variables[1], variables[2]); var lastInstruction = instructions.IndexOf( instructions.First( i => i.OpCode == OpCodes.Callvirt && i.Operand.ToString().Contains("GetCustomAttributes"))) - 4; var nativeMode = false; if (instructions[lastInstruction - 1].OpCode == OpCodes.Call) // x86 protection { lastInstruction--; // don't try emulating native method nativeMode = true; } var result = EmulateManagedMethod(ctx.CreateMethod, firstInstruction, lastInstruction); if (nativeMode) { var nativeMethod = (MethodDef)instructions[lastInstruction].Operand; if (!NativeMethods.Contains(nativeMethod)) { NativeMethods.Add(nativeMethod); } result = EmulateNativeMethod(nativeMethod, result); } result *= GetMagicNumber(field.CustomAttributes[0]); calledMethod = module.ResolveMemberRef(new MDToken(result).Rid); if (calledMethod == null) { throw new Exception(); } var charNum = GetCharNum(instructions, parameters.Last()); callOpcode = GetCallOpCode(calledMethod, charNum, ctx.ByteNum); ctx.CreateMethod.Body = originalMethod.Body; // restore }