예제 #1
0
        public void HPSC_ResolveBlockConflicts_RemoveDirectlyCalledAddress()
        {
            var calledAddr = Address.Ptr32(0x5678);
            var wrongBlock = Given_Block(0x1234);

            Given_Instrs(wrongBlock, m =>
            {
                m.Call(calledAddr, 4);
            });
            var firstBlock = Given_Block(0x1235);

            Given_Instrs(firstBlock, m =>
            {
                m.Assign(m.Mem32(m.Word32(0x2222)), 0);
            });
            var lastBlock = Given_Block(0x1240);

            Given_Instrs(lastBlock, m =>
            {
                m.Return(4, 0);
            });
            var cfg = new DiGraph <RtlBlock>();

            cfg.AddNode(wrongBlock);
            cfg.AddNode(firstBlock);
            cfg.AddNode(lastBlock);
            cfg.AddEdge(firstBlock, lastBlock);
            var sr = CreateScanResults(cfg);

            sr.DirectlyCalledAddresses.Add(calledAddr, 1);

            ResolveBlockConflicts(sr);

            Assert.AreEqual(0, sr.DirectlyCalledAddresses.Count);
        }
예제 #2
0
        private void RemoveInvalidBlocks(ScanResults sr)
        {
            var revGraph = new DiGraph <RtlBlock>();
            var invalid  = new RtlBlock(null !, "<invalid>");

            revGraph.AddNode(invalid);
            foreach (var b in sr.ICFG.Nodes)
            {
                revGraph.AddNode(b);
            }
            foreach (var b in sr.ICFG.Nodes)
            {
                foreach (var s in sr.ICFG.Successors(b))
                {
                    revGraph.AddEdge(s, b);
                }
                if (!b.IsValid)
                {
                    revGraph.AddEdge(invalid, b);
                }
            }

            // Find the transitive closure of invalid nodes.

            var invalidNodes = new DfsIterator <RtlBlock>(revGraph)
                               .PreOrder(invalid)
                               .ToList();

            foreach (var n in invalidNodes.Where(nn => nn != invalid))
            {
                sr.ICFG.RemoveNode(n);
                sr.DirectlyCalledAddresses.Remove(n.Address);
                // Debug.Print("Removed invalid node {0}", n.Address);  // commented out as this becomes very verbose.
            }
        }
예제 #3
0
        public DiGraph <RtlBlock> BuildIcfg(Dictionary <Address, block> blocks)
        {
            var icfg      = new DiGraph <RtlBlock>();
            var map       = new Dictionary <Address, RtlBlock>();
            var rtlBlocks =
                from b in blocks.Values
                join i in sr.FlatInstructions.Values on b.id equals i.block_id into instrs
                orderby b.id
                select new RtlBlock(b.id, b.id.GenerateName("l", ""))
            {
                Instructions = instrs.Select(x => x.rtl).ToList()
            };

            foreach (var rtlBlock in rtlBlocks)
            {
                map[rtlBlock.Address] = rtlBlock;
                icfg.AddNode(rtlBlock);
            }
            foreach (var edge in sr.FlatEdges)
            {
                if (!map.TryGetValue(edge.first, out RtlBlock from) ||
                    !map.TryGetValue(edge.second, out RtlBlock to))
                {
                    continue;
                }
                icfg.AddEdge(from, to);
            }
            return(icfg);
        }
예제 #4
0
        public void AddEdge(DiGraph <Address> g, Address from, Address to)
        {
#if !not_LinQ
            if (from == Bad)
            {
                return;
            }
            sr.FlatEdges.Add(new ScanResults.link
            {
                first  = to,
                second = from,
            });
#else
            g.AddNode(from);
            g.AddNode(to);
            g.AddEdge(from, to);
#endif
        }
