private void When_DisassembleProcedure()
 {
     var hsc = new HeuristicScanner(prog, host);
     this.proc = hsc.DisassembleProcedure(
         prog.Image.BaseAddress,
         prog.Image.BaseAddress + prog.Image.Length);
 }
 public HeuristicProcedureScanner(Program program, HeuristicProcedure proc)
 {
     this.program   = program;
     this.proc      = proc;
     this.blocks    = proc.Cfg;
     this.conflicts = BuildConflictGraph(proc.Cfg.Nodes);
 }
Exemple #3
0
        /// <summary>
        /// Heuristically disassembles a range of addresses between
        /// <paramref name="addrStart"/> and <paramref name="addrEnd"/>.
        /// </summary>
        /// <param name="addrStart"></param>
        /// <param name="addrEnd"></param>
        /// <returns></returns>
        public HeuristicProcedure DisassembleProcedure(Address addrStart, Address addrEnd)
        {
            var proc = new HeuristicProcedure(
                addrStart,
                addrEnd,
                program.Architecture.CreateFrame());
            var sr = new ScanResults
            {
                ICFG = proc.Cfg,
                DirectlyCalledAddresses = new Dictionary <Address, int>(),
            };
            var dasm = new HeuristicDisassembler(
                program,
                binder,
                sr,
                proc.IsValidAddress,
                true,
                host);
            int instrByteGranularity = program.Architecture.InstructionBitSize / program.Architecture.MemoryGranularity;

            for (Address addr = addrStart; addr < addrEnd; addr = addr + instrByteGranularity)
            {
                dasm.Disassemble(addr);
            }
            DumpBlocks(proc.Cfg.Nodes);
            return(proc);
        }
 private void When_DisassembleProcedure()
 {
     var hsc = new HeuristicScanner(program, host, eventListener);
     this.proc = hsc.DisassembleProcedure(
         program.ImageMap.BaseAddress,
         program.ImageMap.BaseAddress + program.SegmentMap.GetExtent());
 }
 public HeuristicDisassembler(
     Program program,
     HeuristicProcedure proc,
     IRewriterHost host)
 {
     this.program = program;
     this.proc = proc;
     this.host = host;
     blockMap = new Dictionary<Address, HeuristicBlock>();
 }
Exemple #6
0
 public HeuristicDisassembler(
     Program program,
     HeuristicProcedure proc,
     IRewriterHost host)
 {
     this.program = program;
     this.proc    = proc;
     this.host    = host;
     blockMap     = new Dictionary <Address, HeuristicBlock>();
 }
 public HeuristicProcedureScanner(
     Program program,
     HeuristicProcedure proc,
     IRewriterHost host)
 {
     this.program   = program;
     this.proc      = proc;
     this.host      = host;
     this.blocks    = proc.Cfg;
     this.conflicts = BuildConflictGraph(proc.Cfg.Nodes);
 }
Exemple #8
0
 /// <summary>
 /// Heuristically disassembles a procedure that has been assumed to 
 /// be located between <paramref name="addrStart"/> and <paramref name="addrEnd"/>. 
 /// </summary>
 /// <param name="addrStart"></param>
 /// <param name="addrEnd"></param>
 /// <returns></returns>
 public HeuristicProcedure DisassembleProcedure(Address addrStart, Address addrEnd)
 {
     var proc = new HeuristicProcedure
     {
         BeginAddress = addrStart,
         EndAddress = addrEnd,
         Frame = program.Architecture.CreateFrame()
     };
     var dasm = new HeuristicDisassembler(program, proc, host);
     int instrByteGranularity = program.Architecture.InstructionBitSize / 8;
     for (Address addr = addrStart; addr < addrEnd; addr = addr + instrByteGranularity)
     {
         dasm.Disassemble(addr);
     }
     DumpBlocks(proc.Cfg.Nodes);
     return proc;
 }
Exemple #9
0
        // Plan of attack:
        // For each "hole", look for signatures of program entry points.
        // These are procedure entry candidates of .
        // Next scan all executable code segments for:
        //  - calls that reach those candidates
        //  - jmps to those candidates
        //  - pointers to those candidates.
        // Each time we find a call, we increase the score of the candidate.
        // At the end we have a list of scored candidates.
        //
        public HeuristicProcedure DisassembleProcedure(Address addrStart, Address addrEnd)
        {
            blockMap = new Dictionary <Address, HeuristicBlock>();
            var proc = new HeuristicProcedure
            {
                BeginAddress = addrStart,
                EndAddress   = addrEnd,
                Frame        = prog.Architecture.CreateFrame()
            };

            for (Address addr = addrStart; addr < addrEnd; addr = addr + prog.Architecture.InstructionBitSize / 8)
            {
                HeuristicDisassemble(addr, proc);
            }
            DumpBlocks(proc.Cfg.Nodes);
            return(proc);
        }
