pwntools cheatsheet
running a program
from pwn import *
r = remote('0.0.0.0', 1234) #
p = process('./vuln') #
p.interactive() # drops you into an interactive shell
p.close() # oh man, idk
pause() #
debugging with gdb
# https://docs.pwntools.com/en/stable/gdb.html
context.arch = 'i386'
context.terminal = ['urxvt', '-e', 'sh', '-c']
gdb.attach(p, gdb_cmd) # attach to an existing process
gdb.debug('./vuln', ) # spin up a debugger process, stopped at the first instruction
if the gdb windows that’s spawned is ugly as hell, check out this
sending data
p.recvuntil(until) # read input from p until 'line'
p.sendline(line) # sends the line to the program
p.sendlineafter(until, line) # combines recvuntil() and sendline()
packing data
p32(0x12345678) # packs a 32-bit hex number (b'\x78\x56\x34\x12')
u32(b'\x78\x56\x34\x12') # unpacks a 32-bit (little-endian) number.
hex() #
bytes() #
f''.encode() #
b''.decode() #
shellcode
asm("""
push 0x0068732f
push 0x6e69622f
mov ebx, esp
mov eax, 0xb
mov ecx, 0
mov edx, 0
mov esi, 0
int 0x80
""") # a simple system('/bin/sh') payload
reading memory address
magic numbers are bad, use these instead
elf = ELF('./vuln') #
elf = p.elf # same as ELF('./vuln')
elf.symbols['win'] #
elf.got['puts'] #
# if ASLR is enabled, you'll need to specify the binary base), otherwise it'll just give you the offset
elf.address = 0xdeadbeef
locating what part of your input overwrites certain registers
c = cyclic_gen()
c.get(n) # Get a chunk of length n
c.find(b'caaa') # -> (8, 0, 8): position 8, which is chunk 0 at position 8
finding ROPTools
# you can ignore this until week05
rop = ROP('./vuln') #
## TODO https://docs.pwntools.com/en/stable/rop/rop.html