Pwntools Quick Reference Guide
pwntools is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
Context
Setting the Target Architecture and OS:
1 | context(arch='arm', os='linux', endian='big', log_level='debug') |
Log
It’s similar to logging.Logger.
1 | log.info('Hello, world!') |
Making connections
New a tube
Create a tube instance from a local program or a remote conncetion.
1 | conn = process('./pwn') |
Comunication
Send and recv
There are many functions to send or recv data via tube.
1 | recv(numb = 4096, timeout = default) |
Listen
1 | l = listen(port=2333, bindaddr = "0.0.0.0") |
ELF Manipulation
Stop hard-coding things! Look them up at runtime with pwnlib.elf.
1 | e = ELF('/bin/cat') |
You can even patch and save the files.
1 | e = ELF('/bin/cat') |
Debug with gdb
pwnlib.gdb.attach() starts GDB in a new terminal and attach to target.
Target can be a process, (addr, port), or ssh channel.
1 | p = process('./helloworld') |
If you want to start GDB in a split window in tmux:
1 | context.terminal = ['tmux', 'splitw', '-h'] |
Fmtstr
pwnlib.fmtstr.fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')
It can generate payload for 32 or 64 bits architectures. The size of the addr is taken from context.bits
Parameters:
- offset (int) – the first formatter’s offset you control
- writes (dict) – dict with addr, value {addr: value, addr2: value2}
- numbwritten (int) – number of byte already written by the printf function
- write_size (str) – must be byte, short or int. Tells if you want to write byte by byte, short by short or int by int (hhn, hn or n)
DynELF
pwnlib.dynelf — Resolving remote functions using leaks
Resolve symbols in loaded, dynamically-linked ELF binaries. Given a function which can leak data at an arbitrary address, any symbol in any loaded library can be resolved.
This is an example in the document:
1 | # Assume a process or remote connection |
Utility
Generation of unique sequences
pwnlib.util.cyclic.cyclic(length = None, alphabet = string.ascii_lowercase, n = 4)
pwnlib.util.cyclic.cyclic_find(subseq, alphabet = string.ascii_lowercase, n = None)
1 | cyclic(20) |
Assembly and Disassembly
1 | asm('mov eax, 0').encode('hex') |
Packing Integers
p8(), p16(), p32(), p64(), u8(), u16(), u32(), u64()
1 | import struct |
pwnlib.util.packing.pack/unpack(number, word_size = None, endianness = None, sign = None, **kwargs)