예제 #1
0
        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");
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
            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)
                {
                }
            }
예제 #7
0
        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
        }