Skip to main content
The ChainBuilder class provides high-level methods to generate common ROP chains based on discovered gadgets. It handles register setting, memory operations, function calls, system calls, and more.

Class Definition

class ChainBuilder
Provides functions to generate common ROP chains based on existing gadgets.

Constructor

ChainBuilder(project, rop_gadgets, pivot_gadgets, syscall_gadgets, arch, badbytes, roparg_filler)
project
angr.Project
required
The angr project instance.
rop_gadgets
list[RopGadget]
required
List of ROP gadgets to use for chain building.
pivot_gadgets
list[PivotGadget]
required
List of stack pivot gadgets.
syscall_gadgets
list[SyscallGadget]
required
List of syscall gadgets.
arch
RopArch
required
Architecture object describing the target platform.
badbytes
list[int]
required
List of bytes to avoid in the generated chains.
roparg_filler
int | None
required
Integer used when popping superfluous registers, or None for symbolic values.
You typically don’t instantiate ChainBuilder directly. Instead, access it through the ROP class, which automatically exposes all ChainBuilder methods.

Register Operations

set_regs

set_regs(*args, preserve_regs=None, **registers) -> RopChain
Generates a ROP chain that sets registers to requested values.
preserve_regs
set[str] | None
Set of register names to preserve (e.g., {'eax', 'ebx'}).
**registers
int | RopValue
Register names mapped to their desired values.
Returns: A RopChain that sets the registers. Example:
chain = rop.set_regs(rax=0x1234, rcx=0x41414141)

move_regs

move_regs(preserve_regs=None, **registers) -> RopChain
Generates a ROP chain that moves values from one register to another.
preserve_regs
set[str] | None
Set of register names to preserve.
**registers
str
Mapping where key is destination register and value is source register name.
Returns: A RopChain that performs the register moves. Example:
chain = rop.move_regs(rax='rcx', rcx='rbx')

Memory Operations

write_to_mem

write_to_mem(addr, data, fill_byte=b"\xff") -> RopChain
Generates a ROP chain that writes data to memory.
addr
int | RopValue
required
Address where data should be written.
data
bytes
required
Data to write to memory.
fill_byte
bytes
default:"b'\\xff'"
Byte used to fill/pad the data if necessary.
Returns: A RopChain that writes the data. Example:
chain = rop.write_to_mem(0x8048f000, b"/bin/sh\x00")

add_to_mem

add_to_mem(addr, value, data_size=None) -> RopChain
Generates a ROP chain that adds a value to a memory location.
addr
int | RopValue
required
Memory address to modify.
value
int | RopValue
required
Value to add to the memory location.
data_size
int | None
Size of the data in bits (defaults to architecture word size).
Returns: A RopChain that performs [addr] += value. Example:
chain = rop.add_to_mem(0x8048f124, 0x41414141)

mem_xor

mem_xor(addr, value, size=None) -> RopChain
Generates a ROP chain that XORs a memory location with a value.
addr
int | RopValue
required
Memory address to modify.
value
int | RopValue
required
Value to XOR with.
size
int | None
Size of the operation in bytes.
Returns: A RopChain that performs [addr] ^= value.

mem_add

mem_add(addr, value, size=None) -> RopChain
Generates a ROP chain that adds to a memory location.
addr
int | RopValue
required
Memory address to modify.
value
int | RopValue
required
Value to add.
size
int | None
Size of the operation in bytes.
Returns: A RopChain that performs [addr] += value.

mem_or

mem_or(addr, value, size=None) -> RopChain
Generates a ROP chain that performs bitwise OR on a memory location.
addr
int | RopValue
required
Memory address to modify.
value
int | RopValue
required
Value to OR with.
size
int | None
Size of the operation in bytes.
Returns: A RopChain that performs [addr] |= value.

mem_and

mem_and(addr, value, size=None) -> RopChain
Generates a ROP chain that performs bitwise AND on a memory location.
addr
int | RopValue
required
Memory address to modify.
value
int | RopValue
required
Value to AND with.
size
int | None
Size of the operation in bytes.
Returns: A RopChain that performs [addr] &= value.

Function and System Calls

func_call

