Code Blocks¶
If you ever looked at a function in the Graph-View, you know what code blocks are. They are the nodes in the function graph, sometimes referred to as a flowchart.
>>> block = sark.CodeBlock()
>>> print(list(block.next))
[<CodeBlock(start_ea=0x00417567, end_ea=0x00417570)>,
<CodeBlock(start_ea=0x0041759E, end_ea=0x004175D4)>]
Sark’s CodeBlock
object inherits from the idaapi.BasicBlock
objects, and adds a few handy members.
Member | Usage |
---|---|
lines | the lines in the block, as a generator |
next | successor nodes, as a generator |
prev | predecessor nodes, as a generator |
color | the background color of the node |
These members allow for easy traversal and analysis of nodes in a graph.
FlowChart¶
Sark’s flowchart, inheriting from idaapi.FlowChart
, is in every way
the same except for returning Sark CodeBlock
objects instead of
idaapi.BasicBlock
ones. It can be used to quickly fetch all the
blocks in a function graph.
Getting Codeblocks¶
Codeblocks are created using the sark.CodeBlock(ea)
class.
Flowcharts can be retrieved using the sark.FlowChart(ea)
class accordingly.
In some cases, you may want to go over more than one function. In those
cases, you can use the sark.codeblocks(start=None, end=None, full=True)
function.
The full
parameter controls the way the blocks are generated. With full=True
,
FlowChart
objects are generated per function, yielding fully capable CodeBlock
objects. With full=False
, a single FlowChart
is generated for the entire
address range. This results in faster iteration, but since the blocks are not associated
to their containing functions, it is not possible to get or set block colors (line color
will change, though.)
Advanced Usage¶
Since the function flowchart is actually a graph, it makes sense to use
it as one. To ease you into it, the sark.get_nx_graph(ea)
function
was added.
>>> sark.get_nx_graph(idc.here())
<networkx.classes.digraph.DiGraph at 0x85d6570>
The function returns a NetworkX
DiGraph
object representing the flowchart, with each node being the
start_ea
of a matching block. Using NetworkX’s functionality, it is
easy to trace routes in the graph.
>>> import networkx as nx
>>> func = sark.Function()
>>> graph = sark.get_nx_graph(func.ea)
>>> start_address = sark.get_block_start(func.start_ea) # The `get_block_start(ea)` is short for `get_codeblock(ea).start_ea`
>>> end_address = sark.get_block_start(func.end_ea - 1) # Remember, `end_ea` is outside the function!
>>> path = nx.shortest_path(graph, start_address, end_address)
>>> print("From {} to {}".format(hex(start_address), hex(end_address)))
From 0x417400L to 0x4176a6L
>>>print " -> ".join(map(hex, nx.shortest_path(graph, start, end)))
0x417400L -> 0x41745dL -> 0x417483L -> 0x417499L -> 0x4176a6L