Exemple #10
0
        /// <summary>
        /// Heuristically disassembles a procedure that has been assumed to
        /// be located between <paramref name="addrStart"/> and <paramref name="addrEnd"/>.
        /// </summary>
        /// <param name="addrStart"></param>
        /// <param name="addrEnd"></param>
        /// <returns></returns>
        public HeuristicProcedure DisassembleProcedure(Address addrStart, Address addrEnd)
        {
            var proc = new HeuristicProcedure
            {
                BeginAddress = addrStart,
                EndAddress   = addrEnd,
                Frame        = program.Architecture.CreateFrame()
            };
            var dasm = new HeuristicDisassembler(program, proc, host);
            int instrByteGranularity = program.Architecture.InstructionBitSize / 8;

            for (Address addr = addrStart; addr < addrEnd; addr = addr + instrByteGranularity)
            {
                dasm.Disassemble(addr);
            }
            DumpBlocks(proc.Cfg.Nodes);
            return(proc);
        }
Exemple #11
0
        private void AddBlocks(HeuristicProcedure hproc)
        {
            var name = program.NamingPolicy.ProcedureName(hproc.BeginAddress);
            var proc = Procedure.Create(program.Architecture, name, hproc.BeginAddress, hproc.Frame);

            foreach (var block in hproc.Cfg.Nodes.Where(bb => bb.Instructions.Count > 0))
            {
                var last = block.Instructions.Last();
                var b    = new Block(proc, block.Address, "l" + block.Address);
                if (program.ImageMap.Items.ContainsKey(block.Address))
                {
                    continue;
                }
                program.ImageMap.AddItemWithSize(
                    block.Address,
                    new ImageMapBlock(block.Address)
                {
                    Block = b,
                    Size  = (uint)(last.Address - block.Address) + (uint)last.Length
                });
            }
        }
Exemple #12
0
        // Partition memory into chunks betweeen each candidate.
        // Decode each possible instruction at each possible address, yielding a list of potential instructions.
        // Identify intra procedural xfers:
        //   - target is in this chunk.
        //   - conditional jmp.
        // HeuristicFunction will hve
        //   - start address
        //   - end address
        // To find all of these, scan the all the potential_instructions, if any of them are a GOTO or a RtlBranch.
        //   if found, add to <Set>jump_candidates
        // Now use scanner to build initial CFG
        // feed scanner with fn start and all jump_candidates
        // this may yield dupes and broken blocks.

        // SpuriousNodes: how to get rid of.

        // it is possible
        //to have instructions in the initial call graph that overlap.
        //In this case, two different basic blocks in the call graph
        //can contain overlapping instructions starting at slightly
        //different addresses. When following a sequence of instructions,
        //the disassembler can arrive at an instruction
        //that is already part of a previously found basic block. In
        //the regular case, this instruction is the first instruction of
        //the existing block. The disassembler can complete the
        //instruction sequence of the current block and create a
        //link to the existing basic block in the control flow graph

        private HeuristicBlock SplitBlock(HeuristicBlock block, Address addr, HeuristicProcedure proc)
        {
            var newBlock = new HeuristicBlock(addr, string.Format("l{0:X}", addr));

            proc.Cfg.Nodes.Add(newBlock);
            newBlock.Statements.AddRange(
                block.Statements.Where(r => r.Address >= addr).OrderBy(r => r.Address));
            foreach (var de in blockMap.Where(d => d.Key >= addr && d.Value == block).ToList())
            {
                blockMap[de.Key] = newBlock;
            }
            block.Statements.RemoveAll(r => r.Address >= addr);
            var succs = proc.Cfg.Successors(block).ToArray();

            foreach (var s in succs)
            {
                proc.Cfg.AddEdge(newBlock, s);
                proc.Cfg.RemoveEdge(block, s);
            }
            proc.Cfg.AddEdge(block, newBlock);
            return(newBlock);
        }
