예제 #1
0
        public void BwIndexInMemoryAddress()
        {
            // samples of switch statement emitted
            // by the Microsoft VC compiler

            var ebp = m.Frame.EnsureRegister(Registers.ebp);
            var eax = m.Frame.EnsureRegister(Registers.eax);
            var edx = m.Frame.EnsureRegister(Registers.edx);

            // cmp [ebp-66],1D

            m.Assign(SCZO, m.Cond(m.ISub(m.Mem32(m.ISub(ebp, 0xC4)), 0x1D)));
            var block0 = m.CurrentBlock;

            m.BranchIf(new TestCondition(ConditionCode.UGT, SCZO), "default");

            // mov edx,[ebp-66]
            // movzx eax,byte ptr [edx + 0x10000]
            // jmp [eax + 0x12000]

            m.Assign(edx, m.Mem32(m.ISub(ebp, 0xC4)));
            m.Assign(eax, m.Convert(m.Mem8(m.IAdd(edx, 0x10000)), PrimitiveType.Byte, PrimitiveType.Word32));
            var xfer = new RtlGoto(m.Mem32(m.IAdd(eax, 0x12000)), InstrClass.Transfer);

            var block1 = m.CurrentBlock;
            var bw     = new Backwalker <Block, Instruction>(host, xfer, expSimp);
            var ret    = bw.BackwalkInstructions(Registers.eax, block1);

            Assert.AreEqual("None", bw.Index.ToString());
            Assert.AreEqual("Mem0[ebp - 0xC4<32>:word32]", bw.IndexExpression.ToString());
            Assert.AreEqual(4, bw.JumpSize);
            Assert.IsTrue(ret);

            ret = bw.BackwalkInstructions(null, block0);
        }
예제 #2
0
        public void BwInvertedCondition()
        {
            var ebx = m.Reg32("ebx", 3);
            var eax = m.Reg32("eax", 0);

            var CZ = m.Flags("CZ");

            m.Assign(CZ, m.Cond(m.ISub(ebx, 0x30)));
            m.BranchIf(m.Test(ConditionCode.ULE, CZ), "do_switch");
            m.Goto("default_case");

            m.Label("do_switch");
            m.Assign(eax, 0);
            var block = m.CurrentBlock;
            var xfer  = new RtlGoto(m.Mem32(m.IAdd(Constant.Word32(0x00123400), m.IMul(ebx, 4))), RtlClass.Transfer);

            m.Label("default_case");
            m.Return();

            var bw = new Backwalker <Block, Instruction>(host, xfer, expSimp);

            Assert.IsTrue(bw.CanBackwalk());
            var ops = bw.BackWalk(block);

            Assert.AreEqual(3, ops.Count);
            Assert.AreEqual("cmp 48", ops[0].ToString());
            Assert.AreEqual("branch UGT", ops[1].ToString());
            Assert.AreEqual("* 4", ops[2].ToString());
        }