예제 #5
0
        public (DirectedGraph <Region>, Region) Build()
        {
            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock ||
                    b == proc.ExitBlock)
                {
                    continue;
                }
                var reg = regionFactory.Create(b);
                btor.Add(b, reg);
                graph.AddNode(reg);
            }

            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (btor.TryGetValue(b, out var reg) &&
                    reg.Type == RegionType.IncSwitch)
                {
                    MakeSwitchPads(b);
                }
            }

            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock)
                {
                    continue;
                }
                btor.TryGetValue(b, out var from);
                foreach (var s in b.Succ)
                {
                    if (s == proc.ExitBlock)
                    {
                        continue;
                    }
                    var to = Destination(b, s);
                    graph.AddEdge(from, to);
                }
                if (from != null)
                {
                    if (graph.Successors(from).Count == 0)
                    {
                        from.Type = RegionType.Tail;
                    }
                }
            }

            foreach (var reg in graph.Nodes.ToList())
            {
                if (graph.Predecessors(reg).Count == 0 && reg != btor[proc.EntryBlock])
                {
                    graph.Nodes.Remove(reg);
                }
            }
            return(graph, btor[proc.EntryBlock]);
예제 #6
0
 /// <summary>
 /// Disassemble every byte of the image, marking those addresses that likely
 /// are code as MaybeCode, everything else as data.
 /// </summary>
 /// <param name="segment"></param>
 /// <returns>An array of bytes classifying each byte as code or data.
 /// </returns>
 public byte[] ScanSegment(ImageMapSegment segment)
 {
     var G = new DiGraph<Address>();
     G.AddNode(bad);
     var y = new byte[segment.ContentSize];
     var step = program.Architecture.InstructionBitSize / 8;
     bool inDelaySlot = false;
     for (var a = 0; a < y.Length; a += step)
     {
         y[a] = MaybeCode;
         var i = Dasm(segment, a);
         if (i == null || i.InstructionClass == InstructionClass.Invalid)
         {
             AddEdge(G, bad, i.Address);
             inDelaySlot = false;
         }
         else
         {
             if (MayFallThrough(i))
             {
                 if (!inDelaySlot)
                 {
                     if (a + i.Length < y.Length)
                         AddEdge(G, i.Address + i.Length, i.Address);
                     else
                         AddEdge(G, bad, i.Address);
                 }
             }
             if ((i.InstructionClass & InstructionClass.Transfer) != 0) 
             {
                 var dest = Destination(i);
                 if (dest != null)
                 {
                     if (IsExecutable(dest))
                         AddEdge(G, dest, i.Address);
                     else
                         AddEdge(G, bad, i.Address);
                 }
             }
             // If this is a delayed unconditional branch...
             inDelaySlot = i.InstructionClass == DT;
         }
     }
     foreach (var a in new DfsIterator<Address>(G).PreOrder(bad))
     {
         if (a != bad)
         {
             y[a - segment.Address] = Data;
         }
     }
     return y;
 }
예제 #7
0
 public ShingledScanner(Program program, IRewriterHost host, IStorageBinder storageBinder, ScanResults sr, DecompilerEventListener eventListener)
 {
     this.program                    = program;
     this.host                       = host;
     this.storageBinder              = storageBinder;
     this.sr                         = sr;
     this.eventListener              = eventListener;
     this.sr.TransferTargets         = new HashSet <Address>();
     this.sr.DirectlyCalledAddresses = new Dictionary <Address, int>();
     this.sr.Instructions            = new SortedList <Address, RtlInstructionCluster>();
     this.sr.FlatInstructions        = new SortedList <Address, ScanResults.instr>();
     this.sr.FlatEdges               = new List <ScanResults.link>();
     this.G   = new DiGraph <Address>();
     this.Bad = program.Platform.MakeAddressFromLinear(~0ul);
     G.AddNode(Bad);
 }
