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
Provides functions to generate common ROP chains based on existing gadgets.
Constructor
ChainBuilder(project, rop_gadgets, pivot_gadgets, syscall_gadgets, arch, badbytes, roparg_filler)
The angr project instance.
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.
Architecture object describing the target platform.
List of bytes to avoid in the generated chains.
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.
Set of register names to preserve (e.g., {'eax', 'ebx'}).
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.
Set of register names to preserve.
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.
Address where data should be written.
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.
Memory address to modify.
Value to add to the memory location.
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.
Memory address to modify.
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.
Memory address to modify.
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.
Memory address to modify.
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.
Memory address to modify.
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 or name of the function to call.
List or tuple of arguments to pass to the function.
Set of registers to preserve.
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.
The syscall number to execute.
List of register values to set before making the syscall.
Whether to continue the ROP chain after the syscall.
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 of binary to execute. Defaults to b"/bin/sh\x00".
Address where the path string should be stored.
Returns: A RopChain that executes execve.
Example:
sigreturn
sigreturn(**registers) -> RopChain
Generates a ROP chain that invokes sigreturn/rt_sigreturn and loads registers from a frame.
Override syscall number if needed.
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 number for sigreturn.
Syscall arguments for sigreturn.
Address to jump to after sigreturn.
Returns: A RopChain object.
Stack Operations
pivot
Generates a ROP chain that performs a stack pivot.
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.
Number of bytes to shift the stack pointer.
Set of registers to preserve.
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 of the retsled chain in bytes.
Set of registers to preserve.
Returns: A RopChain consisting of ret gadgets.
Configuration Methods
set_badbytes
Updates the list of bad bytes to avoid in chains.
set_roparg_filler
set_roparg_filler(roparg_filler)
Updates the filler value for useless register pops.
optimize
Optimizes the chain builder by improving register setter and mover capabilities.
Number of processes to use for optimization.
Internal Methods
bootstrap
Initializes all internal chain building components. Called automatically after gadget discovery.
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