pwnlib.rop — Return Oriented Programming

Return Oriented Programming

class pwnlib.rop.ROP(elfs, base=None)[source]

Class which simplifies the generation of ROP-chains.


elf = ELF('ropasaurusrex')
rop = ROP(elf), elf.bss(0x80))
# ['0x0000:        0x80482fc (read)',
#  '0x0004:       0xdeadbeef',
#  '0x0008:              0x0',
#  '0x000c:        0x80496a8']
# '\xfc\x82\x04\x08\xef\xbe\xad\xde\x00\x00\x00\x00\xa8\x96\x04\x08'

Helper to make finding ROP gadets easier.

Also provides a shorthand for .call():
` rop.function(args) ==>, args) `
>>> elf=ELF(which('bash'))
>>> rop=ROP([elf])
>>> rop.rdi     ==['rdi'], order = 'regs')
>>> rop.r13_r14_r15_rbp ==['r13','r14','r15','rbp'], order = 'regs')
>>> rop.ret     ==
>>> rop.ret_8   ==
>>> rop.ret     != None

Returns: Raw bytes of the ROP chain


Build the ROP chain into a list (addr, int/string, bool), where the last value is True iff the value was an internal reference.

It is guaranteed that the individual parts are next to each other.

If there is no base available, then the returned addresses are indexed from 0.

Parameters:base (int) – The base address to build the rop-chain from. Defaults to self.base.
call(resolvable, arguments=())[source]

Add a call to the ROP chain

  • resolvable (str,int) – Value which can be looked up via ‘resolve’, or is already an integer.
  • arguments (list) – List of arguments which can be passed to pack(). Alternately, if a base address is set, arbitrarily nested structures of strings or integers can be provided.

Build the ROP chain

Returns:str containging raw ROP bytes

Dump the ROP chain in an easy-to-read manner


Explicitly set $sp, by using a leave; ret gadget


Adds a raw integer or string to the ROP chain.

If your architecture requires aligned values, then make sure that any given string is aligned!

Parameters:data (int/str) – The raw value to put onto the rop chain.

Resolves a symbol to an address

Parameters:resolvable (str,int) – Thing to convert into an address
Returns:int containing address of ‘resolvable’, or None
search(move=0, regs=None, order='size')[source]

Search for a gadget which matches the specified criteria.

  • move (int) – Minimum number of bytes by which the stack pointer is adjusted.
  • regs (list) – Minimum list of registers which are popped off the stack.
  • order (str) – Either the string ‘size’ or ‘regs’. Decides how to order multiple gadgets the fulfill the requirements.

The search will try to minimize the number of bytes popped more than requested, the number of registers touched besides the requested and the address.

If order == 'size', then gadgets are compared lexicographically by (total_moves, total_regs, addr), otherwise by (total_regs, total_moves, addr).

Returns:A tuple of (address, info) in the same format as self.gadgets.items().

Inverts ‘resolve’. Given an address, it attempts to find a symbol for it in the loaded ELF files. If none is found, it searches all known gadgets, and returns the disassembly

Parameters:value (int) – Address to look up
Returns:String containing the symbol name for the address, disassembly for a gadget (if there’s one at that address), or an empty string.