예제 #1
0
        public List<Address> BuildAux(Backwalker bw, Address addrFrom, ProcessorState state)
        {
            int limit = 0;
            int[] permutation = null;
            foreach (BackwalkOperation op in bw.Operations)
            {
                BackwalkError err = op as BackwalkError;
                if (err != null)
                {
                    return PostError(err.ErrorMessage, addrFrom, bw.VectorAddress);
                }
                var deref = op as BackwalkDereference;
                if (deref != null)
                {
                    permutation = BuildMapping(deref, limit);
                }
                limit = op.Apply(limit);
            }
            if (limit == 0)
                return PostError("Unable to determine limit", addrFrom, bw.VectorAddress);

            return BuildTable(
                bw.VectorAddress, 
                limit, 
                permutation,
                (bw.Stride == 1 || bw.Stride == 0) && bw.JumpSize > 1 
                    ? bw.JumpSize 
                    : bw.Stride,
                state);
        }
예제 #2
0
 public void BwAndMask()
 {
     var eax = m.Frame.EnsureRegister(Registers.eax);
     var bw = new Backwalker(host, new RtlGoto(m.LoadDw(m.IAdd(eax, 0x10000)), RtlClass.Transfer), expSimp);
     Assert.IsFalse(bw.BackwalkInstruction(m.Assign(eax, m.And(eax, 0x7))));
     Assert.AreSame(Registers.eax, bw.Index);
     Assert.AreEqual(0x10000ul, bw.VectorAddress.ToLinear());
     Assert.AreEqual("cmp 8", bw.Operations[0].ToString());
 }
예제 #3
0
 public List<Address> Build(Address addrTable, Address addrFrom, ProcessorState state)
 {
     bw = new Backwalker(this, null, null);
     if (bw == null)
         return null;
     List<BackwalkOperation> operations = bw.BackWalk(null);
     if (operations == null)
         return PostError("Unable to determine limit", addrFrom, addrTable);
     return BuildAux(bw, addrFrom, state);
 }
예제 #4
0
 public void BwAdd()
 {
     var eax = m.Frame.EnsureRegister(Registers.eax);
     var bw = new Backwalker(
         host,
         new RtlGoto(m.LoadDw(m.IAdd(eax, 0x10000)), RtlClass.Transfer),
         expSimp);
     Assert.IsTrue(bw.BackwalkInstruction(m.Assign(eax, m.IAdd(eax, eax))));
     Assert.AreSame(Registers.eax, bw.Index);
     Assert.AreEqual("* 2", bw.Operations[0].ToString());
     Assert.AreEqual(2, bw.Stride);
 }
예제 #5
0
        public List <Address> Build(Address addrTable, Address addrFrom, ProcessorState state)
        {
            bw = new Backwalker(this, null, null);
            if (bw == null)
            {
                return(null);
            }
            List <BackwalkOperation> operations = bw.BackWalk(null);

            if (operations == null)
            {
                return(PostError("Unable to determine limit", addrFrom, addrTable));
            }
            return(BuildAux(bw, addrFrom, state));
        }
예제 #6
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);
 }
예제 #7
0
		public void BwInc()
		{
            var state = arch.CreateProcessorState();
            var di = new Identifier("di", Registers.di.DataType, Registers.di);
			Backwalker bw = new Backwalker(host, new RtlGoto(new MemoryAccess(di, di.DataType), RtlClass.Transfer),
                new ExpressionSimplifier(state));
			var instrs = new StatementList(new Block(null, "foo"));
			instrs.Add(0, new Assignment(di, new BinaryExpression(Operator.IAdd, di.DataType, di, Constant.Word16(1))));
			bw.BackwalkInstructions(Registers.di, instrs);
			Assert.AreSame(Registers.di, bw.Index);
			Assert.AreEqual("+ 1", bw.Operations[0].ToString());
		}
예제 #8
0
        public void BwXorHiwordOfIndex()
        {
            var bx = m.Frame.EnsureRegister(Registers.bx);
            var bl = m.Frame.EnsureRegister(Registers.bl);
            var bh = m.Frame.EnsureRegister(Registers.bh);
            var bw = new Backwalker(host, new RtlGoto(m.LoadDw(m.IAdd(bx, 0x1000)), RtlClass.Transfer), expSimp);

            Assert.IsTrue(bw.BackwalkInstruction(
                m.Assign(bh, m.Xor(bh, bh))));
            Assert.AreSame(Registers.bl, bw.Index);
            Assert.AreEqual("& 255", bw.Operations[0].ToString());
        }
