public Block CloneBlock(Block blockOrig) { if (blockOrig == blockOrig.Procedure.ExitBlock) { return(null); } var succ = blockOrig.Succ.Count > 0 ? CloneBlock(blockOrig.Succ[0]) : null; var blockNew = new Block(procCalling, blockOrig.Name + "_in_" + procCalling.Name); foreach (var stm in blockOrig.Statements) { Statement = stm; blockNew.Statements.Add(new Statement( stm.LinearAddress, stm.Instruction.Accept(this), blockNew)); } procCalling.AddBlock(blockNew); if (succ == null) { procCalling.ControlGraph.AddEdge(blockNew, procCalling.ExitBlock); } else { procCalling.ControlGraph.AddEdge(blockNew, succ); } return(blockNew); }
public void Bwi_CallTerminatingProcedure_StopScanning() { proc = Procedure.Create(program.Architecture, "proc", Address.Ptr32(0x102000), new Frame(PrimitiveType.Ptr32)); var terminator = Procedure.Create(program.Architecture, "terminator", Address.Ptr32(0x0001000), new Frame(PrimitiveType.Ptr32)); terminator.Characteristics = new ProcedureCharacteristics { Terminates = true, }; block = proc.AddBlock("the_block"); arch.Setup(a => a.PointerType).Returns(PrimitiveType.Word32); scanner.Setup(s => s.FindContainingBlock(It.IsAny <Address>())).Returns(block); Given_NoImportedProcedure(); Given_NoInlinedCall(); scanner.Setup(s => s.ScanProcedure( It.IsNotNull <IProcessorArchitecture>(), It.IsAny <Address>(), It.IsAny <string>(), It.IsAny <ProcessorState>())) .Returns(terminator) .Verifiable(); scanner.Setup(s => s.TerminateBlock(It.IsNotNull <Block>(), It.IsNotNull <Address>())).Verifiable(); arch.Setup(a => a.FramePointerType).Returns(PrimitiveType.Ptr32); Given_SimpleTrace(trace); trace.Add(m => m.Call(Address.Ptr32(0x00102000), 4)); trace.Add(m => m.SideEffect(new ProcedureConstant(VoidType.Instance, new PseudoProcedure("shouldnt_decompile_this", VoidType.Instance, 0)))); var wi = CreateWorkItem(Address.Ptr32(0x2000)); wi.Process(); Assert.AreEqual(1, block.Statements.Count, "Should only have rewritten the Call to 'terminator'"); scanner.Verify(); }
public void Bwi_CallTerminatingProcedure_StopScanning() { proc = Procedure.Create(program.Architecture, "proc", Address.Ptr32(0x102000), new Frame(PrimitiveType.Ptr32)); var terminator = Procedure.Create(program.Architecture, "terminator", Address.Ptr32(0x0001000), new Frame(PrimitiveType.Ptr32)); terminator.Characteristics = new ProcedureCharacteristics { Terminates = true, }; block = proc.AddBlock("the_block"); arch.Stub(a => a.PointerType).Return(PrimitiveType.Word32); scanner.Stub(s => s.FindContainingBlock(Arg <Address> .Is.Anything)).Return(block); scanner.Stub(s => s.GetImportedProcedure(Arg <Address> .Is.Anything, Arg <Address> .Is.NotNull)).Return(null); scanner.Expect(s => s.ScanProcedure( Arg <Address> .Is.Anything, Arg <string> .Is.Anything, Arg <ProcessorState> .Is.Anything)) .Return(terminator); scanner.Expect(s => s.TerminateBlock(Arg <Block> .Is.NotNull, Arg <Address> .Is.NotNull)); arch.Stub(a => a.FramePointerType).Return(PrimitiveType.Ptr32); scanner.Stub(s => s.GetTrace(null, null, null)).IgnoreArguments().Return(trace); mr.ReplayAll(); trace.Add(m => m.Call(Address.Ptr32(0x00102000), 4)); trace.Add(m => m.SideEffect(new ProcedureConstant(VoidType.Instance, new PseudoProcedure("shouldnt_decompile_this", VoidType.Instance, 0)))); var wi = CreateWorkItem(Address.Ptr32(0x2000)); wi.Process(); Assert.AreEqual(1, block.Statements.Count, "Should only have rewritten the Call to 'terminator'"); mr.VerifyAll(); }
public Block BlockOf(string label, bool defer) { Block b; if (deferredBlocks.TryGetValue(label, out b)) { if (!defer) { deferredBlocks.Remove(label); labelMap.Add(label, b); } return(b); } if (!labelMap.TryGetValue(label, out b)) { b = proc.AddBlock("l" + label); if (defer) { deferredBlocks.Add(label, b); } else { labelMap.Add(label, b); } } return(b); }
/// <summary> /// Creates a small basic block, consisting solely of a 'call' followed by a 'return' /// instruction. /// </summary> /// <remarks> /// This is done when encountering tail calls (i.e. jumps) from one /// procedure into another. /// </remarks> /// <param name="addrFrom"></param> /// <param name="procOld"></param> /// <param name="procNew"></param> /// <returns></returns> public Block CreateCallRetThunk(Address addrFrom, Procedure procOld, Procedure procNew) { //$BUG: ReturnAddressOnStack property needs to be properly set, the // EvenOdd sample shows how this doesn't work currently. var blockName = string.Format( "{0}_thunk_{1}", Block.GenerateName(addrFrom), procNew.Name); var callRetThunkBlock = procOld.AddBlock(blockName); callRetThunkBlock.IsSynthesized = true; var linFrom = addrFrom.ToLinear(); callRetThunkBlock.Statements.Add( linFrom, new CallInstruction( new ProcedureConstant(Program.Platform.PointerType, procNew), new CallSite( procNew.Signature.ReturnAddressOnStack, 0))); Program.CallGraph.AddEdge(callRetThunkBlock.Statements.Last, procNew); callRetThunkBlock.Statements.Add(linFrom, new ReturnInstruction()); procOld.ControlGraph.AddEdge(callRetThunkBlock, procOld.ExitBlock); SetProcedureReturnAddressBytes(procOld, procNew.Frame.ReturnAddressSize, addrFrom); return(callRetThunkBlock); }
public void Setup() { mr = new MockRepository(); program = new Program(); proc = new Procedure("testProc", new Frame(PrimitiveType.Word32)); block = proc.AddBlock("l00100000"); trace = new RtlTrace(0x00100000); r0 = new Identifier("r0", PrimitiveType.Word32, new RegisterStorage("r0", 0, 0, PrimitiveType.Word32)); r1 = new Identifier("r1", PrimitiveType.Word32, new RegisterStorage("r1", 1, 0, PrimitiveType.Word32)); r2 = new Identifier("r2", PrimitiveType.Word32, new RegisterStorage("r2", 2, 0, PrimitiveType.Word32)); sp = new Identifier("sp", PrimitiveType.Word32, new RegisterStorage("sp", 15, 0, PrimitiveType.Word32)); grf = proc.Frame.EnsureFlagGroup(Registers.eflags, 3, "SCZ", PrimitiveType.Byte); var sc = new ServiceContainer(); var listener = mr.Stub<DecompilerEventListener>(); scanner = mr.StrictMock<IScanner>(); arch = mr.Stub<IProcessorArchitecture>(); program.Architecture = arch; program.SegmentMap = new SegmentMap( Address.Ptr32(0x00100000), new ImageSegment( ".text", new MemoryArea(Address.Ptr32(0x00100000), new byte[0x20000]), AccessMode.ReadExecute)); arch.Replay(); program.Platform = new DefaultPlatform(null, arch); arch.BackToRecord(); arch.Stub(s => s.StackRegister).Return((RegisterStorage)sp.Storage); arch.Stub(s => s.PointerType).Return(PrimitiveType.Pointer32); scanner.Stub(s => s.Services).Return(sc); sc.AddService<DecompilerEventListener>(listener); }
public void Setup() { mr = new MockRepository(); program = new Program(); proc = new Procedure(program.Architecture, "testProc", new Frame(PrimitiveType.Word32)); block = proc.AddBlock("l00100000"); trace = new RtlTrace(0x00100000); r0 = new Identifier("r0", PrimitiveType.Word32, new RegisterStorage("r0", 0, 0, PrimitiveType.Word32)); r1 = new Identifier("r1", PrimitiveType.Word32, new RegisterStorage("r1", 1, 0, PrimitiveType.Word32)); r2 = new Identifier("r2", PrimitiveType.Word32, new RegisterStorage("r2", 2, 0, PrimitiveType.Word32)); sp = new Identifier("sp", PrimitiveType.Word32, new RegisterStorage("sp", 15, 0, PrimitiveType.Word32)); grf = proc.Frame.EnsureFlagGroup(Registers.eflags, 3, "SCZ", PrimitiveType.Byte); var sc = new ServiceContainer(); var listener = mr.Stub <DecompilerEventListener>(); scanner = mr.StrictMock <IScanner>(); arch = mr.Stub <IProcessorArchitecture>(); program.Architecture = arch; program.SegmentMap = new SegmentMap( Address.Ptr32(0x00100000), new ImageSegment( ".text", new MemoryArea(Address.Ptr32(0x00100000), new byte[0x20000]), AccessMode.ReadExecute)); arch.Replay(); program.Platform = new DefaultPlatform(null, arch); arch.BackToRecord(); arch.StackRegister = (RegisterStorage)sp.Storage; arch.Stub(s => s.PointerType).Return(PrimitiveType.Ptr32); scanner.Stub(s => s.Services).Return(sc); sc.AddService <DecompilerEventListener>(listener); }
public void BwiUsePatch() { var addrStart = Address.Ptr32(0x00100000); trace.Add(m => m.Assign(r0, m.Mem8(m.Word16(0x0042)))); trace.Add(m => m.Assign(r1, 42)); Given_SimpleTrace(trace); Given_TransferPatch(addrStart.ToUInt32() + 4, 8, m => { m.BranchInMiddleOfInstruction(m.Eq(r0, 1), Address.Ptr32(0x00100100), InstrClass.ConditionalTransfer); m.BranchInMiddleOfInstruction(m.Eq(r0, 2), Address.Ptr32(0x00100200), InstrClass.ConditionalTransfer); m.BranchInMiddleOfInstruction(m.Eq(r0, 3), Address.Ptr32(0x00100300), InstrClass.ConditionalTransfer); m.Goto(Address.Ptr32(0x00100400)); }); Given_ExpectedBranchTarget(0x00100100, proc.AddBlock("case1")); Given_ExpectedBranchTarget(0x00100200, proc.AddBlock("case2")); Given_ExpectedBranchTarget(0x00100300, proc.AddBlock("case3")); Given_ExpectedBranchTarget(0x00100400, proc.AddBlock("default")); scanner.Setup(s => s.FindContainingBlock(addrStart)).Returns(block); scanner.Setup(s => s.FindContainingBlock(addrStart + 4)).Returns(block); var wi = CreateWorkItem(addrStart); wi.Process(); var expected = @"testProc_entry: case1: case2: case3: default: l00100000: r0 = Mem0[0x42<16>:byte] branch r0 == 1<32> case1 l00100004_1: branch r0 == 2<32> case2 l00100004_2: branch r0 == 3<32> case3 l00100004_3: goto 0x00100400<p32> goto default testProc_exit: "; AssertProcedureCode(expected, block.Procedure); }
private void BuildTest(IntelArchitecture arch, Address addr, IPlatform platform, Action <X86Assembler> m) { proc = new Procedure(arch, "test", addr, arch.CreateFrame()); block = proc.AddBlock("testblock"); var asm = new X86Assembler(sc, new DefaultPlatform(sc, arch), addr, new List <ImageSymbol>()); scanner = new Mock <IScanner>(); scanner.Setup(s => s.Services).Returns(sc); m(asm); lr = asm.GetImage(); this.state = arch.CreateProcessorState(); host = new RewriterHost( asm.ImportReferences, new Dictionary <string, FunctionType> { { "GetDC", new FunctionType( new Identifier("", new Pointer(VoidType.Instance, 32), new RegisterStorage("eax", 0, 0, PrimitiveType.Word32)), new [] { new Identifier("arg", new TypeReference( "HWND", new Pointer(VoidType.Instance, 32)), new StackArgumentStorage(4, new TypeReference( "HWND", new Pointer(VoidType.Instance, 32)))) }) { StackDelta = 4, } } }, new Dictionary <string, DataType>()); var rw = arch.CreateRewriter( lr.SegmentMap.Segments.Values.First().MemoryArea.CreateLeReader(addr), this.state, proc.Frame, host); this.program = new Program { Architecture = arch, SegmentMap = lr.SegmentMap, ImageMap = lr.ImageMap, Platform = platform, }; scanner.Setup(x => x.FindContainingBlock(It.IsAny <Address>())).Returns(block); scanner.Setup(x => x.GetTrace( It.IsAny <IProcessorArchitecture>(), It.IsAny <Address>(), It.IsAny <ProcessorState>(), It.IsAny <IStorageBinder>())).Returns(rw); scanner.Setup(x => x.Services).Returns(sc); wi = new BlockWorkitem(scanner.Object, program, arch, state, addr); }
protected Block BlockOf(string label) { if (!blocks.TryGetValue(label, out Block b)) { b = Procedure.AddBlock(label); blocks.Add(label, b); } return(b); }
private Block BlockOf(string label) { Block b; if (!blocks.TryGetValue(label, out b)) { b = Procedure.AddBlock(label); blocks.Add(label, b); } return(b); }
private void Given_ExpectedBranchTarget(uint uAddrDst, string blockName) { var block = proc.AddBlock(Address.Ptr32(uAddrDst), blockName); scanner.Setup(x => x.EnqueueJumpTarget( It.IsNotNull <Address>(), It.Is <Address>(a => a.ToUInt32() == uAddrDst), block.Procedure, It.IsAny <ProcessorState>())) .Returns(block); }
public void Bwi_RtlIf() { var followBlock = proc.AddBlock("l00100004"); using (mr.Record()) { arch.Stub(a => a.GetRegister(1)).Return((RegisterStorage)r1.Storage); arch.Stub(a => a.GetRegister(2)).Return((RegisterStorage)r2.Storage); arch.Stub(a => a.StackRegister).Return((RegisterStorage)r1.Storage); scanner.Stub(s => s.FindContainingBlock( Arg <Address> .Matches(a => a.ToLinear() == 0x00100000))).Return(block); scanner.Stub(s => s.FindContainingBlock( Arg <Address> .Matches(a => a.ToLinear() == 0x00100004))).Return(followBlock); scanner.Stub(s => s.Warn(null, null)).IgnoreArguments().WhenCalled(m => { var d = (Diagnostic)m.Arguments[1]; Debug.Print("{0}: {1}", d.GetType().Name, d.Message); }); scanner.Stub(s => s.EnqueueJumpTarget( Arg <Address> .Is.NotNull, Arg <Address> .Matches(a => a.ToLinear() == 0x00100004), Arg <Procedure> .Is.NotNull, Arg <ProcessorState> .Is.Anything)).Return(followBlock); scanner.Stub(s => s.GetTrace(null, null, null)).IgnoreArguments().Return(trace); } trace.Add(m => m.If(new TestCondition(ConditionCode.GE, grf), new RtlAssignment(r2, r1))); var wi = CreateWorkItem(Address.Ptr32(0x00100000), new FakeProcessorState(arch)); wi.Process(); var sw = new StringWriter(); mr.VerifyAll(); proc.Write(false, sw); var sExp = @"// testProc // Return size: 0 void testProc() testProc_entry: l00100000: branch Test(LT,SCZ) l00100004 // succ: l00100000_1 l00100004 l00100000_1: r2 = r1 // succ: l00100004 l00100004: testProc_exit: "; Assert.AreEqual(sExp, sw.ToString()); }
public void TrfPropagateToSuccessorBlocks() { Procedure proc = new Procedure("test", prog.Architecture.CreateFrame()); var frame = proc.Frame; Identifier ecx = m.Register(1); Identifier edx = m.Register(2); Identifier ebx = m.Register(3); Block b = proc.AddBlock("b"); Block t = proc.AddBlock("t"); Block e = proc.AddBlock("e"); proc.ControlGraph.AddEdge(b, e); proc.ControlGraph.AddEdge(b, t); flow[t] = new BlockFlow(t, null, new SymbolicEvaluationContext(prog.Architecture, frame)); flow[e] = new BlockFlow(e, null, new SymbolicEvaluationContext(prog.Architecture, frame)); trf = CreateTrashedRegisterFinder(prog); CreateBlockFlow(b, frame); trf.StartProcessingBlock(b); trf.RegisterSymbolicValues[(RegisterStorage)ecx.Storage] = Constant.Invalid; trf.RegisterSymbolicValues[(RegisterStorage)edx.Storage] = ebx; flow[e].SymbolicIn.RegisterState[(RegisterStorage)ecx.Storage] = edx; flow[e].SymbolicIn.RegisterState[(RegisterStorage)edx.Storage] = ebx; flow[t].SymbolicIn.RegisterState[(RegisterStorage)ecx.Storage] = Constant.Invalid; flow[t].SymbolicIn.RegisterState[(RegisterStorage)edx.Storage] = edx; trf.PropagateToSuccessorBlock(e); trf.PropagateToSuccessorBlock(t); Assert.AreEqual(2, proc.ControlGraph.Successors(b).Count); Assert.AreEqual("<invalid>", flow[e].SymbolicIn.RegisterState[(RegisterStorage)ecx.Storage].ToString(), "trash & r2 => trash"); Assert.AreEqual("ebx", flow[e].SymbolicIn.RegisterState[(RegisterStorage)edx.Storage].ToString(), "ebx & ebx => ebx"); Assert.AreEqual("<invalid>", flow[e].SymbolicIn.RegisterState[(RegisterStorage)ecx.Storage].ToString(), "trash & r2 => trash"); Assert.AreEqual("ebx", flow[e].SymbolicIn.RegisterState[(RegisterStorage)edx.Storage].ToString(), "ebx & ebx => ebx"); Assert.AreEqual("<invalid>", flow[t].SymbolicIn.RegisterState[(RegisterStorage)ecx.Storage].ToString(), "trash & trash => trash"); Assert.AreEqual("<invalid>", flow[t].SymbolicIn.RegisterState[(RegisterStorage)edx.Storage].ToString(), "r3 & r2 => trash"); }
private void BuildTest(IntelArchitecture arch, Address addr, IPlatform platform, Action <X86Assembler> m) { this.arch = new X86ArchitectureFlat32(); proc = new Procedure("test", arch.CreateFrame()); block = proc.AddBlock("testblock"); this.state = arch.CreateProcessorState(); var asm = new X86Assembler(sc, new DefaultPlatform(sc, arch), addr, new List <ImageSymbol>()); scanner = mr.StrictMock <IScanner>(); m(asm); lr = asm.GetImage(); host = new RewriterHost(asm.ImportReferences, new Dictionary <string, ProcedureSignature> { { "GetDC", new ProcedureSignature( new Identifier("", new Pointer(VoidType.Instance, 4), new RegisterStorage("eax", 0, 0, PrimitiveType.Word32)), new Identifier("arg", new TypeReference( "HWND", new Pointer(VoidType.Instance, 4)), new StackArgumentStorage(0, new TypeReference( "HWND", new Pointer(VoidType.Instance, 4))))) { StackDelta = 4, } } }); var rw = arch.CreateRewriter( lr.SegmentMap.Segments.Values.First().MemoryArea.CreateLeReader(addr), this.state, proc.Frame, host); var prog = new Program { Architecture = arch, SegmentMap = lr.SegmentMap, ImageMap = lr.ImageMap, Platform = platform, }; using (mr.Record()) { scanner.Stub(x => x.FindContainingBlock(Arg <Address> .Is.Anything)).Return(block); scanner.Stub(x => x.GetTrace(null, null, null)).IgnoreArguments().Return(rw); } wi = new BlockWorkitem(scanner, prog, state, addr); }
public override void Process() { var movedBlocks = new HashSet <Block>(); var stack = new Stack <IEnumerator <Block> >(); stack.Push(new Block[] { Block }.Cast <Block>().GetEnumerator()); while (stack.Count != 0) { DumpBlocks(Block.Procedure); var e = stack.Peek(); if (!e.MoveNext()) { stack.Pop(); continue; } var b = e.Current; if (b.Procedure == ProcNew || b == b.Procedure.ExitBlock || b.Procedure.EntryBlock.Succ[0] == b) { continue; } trace.Verbose("PBW: Visiting block {0}, stack depth {1}", b.DisplayName, stack.Count); var replacer = new IdentifierRelocator(b.Procedure.Frame, ProcNew.Frame); b.Procedure.RemoveBlock(b); ProcNew.AddBlock(b); b.Procedure = ProcNew; movedBlocks.Add(b); foreach (var stm in b.Statements) { if (stm.LinearAddress == 0x00000000000009c4) { stm.ToString(); } stm.Instruction = replacer.ReplaceIdentifiers(stm.Instruction); } if (b.Succ.Count > 0) { stack.Push(b.Succ.GetEnumerator()); } } foreach (var b in movedBlocks) { FixExitEdges(b); FixInboundEdges(b); FixOutboundEdges(b); // SanityCheck(b); } }
/// <summary> /// Inserts a frame pointer assignment at the beginning of the procedure /// </summary> /// <remarks> /// The frame pointer assignment needs a block of its own, as placing it in the /// "entryBlock" wreaks havoc with SSA assignments &c. /// </remarks> public void InsertFramePointerAssignment(IProcessorArchitecture arch) { Block b = proc.AddBlock(proc.Name + "_frame_asgn"); Block s = proc.EntryBlock.Succ[0]; proc.ControlGraph.RemoveEdge(proc.EntryBlock, s); proc.ControlGraph.AddEdge(proc.EntryBlock, b); proc.ControlGraph.AddEdge(b, s); StructureType st = new StructureType(proc.Name + "_frame_t", 0); Identifier frame = proc.Frame.CreateTemporary(proc.Name + "_frame", st); b.Statements.Add( 0, new Assignment( proc.Frame.FramePointer, new UnaryExpression(Operator.AddrOf, arch.FramePointerType, frame))); }
/// <summary> /// Creates a small basic block, consisting solely of a 'call' followed by a 'return' /// instruction. /// </summary> /// <param name="addrFrom"></param> /// <param name="procOld"></param> /// <param name="procNew"></param> /// <returns></returns> public Block CreateCallRetThunk(Address addrFrom, Procedure procOld, Procedure procNew) { var blockName = string.Format( "{0}_thunk_{1}", GenerateBlockName(addrFrom), procNew.Name); var callRetThunkBlock = procOld.AddBlock(blockName); callRetThunkBlock.Statements.Add(0, new CallInstruction( new ProcedureConstant(program.Platform.PointerType, procNew), new CallSite(procNew.Signature.ReturnAddressOnStack, 0))); program.CallGraph.AddEdge(callRetThunkBlock.Statements.Last, procNew); callRetThunkBlock.Statements.Add(0, new ReturnInstruction()); procOld.ControlGraph.AddEdge(callRetThunkBlock, procOld.ExitBlock); SetProcedureReturnAddressBytes(procOld, procNew.Frame.ReturnAddressSize, addrFrom); return(callRetThunkBlock); }
public override void Process() { var movedBlocks = new HashSet <Block>(); var stack = new Stack <IEnumerator <Block> >(); stack.Push(new Block[] { Block }.Cast <Block>().GetEnumerator()); var replacer = new IdentifierReplacer(ProcNew.Frame); while (stack.Count != 0) { DumpBlocks(Block.Procedure); var e = stack.Peek(); if (!e.MoveNext()) { stack.Pop(); continue; } var b = e.Current; if (b.Procedure == ProcNew || b == b.Procedure.ExitBlock || b.Procedure.EntryBlock.Succ[0] == b) { continue; } Debug.Print("PromoteBlock visiting block {0}", b.Name); b.Procedure.RemoveBlock(b); ProcNew.AddBlock(b); b.Procedure = ProcNew; movedBlocks.Add(b); foreach (var stm in b.Statements) { stm.Instruction = replacer.ReplaceIdentifiers(stm.Instruction); } if (b.Succ.Count > 0) { stack.Push(b.Succ.GetEnumerator()); } } foreach (var b in movedBlocks) { FixExitEdges(b); FixInboundEdges(b); FixOutboundEdges(b); } }
public void Setup() { mr = new MockRepository(); program = new Program(); proc = new Procedure("testProc", new Frame(PrimitiveType.Word32)); block = proc.AddBlock("l00100000"); trace = new RtlTrace(0x00100000); r0 = new Identifier("r0", PrimitiveType.Word32, new RegisterStorage("r0", 0, 0, PrimitiveType.Word32)); r1 = new Identifier("r1", PrimitiveType.Word32, new RegisterStorage("r1", 1, 0, PrimitiveType.Word32)); r2 = new Identifier("r2", PrimitiveType.Word32, new RegisterStorage("r2", 2, 0, PrimitiveType.Word32)); grf = proc.Frame.EnsureFlagGroup(Registers.eflags, 3, "SCZ", PrimitiveType.Byte); scanner = mr.StrictMock<IScanner>(); arch = mr.DynamicMock<IProcessorArchitecture>(); arch.Stub(s => s.PointerType).Return(PrimitiveType.Pointer32); program.Architecture = arch; arch.Replay(); program.Platform = new DefaultPlatform(null, arch); arch.BackToRecord(); }
public void Setup() { mr = new MockRepository(); program = new Program(); proc = new Procedure("testProc", new Frame(PrimitiveType.Word32)); block = proc.AddBlock("l00100000"); trace = new RtlTrace(0x00100000); r0 = new Identifier("r0", PrimitiveType.Word32, new RegisterStorage("r0", 0, 0, PrimitiveType.Word32)); r1 = new Identifier("r1", PrimitiveType.Word32, new RegisterStorage("r1", 1, 0, PrimitiveType.Word32)); r2 = new Identifier("r2", PrimitiveType.Word32, new RegisterStorage("r2", 2, 0, PrimitiveType.Word32)); grf = proc.Frame.EnsureFlagGroup(Registers.eflags, 3, "SCZ", PrimitiveType.Byte); scanner = mr.StrictMock <IScanner>(); arch = mr.DynamicMock <IProcessorArchitecture>(); arch.Stub(s => s.PointerType).Return(PrimitiveType.Pointer32); program.Architecture = arch; arch.Replay(); program.Platform = new DefaultPlatform(null, arch); arch.BackToRecord(); }
public Block CloneBlock(Block blockOrig) { if (blockOrig == blockOrig.Procedure.ExitBlock) { return(null); } Block blockNew; if (mpBlocks.TryGetValue(blockOrig, out blockNew)) { return(blockNew); } blockNew = new Block(procCalling, blockOrig.Name + "_in_" + procCalling.Name); blockNew.Address = blockOrig.Address; mpBlocks.Add(blockOrig, blockNew); var succ = blockOrig.Succ.Count > 0 ? CloneBlock(blockOrig.Succ[0]) : null; foreach (var stm in blockOrig.Statements) { Statement = stm; StatementNew = new Statement( stm.LinearAddress, null, blockNew); StatementNew.Instruction = stm.Instruction.Accept(this); blockNew.Statements.Add(StatementNew); } procCalling.AddBlock(blockNew); if (succ == null) { procCalling.ControlGraph.AddEdge(blockNew, procCalling.ExitBlock); } else { procCalling.ControlGraph.AddEdge(blockNew, succ); } return(blockNew); }
public void Setup() { program = new Program(); trace = new RtlTrace(0x00100000); r0 = new Identifier("r0", PrimitiveType.Word32, new RegisterStorage("r0", 0, 0, PrimitiveType.Word32)); r1 = new Identifier("r1", PrimitiveType.Word32, new RegisterStorage("r1", 1, 0, PrimitiveType.Word32)); r2 = new Identifier("r2", PrimitiveType.Word32, new RegisterStorage("r2", 2, 0, PrimitiveType.Word32)); sp = new Identifier("sp", PrimitiveType.Word32, new RegisterStorage("sp", 15, 0, PrimitiveType.Word32)); var sc = new ServiceContainer(); var listener = new Mock <DecompilerEventListener>(); scanner = new Mock <IScanner>(); arch = new Mock <IProcessorArchitecture>(); arch.Setup(a => a.Name).Returns("FakeArch"); proc = new Procedure(arch.Object, "testProc", Address.Ptr32(0x00100000), new Frame(PrimitiveType.Word32)); block = proc.AddBlock(proc.EntryAddress, "l00100000"); grf = proc.Frame.EnsureFlagGroup(Registers.eflags, 3, "SCZ", PrimitiveType.Byte); program.Architecture = arch.Object; program.SegmentMap = new SegmentMap( Address.Ptr32(0x00100000), new ImageSegment( ".text", new ByteMemoryArea(Address.Ptr32(0x00100000), new byte[0x20000]), AccessMode.ReadExecute)); program.Platform = new DefaultPlatform(sc, arch.Object); arch.Setup(a => a.StackRegister).Returns((RegisterStorage)sp.Storage); arch.Setup(s => s.PointerType).Returns(PrimitiveType.Ptr32); arch.Setup(s => s.CreateFrameApplicationBuilder( It.IsAny <IStorageBinder>(), It.IsAny <CallSite>(), It.IsAny <Expression>())) .Returns((IStorageBinder frame, CallSite site, Expression callee) => new FrameApplicationBuilder(arch.Object, frame, site, callee, false)); scanner.Setup(s => s.Services).Returns(sc); sc.AddService <DecompilerEventListener>(listener.Object); }
private StructureNode NewNode(string name) { return(new StructureNode(proc.AddBlock(name), nodeCount++)); }
private void BuildTest(IntelArchitecture arch, Address addr, Platform platform, Action<X86Assembler> m) { this.arch = new IntelArchitecture(ProcessorMode.Protected32); proc = new Procedure("test", arch.CreateFrame()); block = proc.AddBlock("testblock"); this.state = arch.CreateProcessorState(); var asm = new X86Assembler(arch, addr, new List<EntryPoint>()); scanner = repository.StrictMock<IScanner>(); m(asm); lr = asm.GetImage(); host = new RewriterHost(asm.ImportReferences, new Dictionary<string, ProcedureSignature> { { "GetDC", new ProcedureSignature( new Identifier("", new Pointer(VoidType.Instance, 4), new RegisterStorage("eax", 0, PrimitiveType.Word32)), new Identifier("arg", new TypeReference( "HWND", new Pointer(VoidType.Instance, 4)), new StackArgumentStorage(0, new TypeReference( "HWND", new Pointer(VoidType.Instance, 4))))) { StackDelta = 4, } } }); var rw = arch.CreateRewriter(lr.Image.CreateLeReader(addr), this.state, proc.Frame, host); var prog = new Program { Architecture = arch, Image = lr.Image, ImageMap = lr.ImageMap, Platform = platform, }; using (repository.Record()) { scanner.Stub(x => x.FindContainingBlock(Arg<Address>.Is.Anything)).Return(block); scanner.Stub(x => x.GetTrace(null, null, null)).IgnoreArguments().Return(rw); } wi = new BlockWorkitem(scanner, prog, state, addr); }
public void TrfPropagateToSuccessorBlocks() { Procedure proc = new Procedure("test", program.Architecture.CreateFrame()); var frame = proc.Frame; Identifier ecx = m.Register(1); Identifier edx = m.Register(2); Identifier ebx = m.Register(3); Block b = proc.AddBlock("b"); Block t = proc.AddBlock("t"); Block e = proc.AddBlock("e"); proc.ControlGraph.AddEdge(b, e); proc.ControlGraph.AddEdge(b, t); flow[t] = new BlockFlow(t, null, new SymbolicEvaluationContext(program.Architecture, frame)); flow[e] = new BlockFlow(e, null, new SymbolicEvaluationContext(program.Architecture, frame)); trf = CreateTrashedRegisterFinder(program); CreateBlockFlow(b, frame); trf.StartProcessingBlock(b); trf.RegisterSymbolicValues[(RegisterStorage) ecx.Storage] = Constant.Invalid; trf.RegisterSymbolicValues[(RegisterStorage) edx.Storage] = ebx; flow[e].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage] = edx; flow[e].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage] = ebx; flow[t].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage] = Constant.Invalid; flow[t].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage] = edx; trf.PropagateToSuccessorBlock(e); trf.PropagateToSuccessorBlock(t); Assert.AreEqual(2, proc.ControlGraph.Successors(b).Count); Assert.AreEqual("<invalid>", flow[e].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage].ToString(), "trash & r2 => trash"); Assert.AreEqual("ebx", flow[e].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage].ToString(), "ebx & ebx => ebx"); Assert.AreEqual("<invalid>", flow[e].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage].ToString(), "trash & r2 => trash"); Assert.AreEqual("ebx", flow[e].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage].ToString(), "ebx & ebx => ebx"); Assert.AreEqual("<invalid>", flow[t].SymbolicIn.RegisterState[(RegisterStorage) ecx.Storage].ToString(), "trash & trash => trash"); Assert.AreEqual("<invalid>", flow[t].SymbolicIn.RegisterState[(RegisterStorage) edx.Storage].ToString(), "r3 & r2 => trash"); }
/// <summary> /// Creates a small basic block, consisting solely of a 'call' followed by a 'return' /// instruction. /// </summary> /// <param name="addrFrom"></param> /// <param name="procOld"></param> /// <param name="procNew"></param> /// <returns></returns> public Block CreateCallRetThunk(Address addrFrom, Procedure procOld, Procedure procNew) { //$BUG: ReturnAddressOnStack property needs to be properly set, the // EvenOdd sample shows how this doesn't work currently. var blockName = string.Format( "{0}_thunk_{1}", Block.GenerateName(addrFrom), procNew.Name); var callRetThunkBlock = procOld.AddBlock(blockName); callRetThunkBlock.IsSynthesized = true; var linFrom = addrFrom.ToLinear(); callRetThunkBlock.Statements.Add( addrFrom.ToLinear(), new CallInstruction( new ProcedureConstant(program.Platform.PointerType, procNew), new CallSite( procNew.Signature.ReturnAddressOnStack, 0))); program.CallGraph.AddEdge(callRetThunkBlock.Statements.Last, procNew); callRetThunkBlock.Statements.Add(linFrom, new ReturnInstruction()); procOld.ControlGraph.AddEdge(callRetThunkBlock, procOld.ExitBlock); SetProcedureReturnAddressBytes(procOld, procNew.Frame.ReturnAddressSize, addrFrom); return callRetThunkBlock; }
/// <summary> /// Creates a small basic block, consisting solely of a 'call' followed by a 'return' /// instruction. /// </summary> /// <param name="addrFrom"></param> /// <param name="procOld"></param> /// <param name="procNew"></param> /// <returns></returns> public Block CreateCallRetThunk(Address addrFrom, Procedure procOld, Procedure procNew) { var blockName = string.Format( "{0}_thunk_{1}", GenerateBlockName(addrFrom), procNew.Name); var callRetThunkBlock = procOld.AddBlock(blockName); callRetThunkBlock.Statements.Add(0, new CallInstruction( new ProcedureConstant(program.Platform.PointerType, procNew), new CallSite(procNew.Signature.ReturnAddressOnStack, 0))); program.CallGraph.AddEdge(callRetThunkBlock.Statements.Last, procNew); callRetThunkBlock.Statements.Add(0, new ReturnInstruction()); procOld.ControlGraph.AddEdge(callRetThunkBlock, procOld.ExitBlock); SetProcedureReturnAddressBytes(procOld, procNew.Frame.ReturnAddressSize, addrFrom); return callRetThunkBlock; }
private void Given_DummyBlock(Procedure proc) { var block = proc.AddBlock(Address.Ptr32(0x100), "0x100"); proc.ControlGraph.AddEdge(proc.EntryBlock, block); }
public void Bwi_CallTerminatingProcedure_StopScanning() { proc = Procedure.Create("proc", Address.Ptr32(0x002000), new Frame(PrimitiveType.Pointer32)); var terminator = Procedure.Create("terminator", Address.Ptr32(0x0001000), new Frame(PrimitiveType.Pointer32)); terminator.Characteristics = new ProcedureCharacteristics { Terminates = true, }; block = proc.AddBlock("the_block"); scanner = mr.StrictMock<IScanner>(); arch.Stub(a => a.PointerType).Return(PrimitiveType.Word32); scanner.Stub(s => s.FindContainingBlock(Arg<Address>.Is.Anything)).Return(block); scanner.Stub(s => s.GetCallSignatureAtAddress(Arg<Address>.Is.Anything)).Return(null); scanner.Stub(s => s.GetImportedProcedure(Arg<Address>.Is.Anything, Arg<Address>.Is.NotNull)).Return(null); scanner.Expect(s => s.ScanProcedure( Arg<Address>.Is.Anything, Arg<string>.Is.Anything, Arg<ProcessorState>.Is.Anything)) .Return(terminator); scanner.Expect(s => s.TerminateBlock(Arg<Block>.Is.NotNull, Arg<Address>.Is.NotNull)); arch.Stub(a => a.FramePointerType).Return(PrimitiveType.Pointer32); scanner.Stub(s => s.GetTrace(null, null, null)).IgnoreArguments().Return(trace); mr.ReplayAll(); trace.Add(m => m.Call(Address.Ptr32(0x0001000), 4)); trace.Add(m => m.SideEffect(new ProcedureConstant(VoidType.Instance, new PseudoProcedure("shouldnt_decompile_this", VoidType.Instance, 0)))); var wi = CreateWorkItem(Address.Ptr32(0x2000), new FakeProcessorState(arch)); wi.ProcessInternal(); Assert.AreEqual(1, block.Statements.Count, "Should only have rewritten the Call to 'terminator'"); mr.VerifyAll(); }
private void BuildTest(IntelArchitecture arch, Address addr, IPlatform platform, Action<X86Assembler> m) { proc = new Procedure("test", arch.CreateFrame()); block = proc.AddBlock("testblock"); this.state = arch.CreateProcessorState(); var asm = new X86Assembler(sc, new DefaultPlatform(sc, arch), addr, new List<ImageSymbol>()); scanner = mr.StrictMock<IScanner>(); scanner.Stub(s => s.Services).Return(sc); m(asm); lr = asm.GetImage(); host = new RewriterHost( asm.ImportReferences, new Dictionary<string, FunctionType> { { "GetDC", new FunctionType( new Identifier("", new Pointer(VoidType.Instance, 4), new RegisterStorage("eax", 0, 0, PrimitiveType.Word32)), new [] { new Identifier("arg", new TypeReference( "HWND", new Pointer(VoidType.Instance, 4)), new StackArgumentStorage(4, new TypeReference( "HWND", new Pointer(VoidType.Instance, 4)))) }) { StackDelta = 4, } } }, new Dictionary<string, DataType>()); var rw = arch.CreateRewriter( lr.SegmentMap.Segments.Values.First().MemoryArea.CreateLeReader(addr), this.state, proc.Frame, host); this.program = new Program { Architecture = arch, SegmentMap = lr.SegmentMap, ImageMap = lr.ImageMap, Platform = platform, }; using (mr.Record()) { scanner.Stub(x => x.FindContainingBlock(Arg<Address>.Is.Anything)).Return(block); scanner.Stub(x => x.GetTrace(null, null, null)).IgnoreArguments().Return(rw); scanner.Stub(x => x.Services).Return(sc); } wi = new BlockWorkitem(scanner, program, state, addr); }