예제 #8
0
        /// <summary>
        /// Builds a graph of regions based on the basic blocks of the code.
        /// </summary>
        /// <param name="proc"></param>
        /// <returns></returns>
        public Tuple<DirectedGraph<Region>, Region> BuildRegionGraph(Procedure proc)
        {
            var btor = new Dictionary<Block, Region>();
            var regs = new DiGraph<Region>();
            var regionFactory = new RegionFactory();
            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock ||
            
                            b == proc.ExitBlock)
                    continue;
                var reg = regionFactory.Create(b);
                btor.Add(b, reg);
                regs.AddNode(reg);
            }
            foreach (var b in proc.ControlGraph.Blocks)
            {
                if (b.Pred.Count == 0 && b != proc.EntryBlock)
                    continue;
                Region from;
                btor.TryGetValue(b, out from);
                foreach (var s in b.Succ)
                {
                    if (s == proc.ExitBlock)
                        continue;
                    var to = btor[s];
                    regs.AddEdge(from, to);
                }
                if (from != null)
                {
                    if (regs.Successors(from).Count == 0)
                        from.Type = RegionType.Tail;
                }
            }

            foreach (var reg in regs.Nodes.ToList())
            {
                if (regs.Predecessors(reg).Count == 0 && reg != btor[proc.EntryBlock])
                {
                    regs.Nodes.Remove(reg);
                }
            }
            return new Tuple<DirectedGraph<Region>, Region>(regs, btor[proc.EntryBlock]);
        }
예제 #9
0
 /// <summary>
 /// Builds a graph of regions based on the basic blocks of the code.
 /// </summary>
 /// <param name="proc"></param>
 /// <returns></returns>
 public Tuple<DirectedGraph<Region>, Region> BuildRegionGraph(Procedure proc)
 {
     var btor = new Dictionary<Block, Region>();
     var regs = new DiGraph<Region>();
     var regionFactory = new RegionFactory();
     foreach (var b in proc.ControlGraph.Blocks)
     {
         var reg = regionFactory.Create(b);
         btor.Add(b, reg);
         regs.AddNode(reg);
     }
     foreach (var b in proc.ControlGraph.Blocks)
     {
         foreach (var s in b.Succ)
         {
             var from = btor[b];
             var to = btor[s];
             regs.AddEdge(from, to);
         }
     }
     return new Tuple<DirectedGraph<Region>, Region>(regs, btor[proc.EntryBlock]);
 }
예제 #10
0
        /// <summary>
        /// Disassemble every byte of the segment, marking those addresses
        /// that likely are code as MaybeCode, everything else as data.
        /// </summary>
        /// <remarks>
        /// The plan is to disassemble every location of the segment, building
        /// a reverse control graph. Any jump to an illegal address or any
        /// invalid instruction will result in an edge from "bad" to that
        /// instruction.
        /// </remarks>
        /// <param name="segment"></param>
        /// <returns>An array of bytes classifying each byte as code or data.
        /// </returns>
        public byte[] ScanSegment(ImageSegment segment)
        {
            var G = new DiGraph <Address>();

            G.AddNode(bad);
            var cbAlloc = Math.Min(
                segment.Size,
                segment.MemoryArea.EndAddress - segment.Address);
            var y = new byte[cbAlloc];

            // Advance by the instruction granularity.
            var  step        = program.Architecture.InstructionBitSize / 8;
            bool inDelaySlot = false;

            for (var a = 0; a < y.Length; a += step)
            {
                y[a] = MaybeCode;
                var i = Dasm(segment, a);
                if (i == null)
                {
                    AddEdge(G, bad, segment.Address + a);
                    inDelaySlot = false;
                    break;
                }
                if (i.InstructionClass == InstructionClass.Invalid)
                {
                    AddEdge(G, bad, i.Address);
                    inDelaySlot = false;
                }
                else
                {
                    if (MayFallThrough(i))
                    {
                        if (!inDelaySlot)
                        {
                            if (a + i.Length < y.Length)
                            {
                                // Still inside the segment.
                                AddEdge(G, i.Address + i.Length, i.Address);
                            }
                            else
                            {
                                // Fell off segment, i must be a bad instruction.
                                AddEdge(G, bad, i.Address);
                            }
                        }
                    }
                    if ((i.InstructionClass & InstructionClass.Transfer) != 0)
                    {
                        var addrDest = DestinationAddress(i);
                        if (addrDest != null)
                        {
                            if (IsExecutable(addrDest))
                            {
                                // call / jump destination is executable
                                AddEdge(G, addrDest, i.Address);
                                if ((i.InstructionClass & InstructionClass.Call) != 0)
                                {
                                    int callTally;
                                    if (!this.possibleCallDestinationTallies.TryGetValue(addrDest, out callTally))
                                    {
                                        callTally = 0;
                                    }
                                    this.possibleCallDestinationTallies[addrDest] = callTally + 1;
                                }
                            }
                            else
                            {
                                // Jump to data / hyperspace.
                                AddEdge(G, bad, i.Address);
                            }
                        }
                    }

                    // If this is a delayed unconditional branch...
                    inDelaySlot = i.InstructionClass == DT;
                }
            }

            // Find all places that are reachable from "bad" addresses.
            // By transitivity, they must also be be bad.
            foreach (var a in new DfsIterator <Address>(G).PreOrder(bad))
            {
                if (a != bad)
                {
                    y[a - segment.Address] = Data;
                }
            }
            return(y);
        }