Exemple #13
0
        // Partition memory into chunks betweeen each candidate.
        // Decode each possible instruction at each possible address, yielding a list of potential instructions.
        // Identify intra procedural xfers:
        //   - target is in this chunk.
        //   - conditional jmp.
        // HeuristicFunction will hve
        //   - start address
        //   - end address
        // To find all of these, scan the all the potential_instructions, if any of them are a GOTO or a RtlBranch.
        //   if found, add to <Set>jump_candidates
        // Now use scanner to build initial CFG
        // feed scanner with fn start and all jump_candidates
        // this may yield dupes and broken blocks.

        // SpuriousNodes: how to get rid of.

        // it is possible
        //to have instructions in the initial call graph that overlap.
        //In this case, two different basic blocks in the call graph
        //can contain overlapping instructions starting at slightly
        //different addresses. When following a sequence of instructions,
        //the disassembler can arrive at an instruction
        //that is already part of a previously found basic block. In
        //the regular case, this instruction is the first instruction of
        //the existing block. The disassembler can complete the
        //instruction sequence of the current block and create a
        //link to the existing basic block in the control flow graph

        private HeuristicBlock SplitBlock(HeuristicBlock block, Address addr, HeuristicProcedure proc)
        {
            var newBlock = new HeuristicBlock(addr, string.Format("l{0:X}", addr));
            proc.Cfg.Nodes.Add(newBlock);
            newBlock.Statements.AddRange(
                block.Statements.Where(r => r.Address >= addr).OrderBy(r => r.Address));
            foreach (var de in blockMap.Where(d => d.Key >= addr && d.Value == block).ToList())
            {
                blockMap[de.Key] = newBlock;
            }
            block.Statements.RemoveAll(r => r.Address >= addr);
            var succs = proc.Cfg.Successors(block).ToArray();
            foreach (var s in succs)
            {
                proc.Cfg.AddEdge(newBlock, s);
                proc.Cfg.RemoveEdge(block, s);
            }
            proc.Cfg.AddEdge(block, newBlock);
            return newBlock;
        }
Exemple #14
0
 /// <summary>
 /// Recursively disassembles the range of addresses specified by the guessed procedure.
 /// <paramref name="proc"/>.
 /// </summary>
 /// <param name="addr"></param>
 /// <param name="proc"></param>
 /// <returns></returns>
 public HeuristicBlock HeuristicDisassemble(Address addr, HeuristicProcedure proc)
 {
     var current = new HeuristicBlock(addr, string.Format("l{0:X}", addr));
     var rAddr = prog.Architecture.CreateRewriter(
              prog.CreateImageReader(addr),
              prog.Architecture.CreateProcessorState(),
              proc.Frame,
              host);
     foreach (var rtl in rAddr.TakeWhile(r => r.Address < proc.EndAddress))
     {
         HeuristicBlock block;
         if (blockMap.TryGetValue(rtl.Address, out block))
         {
             // This instruction was already disassembled before.
             if (rtl.Address.ToLinear() != block.Address.ToLinear())
             {
                 block = SplitBlock(block, rtl.Address, proc);
             }
             if (current.Statements.Count == 0)
             {
                 // Coincides exactly, return the old block.
                 return block;
             }
             else
             {
                 // Fell into 'block' while disassembling
                 // 'current'. Create a fall-though edge
                 if (!proc.Cfg.Nodes.Contains(current))
                 {
                     proc.Cfg.Nodes.Add(current);
                 }
                 proc.Cfg.AddEdge(current, block);
                 return current;
             }
         }
         else
         {
             // Fresh instruction
             if (!proc.Cfg.Nodes.Contains(current))
             {
                 proc.Cfg.Nodes.Add(current);
             }
             current.Statements.Add(rtl);
             blockMap.Add(rtl.Address, current);
             var rtlLast = rtl.Instructions.Last();
             if (rtlLast is RtlCall || rtlLast is RtlReturn)
             {
                 // Since calls cannot be dependent on to return, 
                 // we stop disassembling.
                 return current;
             }
             var rtlJump = rtlLast as RtlGoto;
             if (rtlJump != null)
             {
                 var target = rtlJump.Target as Address;
                 if (target == null ||
                     target < proc.BeginAddress ||
                     target >= proc.EndAddress)
                 {
                     // Stop disassembling if you get outside
                     // the procedure or a computed goto.
                     return current;
                 }
                 block = HeuristicDisassemble(target, proc);
                 proc.Cfg.AddEdge(current, block);
                 return current;
             }
             var rtlBranch = rtlLast as RtlBranch;
             if (rtlBranch != null)
             {
                 block = HeuristicDisassemble(rtlBranch.Target, proc);
                 proc.Cfg.AddEdge(current, block);
                 block = HeuristicDisassemble(rtl.Address + rtl.Length, proc);
                 proc.Cfg.AddEdge(current, block);
                 return current;
             }
         }
     }
     return current;
 }
 private void AddBlocks(HeuristicProcedure hproc)
 {
     var proc = Procedure.Create(hproc.BeginAddress, hproc.Frame);
     foreach (var block in hproc.Cfg.Nodes.Where(bb => bb.Instructions.Count > 0))
     {
         var last = block.Instructions.Last();
         var b = new Block(proc, "l" + block.Address);
         if (program.ImageMap.Items.ContainsKey(block.Address))
             continue;
         program.ImageMap.AddItemWithSize(
             block.Address,
             new ImageMapBlock
             {
                 Block = b,
                 Address = block.Address,
                 Size = (uint)(last.Address - block.Address) + (uint)last.Length
             });
     }
 }
