Pwntools
Jump to navigation
Jump to search
Description
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.
Installation
$ python -m pip install --user pwntools
Examples
Establish a communication
The following example will connect with 2018shell.picoctf.com to port 34802/tcp
from pwn import *
host, port = '2018shell.picoctf.com', 34802
s = remote(host, port)
#
# ...
#
s.close()
Start an ELF executable
elf = pwn.ELF('/problems/got-2-learn-libc_4_526cc290dde8d914a30538d3d0ac4ef1/vuln')
p = elf.process()
output = p.recv()
Send and receive content
from pwn import *
host, port = '2018shell.picoctf.com', 34802
s = remote(host, port)
s.recvuntil('> ')
s.sendline('%8$s')
response = s.recv()
print(response)
s.close()
Suppose that you have an executable that displays a prompt (yes/no) and you want to inject a payload:
$ ./auth Would you like to read the flag? (yes/no) yes Sorry, you are not *authenticated*!
Here is the way to do:
proc.sendlineafter("(yes/no)", payload)
List symbols
>>> from pwn import *
>>> elf = ELF('./auth')
[*] '/data/documents/challenges/picoCTF_2018/binary_exploitation/350-authenticate/files/auth'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
>>> elf.symbols
{'stdout': 134520900, '_IO_stdin_used': 134514860, 'stdin': 134520896, '': 134520896, '__JCR_LIST__': 134520592, 'deregister_tm_clones': 134514080, 'register_tm_clones': 134514128, '__do_global_dtors_aux': 134514192, 'completed.7209': 134520904, '__do_global_dtors_aux_fini_array_entry': 134520588, 'frame_dummy': 134514224, '__frame_dummy_init_array_entry': 134520584, '__FRAME_END__': 134515464, '__JCR_END__': 134520592, '__init_array_end': 134520588, '_DYNAMIC': 134520596, '__init_array_start': 134520584, '__GNU_EH_FRAME_HDR': 134515140, '_GLOBAL_OFFSET_TABLE_': 134520832, '__libc_csu_fini': 134514832, '__x86.get_pc_thunk.bx': 134514064, 'data_start': 134520888, '_edata': 134520896, '_fini': 134514836, '__data_start': 134520888, '__dso_handle': 134520892, '__libc_csu_init': 134514736, 'stdin@@GLIBC_2.0': 134520896, '_end': 134520912, '_start': 134514016, '_fp_hw': 134514856, 'stdout@@GLIBC_2.0': 134520900, '__bss_start': 134520896, 'main': 134514461, 'authenticated': 134520908, '__TMC_END__': 134520896, 'flag': 134514267, '_init': 134513760, 'read_flag': 134514404, 'setresgid': 134513984, 'plt.setresgid': 134513984, 'fopen': 134513968, 'plt.fopen': 134513968, 'setvbuf': 134513952, 'plt.setvbuf': 134513952, '__libc_start_main': 134513936, 'plt.__libc_start_main': 134513936, 'exit': 134513920, 'plt.exit': 134513920, 'puts': 134513904, 'plt.puts': 134513904, 'getegid': 134513888, 'plt.getegid': 134513888, '__stack_chk_fail': 134513872, 'plt.__stack_chk_fail': 134513872, 'fgets': 134513856, 'plt.fgets': 134513856, 'printf': 134513840, 'plt.printf': 134513840, 'strstr': 134513824, 'plt.strstr': 134513824, '__gmon_start__': 134514000, 'plt.__gmon_start__': 134514000, 'got.__gmon_start__': 134520828, 'got.stdin': 134520896, 'got.stdout': 134520900, 'got.strstr': 134520844, 'got.printf': 134520848, 'got.fgets': 134520852, 'got.__stack_chk_fail': 134520856, 'got.getegid': 134520860, 'got.puts': 134520864, 'got.exit': 134520868, 'got.__libc_start_main': 134520872, 'got.setvbuf': 134520876, 'got.fopen': 134520880, 'got.setresgid': 134520884}
Packing strings
# execute system('/bin/sh')
payload = 'A'*160 # buffer overflow
payload += pwn.p32(mem_system) # system
payload += 'B'*4 # return address
payload += pwn.p32(mem_useful_string) # /bin/sh
$ python -c "import pwn; print(pwn.p32(0x80485cb))" b'\xcb\x85\x04\x08'
XOR
#!/bin/env python
import pwn
greetingMessage = "You have now entered the Duck Web, and you're in for a honkin' good time."
sekrutBuffer = [0x29, 0x06, 0x16, 0x4f, 0x2b, 0x35, 0x30, 0x1e, 0x51, 0x1b, 0x5b, 0x14, 0x4b,
0x08, 0x5d, 0x2b, 0x52, 0x17, 0x01, 0x57, 0x16, 0x11, 0x5c, 0x07, 0x5d, 0x00]
print(pwn.xor(greetingMessage, sekrutBuffer))
Patch an executable
The following example shows how to open the executable be-quick-or-be-dead-2, replace the alarm function with a return and save the patched executable as new:
from pwn import *
elf = ELF('./be-quick-or-be-dead-2')
elf.asm(elf.symbols['alarm'], 'ret')
elf.save('./new')