예제 #11
0
 private void AddEdge(DiGraph <Address> g, Address from, Address to)
 {
     g.AddNode(from);
     g.AddNode(to);
     g.AddEdge(from, to);
 }
예제 #12
0
        /// <summary>
        /// Build Shingle blocks from the graph. An instruction can only be
        /// in one block at a time, so at each point in the graph where the
        /// successors > 1 or the predecessors > 1, we create a new node.
        /// </summary>
        /// <param name="instructions"></param>
        /// <returns></returns>
        public IcfgBuilder BuildBlocks(DiGraph <Address> graph)
        {
            // Remember, the graph is backwards!
            var activeBlocks = new List <RtlBlock>();
            var allBlocks    = new DiGraph <RtlBlock>();
            var edges        = new List <Tuple <RtlBlock, Address> >();
            var mpBlocks     = new Dictionary <Address, RtlBlock>();
            var wl           = sr.Instructions.Keys.ToSortedSet();

            while (wl.Count > 0)
            {
                var addr = wl.First();
                wl.Remove(addr);

                var instr = sr.Instructions[addr];
                var label = program.NamingPolicy.BlockName(addr);
                var block = new RtlBlock(addr, label);
                block.Instructions.Add(instr);
                allBlocks.AddNode(block);
                mpBlocks.Add(addr, block);
                bool endBlockNow                = false;
                bool terminateDeferred          = false;
                bool addFallthroughEdge         = false;
                bool addFallthroughEdgeDeferred = false;
                for (;;)
                {
                    var addrInstrEnd = instr.Address + instr.Length;
                    if ((instr.Class & DT) != 0)
                    {
                        if (MayFallThrough(instr))
                        {
                            addFallthroughEdge         = (instr.Class & DT) == T;
                            addFallthroughEdgeDeferred = (instr.Class & DT) == DT;
                        }
                        var addrDst = DestinationAddress(instr);
                        if (addrDst != null && (instr.Class & InstrClass.Call) == 0)
                        {
                            edges.Add(Tuple.Create(block, addrDst));
                        }

                        if ((instr.Class & DT) == DT)
                        {
                            terminateDeferred = true;
                        }
                        else
                        {
                            endBlockNow = true;
                        }
                    }
                    else if (instr.Class == InstrClass.Terminates)
                    {
                        endBlockNow        = true;
                        addFallthroughEdge = false;
                        addFallthroughEdge = false;
                    }
                    else
                    {
                        endBlockNow                = terminateDeferred;
                        addFallthroughEdge         = addFallthroughEdgeDeferred;
                        addFallthroughEdgeDeferred = false;
                    }

                    if (sr.DirectlyCalledAddresses.Keys.Contains(addrInstrEnd) ||
                        sr.KnownProcedures.Contains(addrInstrEnd))
                    {
                        // If control falls into what looks like a procedure, don't
                        // add an edge.
                        addFallthroughEdge = false;
                        endBlockNow        = true;
                    }
                    if (addFallthroughEdge)
                    {
                        edges.Add(Tuple.Create(block, addrInstrEnd));
                    }

                    if (endBlockNow ||
                        !wl.Contains(addrInstrEnd) ||
                        !graph.Nodes.Contains(addrInstrEnd) ||
                        graph.Successors(addrInstrEnd).Count != 1)
                    {
                        //Debug.Print("addr: {0}, end {1}, term: {2}, wl: {3}, nodes: {4}, succ: {5}",
                        //    addr,
                        //    addrInstrEnd,
                        //    endBlockNow,
                        //    !wl.Contains(addrInstrEnd),
                        //    !graph.Nodes.Contains(addrInstrEnd),
                        //    graph.Nodes.Contains(addrInstrEnd)
                        //        ? graph.Successors(addrInstrEnd).Count
                        //        : 0);

                        if (!endBlockNow && !addFallthroughEdge)
                        {
                            edges.Add(Tuple.Create(block, addrInstrEnd));
                        }
                        break;
                    }

                    wl.Remove(addrInstrEnd);
                    instr = sr.Instructions[addrInstrEnd];
                    block.Instructions.Add(instr);
                    endBlockNow = terminateDeferred;
                }
            }
            return(new IcfgBuilder
            {
                Edges = edges,
                AddrToBlock = mpBlocks,
                Blocks = allBlocks,
            });
        }