예제 #3
0
        /// <summary>
        /// RtlGoto transfers control to either a constant destination or
        /// a variable destination computed at run-time.
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool VisitGoto(RtlGoto g)
        {
            scanner.TerminateBlock(blockCur, ric.Address + ric.Length);
            var addrTarget = g.Target as Address;

            if (addrTarget != null)
            {
                var blockTarget = BlockFromAddress(ric.Address, addrTarget, blockCur.Procedure, state);
                var blockSource = scanner.FindContainingBlock(ric.Address);
                EnsureEdge(blockSource.Procedure, blockSource, blockTarget);
                return(false);
            }
            var mem = g.Target as MemoryAccess;

            if (mem != null)
            {
                if (mem.EffectiveAddress is Constant)
                {
                    // jmp [address]
                    var site = state.OnBeforeCall(this.stackReg, 4);            //$BUGBUG: hard coded.
                    Emit(new CallInstruction(g.Target, site));
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
            }
            ProcessIndirectControlTransfer(ric.Address, g);
            return(false);
        }
예제 #4
0
        public void BwDetectIndexRegister()
        {
            var edx  = m.Frame.EnsureRegister(Registers.edx);
            var xfer = new RtlGoto(m.Mem32(m.IAdd(m.Word32(0x10001234), m.IMul(edx, 4))), InstrClass.Transfer);
            var bw   = new Backwalker <Block, Instruction>(host, xfer, expSimp);

            Assert.AreSame(Registers.edx, bw.Index);
        }
예제 #5
0
        public SlicerResult VisitGoto(RtlGoto go)
        {
            var sr = go.Target.Accept(this, BackwardSlicerContext.Cond(RangeOf(go.Target)));

            if (JumpTableFormat == null)
            {
                JumpTableFormat = go.Target;
            }
            return(sr);
        }
예제 #6
0
        public void BwLoadDirect()
        {
            var r1 = m.Reg32("r1", 1);
            m.Assign(r1, m.Mem32(Constant.Word32(0x00123400)));
            var xfer = new RtlGoto(m.Mem32(m.IAdd(Constant.Word32(0x00113300), m.IMul(r1, 8))), InstrClass.Transfer);

            var bw = new Backwalker<Block, Instruction>(host, xfer, expSimp);
            Assert.IsTrue(bw.CanBackwalk());
            var ops = bw.BackWalk(m.Block);
            Assert.IsNull(ops, "Should have reported missing guard.");
        }
예제 #7
0
        /// <summary>
        /// RtlGoto transfers control to either a constant destination or
        /// a variable destination computed at run-time.
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool VisitGoto(RtlGoto g)
        {
            var blockFrom = blockCur;

            if ((g.Class & RtlClass.Delay) != 0)
            {
                // Get next instruction cluster.
                rtlStream.MoveNext();
                ProcessRtlCluster(rtlStream.Current);
            }
            scanner.TerminateBlock(blockCur, rtlStream.Current.Address + ric.Length);
            var addrTarget = g.Target as Address;

            if (addrTarget != null)
            {
                var blockTarget = BlockFromAddress(ric.Address, addrTarget, blockCur.Procedure, state);
                var blockSource = blockCur.IsSynthesized
                    ? blockCur
                    : scanner.FindContainingBlock(ric.Address);
                EnsureEdge(blockSource.Procedure, blockSource, blockTarget);
                if (ric.Address == addrTarget)
                {
                    var bt = BlockFromAddress(ric.Address, addrTarget, blockCur.Procedure, state);
                    EnsureEdge(blockSource.Procedure, blockFrom, bt);
                }
                return(false);
            }
            CallSite site;
            var      mem = g.Target as MemoryAccess;

            if (mem != null)
            {
                if (mem.EffectiveAddress is Constant)
                {
                    // jmp [address]
                    site = state.OnBeforeCall(this.stackReg, 4);            //$BUGBUG: hard coded.
                    Emit(new CallInstruction(g.Target, site));
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
            }
            if (ProcessIndirectControlTransfer(ric.Address, g))
            {
                return(false);
            }
            site = state.OnBeforeCall(this.stackReg, 4);    //$BUGBUG: hard coded
            Emit(new CallInstruction(g.Target, site));
            Emit(new ReturnInstruction());
            blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
            return(false);
        }
예제 #8
0
        public void BwZeroExtend()
        {
            var rax = m.Reg64("rax", 0);
            var eax = m.Reg32("eax", 0);
            var al = m.Reg8("al", 0);
            var ecx = m.Reg32("ecx", 1);
            var CZ = m.Flags("CZ");

            m.Assign(eax, m.Mem8(rax));
            m.Assign(CZ, m.Cond(m.ISub(al, 0x78)));
            m.BranchIf(m.Test(ConditionCode.UGT, CZ), "ldefault");
            m.Assign(ecx, m.Cast(PrimitiveType.Word32, al));
            var xfer = new RtlGoto(m.Mem32(m.IAdd(Constant.Word32(0x00411F40), m.IMul(ecx, 8))), InstrClass.Transfer);

            var bw = new Backwalker<Block, Instruction>(host, xfer, expSimp);
            Assert.IsTrue(bw.CanBackwalk());
            var ops = bw.BackWalk(m.Block);
            Assert.AreEqual(3, ops.Count);
            Assert.AreEqual("cmp 120", ops[0].ToString());
            Assert.AreEqual("branch UGT", ops[1].ToString());
            Assert.AreEqual("* 8", ops[2].ToString());
        }
예제 #9
0
        public void BwSignExtension()
        {
            var CVZNX = m.Flags("CVZNS");
            var CVZN  = m.Flags("CVZN");
            var VZN   = m.Flags("VZN");
            var d1    = m.Reg32("d1", 1);
            var v80   = m.Temp(PrimitiveType.Word32, "v80");
            var v82   = m.Temp(PrimitiveType.Word16, "v82");

            m.Assign(v80, m.ISub(d1, 0x28));
            m.Assign(CVZN, m.Cond(v80));
            m.BranchIf(m.Test(ConditionCode.GT, VZN), "default_label");

            m.Assign(d1, m.IAdd(d1, d1));
            m.Assign(CVZNX, m.Cond(d1));
            m.Assign(v82, m.Mem16(m.IAdd(m.Word32(0x001066A4), d1)));
            m.Assign(d1, m.Dpb(d1, v82, 0));
            m.Assign(CVZN, m.Cond(v82));
            var block = m.CurrentBlock;
            var xfer  = new RtlGoto(
                m.IAdd(
                    m.Word32(0x001066A2),
                    m.Cast(PrimitiveType.Int32, m.Cast(PrimitiveType.Int16, d1))),
                RtlClass.Transfer);

            m.Label("default_case");
            m.Return();

            var bw = new Backwalker <Block, Instruction>(host, xfer, expSimp);

            Assert.IsTrue(bw.CanBackwalk());
            var ops = bw.BackWalk(block);

            Assert.AreEqual(3, ops.Count);
            Assert.AreEqual("cmp 48", ops[0].ToString());
            Assert.AreEqual("branch UGT", ops[1].ToString());
            Assert.AreEqual("* 4", ops[2].ToString());
        }
예제 #10
0
        public RtlInstruction Goto(uint target)
        {
            var g = new RtlGoto(Address.Ptr32(target), RtlClass.Transfer);

            return(Emit(g));
        }
예제 #11
0
 public RtlInstruction Goto(uint target)
 {
     var g = new RtlGoto(Address.Ptr32(target), RtlClass.Transfer);
     return Emit(g);
 }
예제 #12
0
        public void BwIndexInMemoryAddress()
        {
            // samples of switch statement emitted
            // by the Microsoft VC compiler

            var ebp = m.Frame.EnsureRegister(Registers.ebp);
            var eax = m.Frame.EnsureRegister(Registers.eax);
            var edx = m.Frame.EnsureRegister(Registers.edx);
            
            // cmp [ebp-66],1D

            m.Assign(SCZO, m.Cond(m.ISub(m.LoadDw(m.ISub(ebp, 0xC4)), 0x1D)));
            var block0 = m.CurrentBlock;
            m.BranchIf(new TestCondition(ConditionCode.UGT, SCZO), "default");

            // mov edx,[ebp-66]
            // movzx eax,byte ptr [edx + 0x10000]
            // jmp [eax + 0x12000]

            m.Assign(edx, m.LoadDw(m.ISub(ebp, 0xC4)));
            m.Assign(eax, m.Cast(PrimitiveType.Word32, m.LoadB(m.IAdd(edx, 0x10000))));
            var xfer = new RtlGoto(m.LoadDw(m.IAdd(eax, 0x12000)), RtlClass.Transfer);

            var block1 = m.CurrentBlock;
            var bw = new Backwalker(host, xfer, expSimp);
            var ret = bw.BackwalkInstructions(Registers.eax, block1);
            Assert.AreEqual("None", bw.Index.ToString());
            Assert.AreEqual("Mem0[ebp - 0x000000C4:word32]", bw.IndexExpression.ToString());
            Assert.AreEqual(4, bw.JumpSize);
            Assert.IsTrue(ret);

            ret = bw.BackwalkInstructions(null, block0);
        }
예제 #13
0
 public void BwDetectIndexRegister()
 {
     var edx = m.Frame.EnsureRegister(Registers.edx);
     var xfer = new RtlGoto(m.LoadDw(m.IAdd(m.Word32(0x10001234), m.IMul(edx, 4))), RtlClass.Transfer);
     var bw = new Backwalker(host, xfer, expSimp);
     Assert.AreSame(Registers.edx, bw.Index);
 }
예제 #14
0
        /// <summary>
        /// RtlGoto transfers control to either a constant destination or
        /// a variable destination computed at run-time.
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool VisitGoto(RtlGoto g)
        {
            var blockFrom = blockCur;

            if ((g.Class & RtlClass.Delay) != 0)
            {
                // Get next instruction cluster.
                rtlStream.MoveNext();
                ProcessRtlCluster(rtlStream.Current);
            }
            CallSite site;

            scanner.TerminateBlock(blockCur, rtlStream.Current.Address + ric.Length);
            var addrTarget = g.Target as Address;

            if (addrTarget != null)
            {
                var impProc = scanner.GetImportedProcedure(addrTarget, this.ric.Address);
                if (impProc != null)
                {
                    site = state.OnBeforeCall(stackReg, arch.PointerType.Size);
                    var sig = impProc.Signature;
                    var chr = impProc.Characteristics;
                    if (chr != null && chr.IsAlloca)
                    {
                        return(ProcessAlloca(site, impProc));
                    }
                    EmitCall(CreateProcedureConstant(impProc), sig, chr, site);
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
                if (!program.SegmentMap.IsValidAddress(addrTarget))
                {
                    var jmpSite = state.OnBeforeCall(stackReg, arch.PointerType.Size);
                    GenerateCallToOutsideProcedure(jmpSite, addrTarget);
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
                var blockTarget = BlockFromAddress(ric.Address, addrTarget, blockCur.Procedure, state);
                var blockSource = blockCur.IsSynthesized
                    ? blockCur
                    : scanner.FindContainingBlock(ric.Address);
                EnsureEdge(blockSource.Procedure, blockSource, blockTarget);
                if (ric.Address == addrTarget)
                {
                    var bt = BlockFromAddress(ric.Address, addrTarget, blockCur.Procedure, state);
                    EnsureEdge(blockSource.Procedure, blockFrom, bt);
                }
                if (blockCur.Statements.Count == 0)
                {
                    //$REVIEW: we insert a statement into empty blocks to satisfy the BlockHasBeenScanned
                    // predicate. This should be done in a better way; perhaps by keeping track
                    // of scanned blocks in the Scanner class?
                    // The recursive scanning of basic blocks does need improvement;
                    // consider using a similar technique to Shingle scanner, where reachable
                    // statements are collected first, and basic blocks reconstructed afterwards.
                    Emit(new GotoInstruction(addrTarget));
                }
                return(false);
            }
            var mem = g.Target as MemoryAccess;

            if (mem != null)
            {
                if (mem.EffectiveAddress is Constant)
                {
                    // jmp [address]
                    site = state.OnBeforeCall(this.stackReg, 4);            //$BUGBUG: hard coded.
                    Emit(new CallInstruction(g.Target, site));
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
            }
            if (ProcessIndirectControlTransfer(ric.Address, g))
            {
                return(false);
            }
            site = state.OnBeforeCall(this.stackReg, 4);    //$BUGBUG: hard coded
            Emit(new CallInstruction(g.Target, site));
            Emit(new ReturnInstruction());
            blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
            return(false);
        }
예제 #15
0
        /// <summary>
        /// RtlGoto transfers control to either a constant destination or
        /// a variable destination computed at run-time.
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public bool VisitGoto(RtlGoto g)
        {
            var blockFrom = blockCur;

            if ((g.Class & RtlClass.Delay) != 0)
            {
                // Get next instruction cluster.
                rtlStream.MoveNext();
                ProcessRtlCluster(rtlStream.Current);
            }
            CallSite site;

            scanner.TerminateBlock(blockCur, rtlStream.Current.Address + ric.Length);
            var addrTarget = g.Target as Address;

            if (addrTarget != null)
            {
                var impProc = scanner.GetImportedProcedure(addrTarget, this.ric.Address);
                if (impProc != null)
                {
                    site = state.OnBeforeCall(stackReg, arch.PointerType.Size);
                    var sig = impProc.Signature;
                    var chr = impProc.Characteristics;
                    if (chr != null && chr.IsAlloca)
                    {
                        return(ProcessAlloca(site, impProc));
                    }
                    EmitCall(CreateProcedureConstant(impProc), sig, chr, site);
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
                if (!program.SegmentMap.IsValidAddress(addrTarget))
                {
                    var jmpSite = state.OnBeforeCall(stackReg, arch.PointerType.Size);
                    GenerateCallToOutsideProcedure(jmpSite, addrTarget);
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
                var trampoline = scanner.GetTrampoline(addrTarget);
                if (trampoline != null)
                {
                    var jmpSite = state.OnBeforeCall(stackReg, arch.PointerType.Size);
                    var sig     = trampoline.Signature;
                    var chr     = trampoline.Characteristics;
                    // Adjust stack to "hide" any pushed return value since
                    // currently Reko treats the return value as an implicit detail
                    // of the calling convention. Had the x86 rewriter explicity
                    // generated code to predecrement the stack pointer
                    // when encountering CALL instructions this would
                    // not be necessary.
                    if (sig.ReturnAddressOnStack != 0)
                    {
                        Emit(new Assignment(stackReg, new BinaryExpression(
                                                Operator.IAdd,
                                                stackReg.DataType,
                                                stackReg,
                                                Constant.Word(stackReg.DataType.Size, sig.ReturnAddressOnStack))));
                    }
                    EmitCall(CreateProcedureConstant(trampoline), sig, chr, jmpSite);
                    if (sig.ReturnAddressOnStack != 0)
                    {
                        //$TODO: make x86 calls' implicit storage explicit
                        // to avoid this hacky dance,
                        Emit(new Assignment(stackReg, new BinaryExpression(
                                                Operator.ISub,
                                                stackReg.DataType,
                                                stackReg,
                                                Constant.Word(stackReg.DataType.Size, sig.ReturnAddressOnStack))));
                    }
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
                var blockTarget = BlockFromAddress(ric.Address, addrTarget, blockCur.Procedure, state);
                var blockSource = blockCur.IsSynthesized
                    ? blockCur
                    : scanner.FindContainingBlock(ric.Address);
                EnsureEdge(blockSource.Procedure, blockSource, blockTarget);
                if (ric.Address == addrTarget)
                {
                    var bt = BlockFromAddress(ric.Address, addrTarget, blockCur.Procedure, state);
                    EnsureEdge(blockSource.Procedure, blockFrom, bt);
                }
                if (blockCur.Statements.Count == 0)
                {
                    //$REVIEW: we insert a statement into empty blocks to satisfy the BlockHasBeenScanned
                    // predicate. This should be done in a better way; perhaps by keeping track
                    // of scanned blocks in the Scanner class?
                    // The recursive scanning of basic blocks does need improvement;
                    // consider using a similar technique to Shingle scanner, where reachable
                    // statements are collected first, and basic blocks reconstructed afterwards.
                    Emit(new GotoInstruction(addrTarget));
                }
                return(false);
            }
            if (g.Target is MemoryAccess mem)
            {
                if (mem.EffectiveAddress is Constant)
                {
                    // jmp [address]
                    site = state.OnBeforeCall(this.stackReg, 4);            //$BUGBUG: hard coded.
                    Emit(new CallInstruction(g.Target, site));
                    Emit(new ReturnInstruction());
                    blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
                    return(false);
                }
            }
            if (ProcessIndirectControlTransfer(ric.Address, g))
            {
                return(false);
            }
            site = state.OnBeforeCall(this.stackReg, 4);    //$BUGBUG: hard coded
            Emit(new CallInstruction(g.Target, site));
            Emit(new ReturnInstruction());
            blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock);
            return(false);
        }