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); }
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()); }
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); }
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); }
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)); }
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); }
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()); }
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()); }
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); }
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); }
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()); }
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(); } }
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); }
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); }
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()); }
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()); }
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()); }
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()); }
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); }