예제 #13
0
 private void AddEdge(DiGraph<Address> g, Address from, Address to)
 {
     g.AddNode(from);
     g.AddNode(to);
     g.AddEdge(from, to);
 }
예제 #14
0
        /// <summary>
        /// Disassemble every byte of the segment, marking those addresses
        /// that likely are code as MaybeCode, everything else as data.
        /// </summary>
        /// <remarks>
        /// The plan is to disassemble every location of the segment, building
        /// a reverse control graph. Any jump to an illegal address or any
        /// invalid instruction will result in an edge from "bad" to that 
        /// instruction.
        /// </remarks>
        /// <param name="segment"></param>
        /// <returns>An array of bytes classifying each byte as code or data.
        /// </returns>
        public ScannedSegment ScanSegment(ImageSegment segment, ulong workToDo)
        {
            var G = new DiGraph<Address>();
            G.AddNode(bad);
            var cbAlloc = Math.Min(
                segment.Size,
                segment.MemoryArea.EndAddress - segment.Address);
            var y = new byte[cbAlloc];

            // Advance by the instruction granularity.
            var step = program.Architecture.InstructionBitSize / 8;
            var delaySlot = InstructionClass.None;
            for (var a = 0; a < y.Length; a += step)
            {
                y[a] = MaybeCode;
                var i = Dasm(segment, a);
                if (i == null)
                {
                    AddEdge(G, bad, segment.Address + a);
                    break;
                }
                if (IsInvalid(segment.MemoryArea, i))
                {
                    AddEdge(G, bad, i.Address);
                    delaySlot = InstructionClass.None;
                    y[a] = Data;
                }
                else
                {
                    if (MayFallThrough(i))
                    {
                        if (delaySlot != DT)
                        {
                            if (a + i.Length < y.Length)
                            {
                                // Still inside the segment.
                                AddEdge(G, i.Address + i.Length, i.Address);
                            }
                            else
                            {
                                // Fell off segment, i must be a bad instruction.
                                AddEdge(G, bad, i.Address);
                                y[a] = Data;
                            }
                        }
                    }
                    if ((i.InstructionClass & InstructionClass.Transfer) != 0)
                    {
                        var addrDest = DestinationAddress(i);
                        if (addrDest != null)
                        {
                            if (IsExecutable(addrDest))
                            {
                                // call / jump destination is executable
                                AddEdge(G, addrDest, i.Address);
                                if ((i.InstructionClass & InstructionClass.Call) != 0)
                                {
                                    int callTally;
                                    if (!this.possibleCallDestinationTallies.TryGetValue(addrDest, out callTally))
                                        callTally = 0;
                                    this.possibleCallDestinationTallies[addrDest] = callTally + 1;
                                }
                            }
                            else
                            {
                                // Jump to data / hyperspace.
                                AddEdge(G, bad, i.Address);
                                y[a] = Data;
                            }
                        }
                    }

                    // If this is a delayed unconditional branch...
                    delaySlot = i.InstructionClass;
                }
                if (y[a] == MaybeCode)
                    instructions.Add(i.Address, i);
                eventListener.ShowProgress("Shingle scanning", instructions.Count, (int)workToDo);
            }

            // Find all places that are reachable from "bad" addresses.
            // By transitivity, they must also be be bad.
            foreach (var a in new DfsIterator<Address>(G).PreOrder(bad))
            {
                if (a != bad)
                {
                    y[a - segment.Address] = Data;
                    instructions.Remove(a);

                    // Destination can't be a call destination.
                    possibleCallDestinationTallies.Remove(a);
                }
            }

            // Build blocks out of sequences of instructions.
            var blocks = BuildBlocks(G, instructions);
            return new ScannedSegment
            {
                Blocks = blocks,
                CodeFlags = y,
            };
        }
