Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/angr/angr/llms.txt

Use this file to discover all available pages before exploring further.

angr provides two main CFG recovery analyses: CFGFast for fast, static analysis and CFGEmulated for accurate, symbolic execution-based analysis.

CFGFast

CFGFast performs fast control-flow graph recovery by using light-weight analysis combined with heuristics. It does not perform expensive data-flow analysis or symbolic execution.

Constructor

CFGFast(
    binary=None,
    objects=None,
    regions=None,
    symbols=True,
    function_prologues=None,
    resolve_indirect_jumps=True,
    force_complete_scan=False,
    data_references=True,
    cross_references=False,
    normalize=False,
    start_at_entry=True,
    function_starts=None,
    detect_tail_calls=False,
    base_state=None,
    eh_frame=True,
    indirect_jump_resolvers=None,
    **kwargs
)
binary
cle.Backend | None
The binary to recover CFG on. By default the main binary is used.
objects
list[cle.Backend] | None
A list of objects to recover the CFG on. By default all loaded objects are analyzed.
regions
list[tuple[int, int]] | None
A list of tuples (start_address, end_address) describing memory regions that the CFG should cover.
symbols
bool
default:"True"
Get function beginnings from symbols in the binary.
function_prologues
bool | None
Scan the binary for function prologues and use those positions as function beginnings. Defaults to True for non-.NET binaries.
resolve_indirect_jumps
bool
default:"True"
Try to resolve indirect jumps. This is necessary to resolve jump targets from jump tables.
force_complete_scan
bool
default:"False"
Perform a complete scan on the binary and maximize the number of identified code blocks.
data_references
bool
default:"True"
Enables the collection of references to data used by individual instructions.
cross_references
bool
default:"False"
Whether CFGFast should collect cross-references from the entire program. This performs constant propagation on the entire program and may be slower and consume more memory. Implies data_references=True.
normalize
bool
default:"False"
Normalize the CFG as well as all function graphs after CFG recovery.
start_at_entry
bool
default:"True"
Begin CFG recovery at the entry point of the project.
function_starts
list[int] | None
A list of extra function starting points. CFGFast will try to resume scanning from each address in the list.
detect_tail_calls
bool
default:"False"
Enable aggressive tail-call optimization detection.
base_state
SimState | None
A state to use as a backer for all memory loads.
eh_frame
bool
default:"True"
Retrieve function starts from the .eh_frame of ELF binaries or exception records of PE binaries.
indirect_jump_resolvers
list | None
A custom list of indirect jump resolvers. If None or empty, default indirect jump resolvers specific to this architecture and binary types will be loaded.

Properties

graph
SpillingCFG
The control flow graph as a NetworkX DiGraph.
functions
FunctionManager
The function manager containing all identified functions.
memory_data
dict
A mapping of addresses to MemoryData objects representing data in memory.
jump_tables
dict
A mapping of addresses to jump table information.
indirect_jumps
dict
A mapping of addresses to IndirectJump objects.

Example Usage

import angr

project = angr.Project('/bin/true')

# Fast CFG recovery
cfg = project.analyses.CFGFast()

# Access the graph
print(f"Number of nodes: {len(cfg.graph.nodes())}")
print(f"Number of functions: {len(cfg.functions)}")

# Get a specific function
main_func = cfg.functions.get('main')
if main_func:
    print(f"Main function at {hex(main_func.addr)}")

CFGEmulated

CFGEmulated performs accurate control-flow graph recovery using symbolic execution. It is slower than CFGFast but provides more precise results.

Constructor

CFGEmulated(
    context_sensitivity_level=1,
    starts=None,
    avoid_runs=None,
    enable_function_hints=False,
    call_depth=None,
    initial_state=None,
    keep_state=False,
    resolve_indirect_jumps=True,
    enable_advanced_backward_slicing=False,
    enable_symbolic_back_traversal=False,
    indirect_jump_resolvers=None,
    normalize=False,
    max_iterations=1,
    base_graph=None,
    iropt_level=None,
    max_steps=None,
    **kwargs
)
context_sensitivity_level
int
default:"1"
The level of context-sensitivity of this CFG. Ranges from 0 to infinity. Higher values track more calling context.
starts
list | None
A collection of starting points to begin analysis. Can contain:
  • Integer addresses
  • 2-tuples of (address, jumpkind)
  • SimState instances
avoid_runs
list | None
A list of runs to avoid during analysis.
enable_function_hints
bool
default:"False"
Whether to use function hints (constants that might be used as exit targets).
call_depth
int | None
How deep in the call stack to trace. None means no limit.
initial_state
SimState | None
An initial state to use to begin analysis.
keep_state
bool
default:"False"
Whether to keep the SimStates for each CFGNode.
resolve_indirect_jumps
bool
default:"True"
Whether to enable the indirect jump resolvers for resolving indirect jumps.
normalize
bool
default:"False"
If the CFG as well as all Function graphs should be normalized.
max_iterations
int
default:"1"
The maximum number of iterations that each basic block should be “executed”. Larger numbers are required for complex analyses like loop analysis.
base_graph
networkx.DiGraph | None
A basic control flow graph to follow. CFG recovery will strictly follow nodes and edges shown in the graph.
iropt_level
int | None
The optimization level of VEX IR (0, 1, 2). The default level will be used if None.
max_steps
int | None
The maximum number of basic blocks to recover for the longest path from each start before pausing.

Properties

graph
SpillingCFG
The control flow graph as a NetworkX DiGraph.
functions
FunctionManager
The function manager containing all identified functions.
deadends
list
Get all CFGNodes that have an out-degree of 0.
unresolvables
set
Get those SimRuns that have non-resolvable exits.

Methods

copy()

Make a copy of the CFG.
new_cfg = cfg.copy()
Returns: A copy of the CFG instance.

resume(starts=None, max_steps=None)

Resume a paused or terminated control flow graph recovery.
starts
list | None
A collection of new starts to resume from. If None, resume from where it was paused.
max_steps
int | None
The maximum number of blocks on the longest path starting from each start before pausing.

get_function_subgraph(start, max_call_depth=None)

Get a sub-graph of a certain function.
start
int
The function start address.
max_call_depth
int | None
Call depth limit. None indicates no limit.
Returns: A CFGEmulated instance which is a sub-graph of the original graph.

Example Usage

import angr

project = angr.Project('/bin/true')

# Emulated CFG recovery with context sensitivity
cfg = project.analyses.CFGEmulated(
    context_sensitivity_level=2,
    keep_state=True,
    max_iterations=3
)

# Access nodes and edges
for node in cfg.graph.nodes():
    print(f"Node at {hex(node.addr)}")
    
# Get function subgraph
if 'main' in cfg.functions:
    main_addr = cfg.functions['main'].addr
    main_cfg = cfg.get_function_subgraph(main_addr)

CFGNode

Both CFGFast and CFGEmulated create CFGNode objects representing basic blocks in the control flow graph.

Properties

addr
int
The address of this node.
size
int
The size of this node in bytes.
function_address
int
The address of the function this node belongs to.
block
Block
The Block object for this node.
instruction_addrs
list[int]
Addresses of all instructions in this node.
successors
list[CFGNode]
List of successor CFGNodes.
predecessors
list[CFGNode]
List of predecessor CFGNodes.