Exemple #16
0
 // Plan of attack:
 // For each "hole", look for signatures of program entry points.
 // These are procedure entry candidates of .
 // Next scan all executable code segments for:
 //  - calls that reach those candidates
 //  - jmps to those candidates
 //  - pointers to those candidates.
 // Each time we find a call, we increase the score of the candidate.
 // At the end we have a list of scored candidates.
 //
 public HeuristicProcedure DisassembleProcedure(Address addrStart, Address addrEnd)
 {
     blockMap = new Dictionary<Address, HeuristicBlock>();
     var proc = new HeuristicProcedure
     {
         BeginAddress = addrStart,
         EndAddress = addrEnd,
         Frame = prog.Architecture.CreateFrame()
     };
     for (Address addr = addrStart; addr < addrEnd; addr = addr + prog.Architecture.InstructionBitSize / 8)
     {
         HeuristicDisassemble(addr, proc);
     }
     DumpBlocks(proc.Cfg.Nodes);
     return proc;
 }
Exemple #17
0
        /// <summary>
        /// Recursively disassembles the range of addresses specified by the guessed procedure.
        /// <paramref name="proc"/>.
        /// </summary>
        /// <param name="addr"></param>
        /// <param name="proc"></param>
        /// <returns></returns>
        public HeuristicBlock HeuristicDisassemble(Address addr, HeuristicProcedure proc)
        {
            var current = new HeuristicBlock(addr, string.Format("l{0:X}", addr));
            var rAddr   = prog.Architecture.CreateRewriter(
                prog.CreateImageReader(addr),
                prog.Architecture.CreateProcessorState(),
                proc.Frame,
                host);

            foreach (var rtl in rAddr.TakeWhile(r => r.Address < proc.EndAddress))
            {
                HeuristicBlock block;
                if (blockMap.TryGetValue(rtl.Address, out block))
                {
                    // This instruction was already disassembled before.
                    if (rtl.Address.ToLinear() != block.Address.ToLinear())
                    {
                        block = SplitBlock(block, rtl.Address, proc);
                    }
                    if (current.Statements.Count == 0)
                    {
                        // Coincides exactly, return the old block.
                        return(block);
                    }
                    else
                    {
                        // Fell into 'block' while disassembling
                        // 'current'. Create a fall-though edge
                        if (!proc.Cfg.Nodes.Contains(current))
                        {
                            proc.Cfg.Nodes.Add(current);
                        }
                        proc.Cfg.AddEdge(current, block);
                        return(current);
                    }
                }
                else
                {
                    // Fresh instruction
                    if (!proc.Cfg.Nodes.Contains(current))
                    {
                        proc.Cfg.Nodes.Add(current);
                    }
                    current.Statements.Add(rtl);
                    blockMap.Add(rtl.Address, current);
                    var rtlLast = rtl.Instructions.Last();
                    if (rtlLast is RtlCall || rtlLast is RtlReturn)
                    {
                        // Since calls cannot be dependent on to return,
                        // we stop disassembling.
                        return(current);
                    }
                    var rtlJump = rtlLast as RtlGoto;
                    if (rtlJump != null)
                    {
                        var target = rtlJump.Target as Address;
                        if (target == null ||
                            target < proc.BeginAddress ||
                            target >= proc.EndAddress)
                        {
                            // Stop disassembling if you get outside
                            // the procedure or a computed goto.
                            return(current);
                        }
                        block = HeuristicDisassemble(target, proc);
                        proc.Cfg.AddEdge(current, block);
                        return(current);
                    }
                    var rtlBranch = rtlLast as RtlBranch;
                    if (rtlBranch != null)
                    {
                        block = HeuristicDisassemble(rtlBranch.Target, proc);
                        proc.Cfg.AddEdge(current, block);
                        block = HeuristicDisassemble(rtl.Address + rtl.Length, proc);
                        proc.Cfg.AddEdge(current, block);
                        return(current);
                    }
                }
            }
            return(current);
        }