예제 #15
0
        /// <summary>
        /// Disassemble every byte of the segment, marking those addresses
        /// that likely are code as MaybeCode, everything else as data.
        /// </summary>
        /// <remarks>
        /// The plan is to disassemble every location of the segment, building
        /// a reverse control graph. Any jump to an illegal address or any
        /// invalid instruction will result in an edge from "bad" to that
        /// instruction.
        /// </remarks>
        /// <param name="segment"></param>
        /// <returns>An array of bytes classifying each byte as code or data.
        /// </returns>
        public ScannedSegment ScanSegment(ImageSegment segment, ulong workToDo)
        {
            var G = new DiGraph <Address>();

            G.AddNode(bad);
            var cbAlloc = Math.Min(
                segment.Size,
                segment.MemoryArea.EndAddress - segment.Address);
            var y = new byte[cbAlloc];

            // Advance by the instruction granularity.
            var step      = program.Architecture.InstructionBitSize / 8;
            var delaySlot = InstructionClass.None;

            for (var a = 0; a < y.Length; a += step)
            {
                y[a] = MaybeCode;
                var i = Dasm(segment, a);
                if (i == null)
                {
                    AddEdge(G, bad, segment.Address + a);
                    break;
                }
                if (IsInvalid(segment.MemoryArea, i))
                {
                    AddEdge(G, bad, i.Address);
                    delaySlot = InstructionClass.None;
                    y[a]      = Data;
                }
                else
                {
                    if (MayFallThrough(i))
                    {
                        if (delaySlot != DT)
                        {
                            if (a + i.Length < y.Length)
                            {
                                // Still inside the segment.
                                AddEdge(G, i.Address + i.Length, i.Address);
                            }
                            else
                            {
                                // Fell off segment, i must be a bad instruction.
                                AddEdge(G, bad, i.Address);
                                y[a] = Data;
                            }
                        }
                    }
                    if ((i.InstructionClass & InstructionClass.Transfer) != 0)
                    {
                        var addrDest = DestinationAddress(i);
                        if (addrDest != null)
                        {
                            if (IsExecutable(addrDest))
                            {
                                // call / jump destination is executable
                                AddEdge(G, addrDest, i.Address);
                                if ((i.InstructionClass & InstructionClass.Call) != 0)
                                {
                                    int callTally;
                                    if (!this.possibleCallDestinationTallies.TryGetValue(addrDest, out callTally))
                                    {
                                        callTally = 0;
                                    }
                                    this.possibleCallDestinationTallies[addrDest] = callTally + 1;
                                }
                            }
                            else
                            {
                                // Jump to data / hyperspace.
                                AddEdge(G, bad, i.Address);
                                y[a] = Data;
                            }
                        }
                    }

                    // If this is a delayed unconditional branch...
                    delaySlot = i.InstructionClass;
                }
                if (y[a] == MaybeCode)
                {
                    instructions.Add(i.Address, i);
                }
                eventListener.ShowProgress("Shingle scanning", instructions.Count, (int)workToDo);
            }

            // Find all places that are reachable from "bad" addresses.
            // By transitivity, they must also be be bad.
            foreach (var a in new DfsIterator <Address>(G).PreOrder(bad))
            {
                if (a != bad)
                {
                    y[a - segment.Address] = Data;
                    instructions.Remove(a);

                    // Destination can't be a call destination.
                    possibleCallDestinationTallies.Remove(a);
                }
            }

            // Build blocks out of sequences of instructions.
            var blocks = BuildBlocks(G, instructions);

            return(new ScannedSegment
            {
                Blocks = blocks,
                CodeFlags = y,
            });
        }