예제 #9
0
 public void BwLoadIndexed()
 {
     var eax = m.Frame.EnsureRegister(Registers.eax);
     var edx = m.Frame.EnsureRegister(Registers.edx);
     var al = m.Frame.EnsureRegister(Registers.al);
     m.Frame.EnsureFlagGroup(Registers.eflags, (uint)(FlagM.SF | FlagM.ZF | FlagM.CF | FlagM.OF), "SCZO", PrimitiveType.Byte);
     var bw = new Backwalker(host, new RtlGoto(m.LoadDw(m.IAdd(eax, 0x1000)), RtlClass.Transfer), expSimp);
     Assert.IsTrue(bw.BackwalkInstruction(
         m.Assign(al, m.LoadB(m.IAdd(edx, 0x1004)))));
     Assert.AreSame(Registers.edx, bw.Index);
 }
예제 #10
0
 public void BwMaskWithHoles()
 {
     var eax = m.Frame.EnsureRegister(Registers.eax);
     var bw = new Backwalker(host, new RtlGoto(m.LoadDw(m.IAdd(eax, 0x10000)), RtlClass.Transfer), expSimp);
     Assert.IsFalse(bw.BackwalkInstruction(m.Assign(eax, m.And(eax, 0x0A))));
     Assert.IsNull(bw.Index);
     Assert.AreEqual(0, bw.Operations.Count);
 }
예제 #11
0
        public void BwUnresolveableIndirect()
        {
            var eax = m.Reg32("eax", 0);
            var esi = m.Reg32("esi", 6);
            var Z = m.Frame.EnsureFlagGroup(Registers.eflags, 1, "Z", PrimitiveType.Bool);

            var xfer = new RtlCall(eax, 4, RtlClass.Transfer);
            m.Assign(eax, m.LoadDw(esi));
            m.Assign(Z, m.Cond(m.And(eax, eax)));
            m.BranchIf(m.Test(ConditionCode.EQ, Z), "null_ptr");
            m.Label("do_call");

            var bw = new Backwalker(host, xfer, expSimp);
            Assert.IsTrue(bw.CanBackwalk());
            Assert.AreEqual("eax", bw.Index.Name);
            bw.BackWalk(m.Block);
            Assert.AreEqual("None", bw.Index.ToString());
        }
예제 #12
0
        private void RunTest(IntelArchitecture arch, RtlTransfer rtlTransfer, string outputFile)
        {
            using (var fut = new FileUnitTester(outputFile))
            {
                m.Procedure.Write(false, fut.TextWriter);
                fut.TextWriter.Flush();

                var ibw = new Backwalker(host, rtlTransfer, expSimp);
                var bwoList = ibw.BackWalk(m.CurrentBlock);
                Assert.IsNotNull(bwoList);
                foreach (BackwalkOperation bwo in bwoList)
                {
                    fut.TextWriter.WriteLine(bwo);
                }
                fut.TextWriter.WriteLine("Index register: {0}", ibw.Index);
                fut.AssertFilesEqual();
            }
        }