func_call(address, args, preserve_regs=None, needs_return=True) -> RopChain
Generates a ROP chain that calls a function with specified arguments.
address
int | str
required
Address or name of the function to call.
args
list | tuple
required
List or tuple of arguments to pass to the function.
preserve_regs
set[str] | None
Set of registers to preserve.
needs_return
bool
default:"True"
Whether to continue the ROP chain after invoking the function.
Returns: A RopChain that invokes the function. Example:
chain = rop.func_call('system', ['/bin/sh'])

do_syscall

do_syscall(syscall_num, args, needs_return=True, preserve_regs=None) -> RopChain
Generates a ROP chain that performs a system call.
syscall_num
int
required
The syscall number to execute.
args
list
required
List of register values to set before making the syscall.
needs_return
bool
default:"True"
Whether to continue the ROP chain after the syscall.
preserve_regs
set[str] | None
Set of registers to preserve.
Returns: A RopChain that makes the system call. Example:
# execve syscall (59 on x86_64)
chain = rop.do_syscall(59, ['/bin/sh', 0, 0])

execve

execve(path=None, path_addr=None) -> RopChain
Generates a ROP chain that executes the execve system call.
path
bytes | None
Path of binary to execute. Defaults to b"/bin/sh\x00".
path_addr
int | None
Address where the path string should be stored.
Returns: A RopChain that executes execve. Example:
chain = rop.execve()

sigreturn

sigreturn(**registers) -> RopChain
Generates a ROP chain that invokes sigreturn/rt_sigreturn and loads registers from a frame.
syscall_num
int | None
Override syscall number if needed.
**registers
int
Register values to set in the sigreturn frame.
Returns: A RopChain that performs sigreturn.

sigreturn_syscall

sigreturn_syscall(syscall_num, args, sp=None) -> RopChain
Generates a sigreturn syscall chain with syscall gadget and ROP syscall registers.
syscall_num
int
required
Syscall number for sigreturn.
args
list
required
Syscall arguments for sigreturn.
sp
int | None
Address to jump to after sigreturn.
Returns: A RopChain object.

Stack Operations

pivot

pivot(thing) -> RopChain
Generates a ROP chain that performs a stack pivot.
thing
int | RopValue
required
New stack pointer value or register containing it.
Returns: A RopChain that pivots the stack.

shift

shift(length, preserve_regs=None, next_pc_idx=-1) -> RopChain
Generates a ROP chain to shift the stack pointer by a specific amount.
length
int
required
Number of bytes to shift the stack pointer.
preserve_regs
set[str] | None
Set of registers to preserve.
next_pc_idx
int
default:"-1"
Index of the next PC value.
Returns: A RopChain that shifts the stack.

retsled

retsled(size, preserve_regs=None) -> RopChain
Creates a ret-sled ROP chain where control flow is maintained regardless of entry point.
size
int
required
Size of the retsled chain in bytes.
preserve_regs
set[str] | None
Set of registers to preserve.
Returns: A RopChain consisting of ret gadgets.

Configuration Methods

set_badbytes

set_badbytes(badbytes)
Updates the list of bad bytes to avoid in chains.
badbytes
list[int]
required
List of 8-bit integers.

set_roparg_filler

set_roparg_filler(roparg_filler)
Updates the filler value for useless register pops.
roparg_filler
int | None
required
Filler value or None.

optimize

optimize(processes=1)
Optimizes the chain builder by improving register setter and mover capabilities.
processes
int
default:"1"
Number of processes to use for optimization.

Internal Methods

bootstrap

bootstrap()
Initializes all internal chain building components. Called automatically after gadget discovery.

check_can_do_write

check_can_do_write()
Checks whether the chain builder has the capability to write to memory. Sets internal _can_do_write flag.

Usage Through ROP Class

All ChainBuilder methods are automatically exposed through the ROP class:
import angr

project = angr.Project('/bin/ls')
rop = project.analyses.ROP()
rop.find_gadgets()

# All ChainBuilder methods are now available on rop
chain1 = rop.set_regs(rax=0x1234)
chain2 = rop.write_to_mem(0x8048000, b'data')
chain3 = rop.func_call('system', ['/bin/sh'])

# Chains can be combined
full_chain = chain1 + chain2 + chain3

Build docs developers (and LLMs) love