Skip to main content
angr Management provides powerful debugging capabilities that combine traditional debugging with symbolic execution, allowing you to analyze both concrete and symbolic program states.

Debugging Modes

angr Management supports multiple debugging approaches:
Explore program paths symbolically
  • Create symbolic states
  • Set find/avoid addresses
  • Explore multiple paths simultaneously
  • Solve for inputs that reach targets
Best for: Finding inputs, vulnerability discovery, path exploration

Breakpoints

Breakpoint Types

angr Management supports three types of breakpoints:

Execution

Break when instruction is executed

Read

Break when memory is read

Write

Break when memory is written

Setting Breakpoints

Quick method:
  1. Click on instruction
  2. Press F2
  3. Breakpoint toggles on/off
Or right-click:
  1. Right-click instruction
  2. Select “Toggle Breakpoint”
  3. Choose breakpoint type

Managing Breakpoints

In the Breakpoints View (View → Breakpoints):
1

View All

See all breakpoints in a table with type, address, size, and comments
2

Edit

Double-click a breakpoint to modify its properties
3

Delete

Right-click → “Remove breakpoint” or select and press Delete
4

Enable/Disable

Toggle breakpoints without removing them

Breakpoint Visualization

Breakpoints are shown throughout the interface:
  • Disassembly: Red dot next to instruction
  • Hex View: Cyan highlight over address range
  • Breakpoints View: Complete list with details

Execution Control

Control program execution with these commands:
ActionShortcutDescription
ContinueF9Run until next breakpoint
Step ForwardF7Execute one instruction
Step OverF8Step over function calls
Run to CursorRight-click → Run to HereExecute until cursor position
Execution control is available when a debugger is active (symbolic or trace-based).

Symbolic Execution

Creating Symbolic States

1

Open Dialog

  • Right-click in disassembly → “New State”
  • Or use View → States
2

Configure State

  • Starting address (default: current instruction)
  • Input configuration (stdin, files, arguments)
  • Environment variables
  • Memory initialization
3

Create

Click “Create” to generate the symbolic state
4

Execute

State appears in Symbolic Execution view, ready to explore

Find/Avoid Addresses

Guide symbolic execution to desired locations:
Addresses you want to reach:
  1. Right-click target instruction
  2. Select “Set as Find Address”
  3. Green marker appears
  4. Symbolic execution prioritizes paths to this address
Programmatic:
workspace.add_find_address(0x401234)

Symbolic Execution View

The Symbolic Execution view (View → Symbolic Execution) shows:
  • Active simulation managers
  • State organization (active, found, avoided, etc.)
  • State counts for each category
  • Hierarchical view of states
  • Parent-child relationships
  • State divergence points
  • Step states forward
  • Explore paths
  • Merge states
  • Drop unwanted states

State Inspection

Registers View

View → Registers shows current CPU register values:

Display

  • All architecture registers
  • Current values (hex and decimal)
  • Changed values highlighted
  • Symbolic expressions shown

Modification

  • Double-click to edit
  • Set concrete values
  • View constraints on symbolic values

Stack View

View → Stack displays the current stack:
  • Stack pointer location
  • Return addresses
  • Local variables
  • Stack frame boundaries
  • Scroll to explore stack
Features:
  • Click addresses to navigate
  • Highlight stack frames
  • Show ASCII representation
  • Export stack contents

Memory Inspection

Use the Hex View (View → Hex) to inspect memory:
  1. Enter address or symbol name
  2. View bytes and ASCII representation
  3. Edit values directly
  4. See highlighted regions for:
    • Breakpoints
    • Patches
    • Modified data

Constraint Viewer

For symbolic states, view constraints:
  1. Select state in States view
  2. Right-click → “View Constraints”
  3. See all path constraints
  4. Solve for satisfying values

Trace Debugging

Loading Traces

1

Open Trace

File → Load a new trace
2

Select File

Choose bintrace (.trace) file
3

Create Debugger

angr creates a trace debugger automatically
4

Navigate

Step through the recorded execution

Trace Map View

View → Trace Map shows execution coverage:

Visualization

  • Heat map of executed code
  • Color intensity shows execution frequency
  • Identify hot paths and loops

Navigation

  • Click to jump to code
  • Zoom and pan
  • Filter by execution count

Comparing Traces

Load multiple traces to compare:
  1. Load first trace
  2. Load second trace
  3. Switch between traces in Traces view
  4. Use Trace Map to visualize differences

Debugging Workflows

Finding Crash Inputs

1

Load Binary

Open the crashing binary
2

Create Symbolic State

Create state with symbolic input at entry point
3

Set Avoid

Mark the crash location as “avoid” address
4

Explore

Run symbolic execution
5

Check States

States that reach “avoided” addresses may trigger crash
6

Get Input

Solve for concrete input values from the state

Analyzing Function Behavior

1

Navigate

Jump to function start in disassembly
2

Set Breakpoint

Press F2 on first instruction
3

Create State

Right-click → “New State” with symbolic arguments
4

Set Find

Mark return instruction as “find” address
5

Execute

Step through or continue to see different paths
6

Inspect

Examine return values and constraints

Debugging Patches

1

Apply Patch

Modify code in disassembly view
2

Set Breakpoint

Break before patched code
3

Create State

New state at breakpoint
4

Step Through

Single-step through patched code
5

Verify

Check registers and memory for expected behavior

Advanced Debugging

Hooks

Intercept execution at specific addresses:
  1. Right-click instruction → “Hook”
  2. Enter Python code to execute
  3. Access state via state variable
  4. Return value controls execution flow
Example:
# Log function calls
print(f"Called at {hex(state.addr)}")
print(f"First arg: {state.regs.rdi}")

Simulation Manager Control

Advanced state management via console:
# Access simulation manager
simgr = workspace.main_instance.simgrs[0].am_obj

# Step all active states
simgr.step()

# Move states between stashes
simgr.move('active', 'found', lambda s: s.addr == 0x401234)

# Merge states
simgr.merge()

# Explore with constraints
simgr.explore(find=0x401234, avoid=[0x401500, 0x401600])

State Hierarchy

View state relationships:
  1. Open States view
  2. See parent-child relationships
  3. Understand where states diverged
  4. Track constraint additions

Debugging Tips

Performance

Speed up symbolic execution:
  • Use concrete values where possible
  • Set find/avoid addresses early
  • Limit exploration depth
  • Drop unreachable states
  • Enable state merging

Accuracy

Improve results:
  • Use accurate calling conventions
  • Define function signatures
  • Initialize memory correctly
  • Model library functions
  • Add constraints based on knowledge

Troubleshooting

Possible causes:
  • Code never executes
  • Wrong address
  • Breakpoint disabled
Solutions:
  • Verify code path in disassembly
  • Check Breakpoints view for status
  • Ensure debugger is active
Symbolic execution explodes:Solutions:
  • Set find/avoid addresses
  • Reduce symbolic input size
  • Use concrete values for some inputs
  • Enable aggressive state merging
  • Limit exploration depth
Constraint solving takes too long:Solutions:
  • Simplify constraints if possible
  • Reduce symbolic input complexity
  • Use concrete values where feasible
  • Increase solver timeout in settings

Next Steps

Symbolic Execution

Deep dive into symbolic execution

Patching

Apply patches to fix bugs

Scripting

Automate debugging with scripts

Configuration

Configure debugging options

Build docs developers (and LLMs) love