예제 #13
0
        public bool ProcessIndirectControlTransfer(Address addrSwitch, RtlTransfer xfer)
        {
            List <Address>      vector;
            ImageMapVectorTable imgVector;
            Expression          swExp;
            UserIndirectJump    indJump;

            var listener = scanner.Services.RequireService <DecompilerEventListener>();

            if (program.User.IndirectJumps.TryGetValue(addrSwitch, out indJump))
            {
                vector    = indJump.Table.Addresses;
                swExp     = this.frame.EnsureIdentifier(indJump.IndexRegister);
                imgVector = indJump.Table;
            }
            else
            {
                var bw = new Backwalker <Block, Instruction>(new BackwalkerHost(this), xfer, eval);
                if (!bw.CanBackwalk())
                {
                    return(false);
                }
                var bwops = bw.BackWalk(blockCur);
                if (bwops == null || bwops.Count == 0)
                {
                    return(false);     //$REVIEW: warn?
                }
                Identifier idIndex = bw.Index != null
                    ? blockCur.Procedure.Frame.EnsureRegister(bw.Index)
                    : null;

                VectorBuilder builder = new VectorBuilder(scanner.Services, program, new DirectedGraphImpl <object>());
                if (bw.VectorAddress == null)
                {
                    return(false);
                }

                vector = builder.BuildAux(bw, addrSwitch, state);
                if (vector.Count == 0)
                {
                    var rdr = program.CreateImageReader(bw.VectorAddress);
                    if (!rdr.IsValid)
                    {
                        return(false);
                    }
                    // Can't determine the size of the table, but surely it has one entry?
                    var    addrEntry = arch.ReadCodeAddress(bw.Stride, rdr, state);
                    string msg;
                    if (this.program.SegmentMap.IsValidAddress(addrEntry))
                    {
                        vector.Add(addrEntry);
                        msg = "Can't determine size of jump vector; probing only one entry.";
                    }
                    else
                    {
                        // Nope, not even that.
                        msg = "No valid entries could be found in jump vector.";
                    }
                    var nav = listener.CreateJumpTableNavigator(program, addrSwitch, bw.VectorAddress, bw.Stride);
                    listener.Warn(nav, msg);
                    if (vector.Count == 0)
                    {
                        return(false);
                    }
                }
                imgVector = new ImageMapVectorTable(
                    bw.VectorAddress,
                    vector.ToArray(),
                    builder.TableByteSize);
                swExp = idIndex;
                if (idIndex == null || idIndex.Name == "None")
                {
                    swExp = bw.IndexExpression;
                }
            }
            ScanVectorTargets(xfer, vector);

            if (xfer is RtlGoto)
            {
                var blockSource = scanner.FindContainingBlock(ric.Address);
                blockCur = blockSource;
                foreach (Address addr in vector)
                {
                    var dest = scanner.FindContainingBlock(addr);
                    Debug.Assert(dest != null, "The block at address " + addr + "should have been enqueued.");
                    blockSource.Procedure.ControlGraph.AddEdge(blockSource, dest);
                }

                if (swExp == null)
                {
                    scanner.Warn(addrSwitch, "Unable to determine index variable for indirect jump.");
                    Emit(new ReturnInstruction());
                    blockSource.Procedure.ControlGraph.AddEdge(
                        blockSource,
                        blockSource.Procedure.ExitBlock);
                }
                else
                {
                    Emit(new SwitchInstruction(swExp, blockCur.Procedure.ControlGraph.Successors(blockCur).ToArray()));
                }
            }
            if (imgVector.Size > 0)
            {
                program.ImageMap.AddItemWithSize(imgVector.Address, imgVector);
            }
            else
            {
                program.ImageMap.AddItem(imgVector.Address, imgVector);
            }
            return(true);
        }
예제 #14
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);
        }
예제 #15
0
 public void BwJmp()
 {
     var eax = m.Frame.EnsureRegister(Registers.eax);
     var SCZO = m.Frame.EnsureFlagGroup(Registers.eflags, (uint)(FlagM.SF|FlagM.ZF|FlagM.CF|FlagM.OF), "SCZO", PrimitiveType.Byte);
     var bw = new Backwalker(host, new RtlGoto(m.LoadDw(m.IAdd(eax, 0x1000)), RtlClass.Transfer), expSimp);
     Assert.IsTrue(
         bw.BackwalkInstruction(
             m.BranchIf(
             new TestCondition(ConditionCode.UGT, SCZO),
             "Nizze").Instruction));
     Assert.AreEqual("branch UGT", bw.Operations[0].ToString());
     Assert.AreEqual("SCZO", bw.UsedFlagIdentifier.ToString());
 }
예제 #16
0
        public void BwTempRegister()
        {
            var v1 = m.Frame.CreateTemporary(PrimitiveType.Word32);
            var edi = m.Frame.CreateTemporary(PrimitiveType.Word32);
            var esi = m.Frame.EnsureRegister(Registers.esi);
            var xfer = new RtlCall(m.LoadDw(m.IAdd(esi, 40)), 4, RtlClass.Transfer);
            m.Assign(v1, m.LoadDw(edi));
            m.Assign(esi, v1);
            var bw = new Backwalker(host, xfer, expSimp);
            bool result;
            result = bw.BackwalkInstruction(m.Block.Statements[1].Instruction);
            result = bw.BackwalkInstruction(m.Block.Statements[0].Instruction);

            Assert.IsFalse(result);
            Assert.AreEqual("None", bw.Index.ToString());
        }
예제 #17
0
 public void BwComparison()
 {
     var eax = m.Frame.EnsureRegister(Registers.eax);
     var SCZO = m.Frame.EnsureFlagGroup(Registers.eflags, (uint)(FlagM.SF | FlagM.ZF | FlagM.CF | FlagM.OF), "SCZO", PrimitiveType.Byte);
     var bw = new Backwalker(host, new RtlGoto(m.LoadDw(m.IAdd(eax, 0x1000)), RtlClass.Transfer), expSimp);
     bw.UsedFlagIdentifier = m.Frame.EnsureFlagGroup(Registers.eflags,(uint)FlagM.CF, "C", PrimitiveType.Byte);
     Assert.IsFalse(
         bw.BackwalkInstruction(
             m.Assign(SCZO, new ConditionOf(m.ISub(eax, 3)))),
         "Encountering this comparison should terminate the backwalk");
     Assert.AreSame(Registers.eax, bw.Index);
     Assert.AreEqual("cmp 3", bw.Operations[0].ToString());
 }
예제 #18
0
        public void BwReg_00121()
        {
            var d0 = m.Reg32("d0", 0);
            var d3 = m.Reg32("d3", 3);
            var a5 = m.Reg32("a5", 5);
            var v38 = m.Temp(PrimitiveType.Word16, "v38");
            var v39 = m.Temp(PrimitiveType.Byte, "v39");
            var v40 = m.Temp(PrimitiveType.Word16, "v40");
            var VZN = m.Flags("VZN");
            var ZN = m.Flags("ZN");
            var C = m.Flags("C");
            var V = m.Flags("V");
            var CVZN = m.Flags("CVZN");
            var CVZNX = m.Flags("CVZNX");
            m.Assign(d0, d3);
            m.Assign(CVZN, m.Cond(d0));
            m.Assign(v38, m.And(m.Cast(PrimitiveType.Word16, d0), 0xF0));
            m.Assign(d0, m.Dpb(d0, v38, 0));
            m.Assign(ZN, m.Cond(v38));
            m.Assign(C, false);
            m.Assign(V, false);
            m.Assign(v39, m.Shl(m.Cast(PrimitiveType.Byte, d0), 2));
            m.Assign(d0, m.Dpb(d0, v39, 0));
            m.Assign(CVZNX, m.Cond(v39));
            m.Assign(v40, m.ISub(m.Cast(PrimitiveType.Word16, d0), 44));
            m.Assign(CVZN, m.Cond(v40));
            m.BranchIf(m.Test(ConditionCode.GT, VZN), "lDefault");
            m.Assign(a5, m.LoadDw(m.IAdd(Address.Ptr32(0x0000C046), d0)));
            var xfer = new RtlCall(a5, 4, RtlClass.Transfer);

            var bw = new Backwalker(host, xfer, expSimp);
            Assert.IsTrue(bw.CanBackwalk());
            Assert.AreEqual("a5", bw.Index.Name);
            bw.BackWalk(m.Block);
            Assert.AreEqual("v40", bw.IndexExpression.ToString());
        }
예제 #19
0
        public bool ProcessIndirectControlTransfer(Address addrSwitch, RtlTransfer xfer)
        {
            var bw = new Backwalker(new BackwalkerHost(this), xfer, eval);

            if (!bw.CanBackwalk())
            {
                return(false);
            }
            var bwops = bw.BackWalk(blockCur);

            if (bwops == null || bwops.Count == 0)
            {
                return(false);     //$REVIEW: warn?
            }
            var idIndex = blockCur.Procedure.Frame.EnsureRegister(bw.Index);

            VectorBuilder builder = new VectorBuilder(scanner, program, new DirectedGraphImpl <object>());

            if (bw.VectorAddress == null)
            {
                return(false);
            }

            List <Address> vector = builder.BuildAux(bw, addrSwitch, state);

            if (vector.Count == 0)
            {
                var addrNext = bw.VectorAddress + bw.Stride;
                var rdr      = scanner.CreateReader(bw.VectorAddress);
                if (!rdr.IsValid)
                {
                    return(false);
                }
                // Can't determine the size of the table, but surely it has one entry?
                var addrEntry = arch.ReadCodeAddress(bw.Stride, rdr, state);
                if (this.program.Image.IsValidAddress(addrEntry))
                {
                    vector.Add(addrEntry);
                    scanner.Warn(addrSwitch, "Can't determine size of jump vector; probing only one entry.");
                }
                else
                {
                    // Nope, not even that.
                    scanner.Warn(addrSwitch, "No valid entries could be found in jump vector.");
                }
            }

            //$TODO: mark the vector
            ScanVectorTargets(xfer, vector);

            if (xfer is RtlGoto)
            {
                var blockSource = scanner.FindContainingBlock(ric.Address);
                blockCur = blockSource;
                foreach (Address addr in vector)
                {
                    var dest = scanner.FindContainingBlock(addr);
                    Debug.Assert(dest != null, "The block at address " + addr + "should have been enqueued.");
                    blockSource.Procedure.ControlGraph.AddEdge(blockSource, dest);
                }
                Expression swExp = idIndex;
                if (idIndex.Name == "None")
                {
                    swExp = bw.IndexExpression;
                }
                if (swExp == null)
                {
                    throw new NotImplementedException();
                }
                Emit(new SwitchInstruction(swExp, blockCur.Procedure.ControlGraph.Successors(blockCur).ToArray()));
            }
            //vectorUses[wi.addrFrom] = new VectorUse(wi.Address, builder.IndexRegister);
            program.ImageMap.AddItem(bw.VectorAddress,
                                     new ImageMapVectorTable(xfer is RtlCall, vector.ToArray(), builder.TableByteSize));
            return(true);
        }