The pwntools Python Library
pwntools is a Python library designed to streamline the process of writing exploits and interacting with remote services and binary files during cybersecurity competitions such as CTF (Capture The Flag).
Installation
pip install pwntools
Main features
- Process interaction: launch and interact with local processes
- Remote connections: connect to services via TCP or UDP
- Payload construction: simplifies creating payloads for exploits
- Binary data manipulation: tools for working with binary data and specific formats
- Debugging and disassembly: integration with debuggers such as GDB
Connecting to a remote service
from pwn import *
# Set the log level (debug shows all details)
context.log_level = 'debug'
# Remote TCP connection
conn = remote('example.com', 1234)
# Receive one line from the service
welcome_message = conn.recvline()
print(welcome_message)
# Send data to the service
conn.sendline('Hello, server!')
conn.close()
Receiving data
recvuntil() — read up to a specific string
from pwn import *
conn = remote('example.com', 1337)
# Read all data until 'Username:'
data = conn.recvuntil(b'Username:')
print(data.decode())
# Send the response
conn.sendline(b'mario_rossi')
recvuntil() is the most common method in CTFs: it reads continuously until it finds the target string, then stops.
recvline() — read one line at a time
from pwn import *
conn = remote('example.com', 1337)
while True:
line = conn.recvline()
print(line.decode())
if b'Password:' in line:
break
conn.sendline(b'super_secret')
Useful when you do not know exactly which line the expected prompt will appear on.
recvn() — read an exact number of bytes
from pwn import *
conn = remote('example.com', 1337)
# Receive exactly 1024 bytes
data = conn.recvn(1024)
print(data.decode())
Interactive mode
After automating part of the interaction, interactive() hands control back to the user:
from pwn import *
conn = remote('example.com', 1337)
# Automate authentication
conn.recvuntil(b'Username:')
conn.sendline(b'mario_rossi')
conn.recvuntil(b'Password:')
conn.sendline(b'super_secret')
# Hand control to the user
conn.interactive()
In interactive mode:
- all keyboard input is sent to the service
- the service’s output is displayed in real time
- to exit:
Ctrl+Dor by closing the connection server-side
Full example
from pwn import *
context.log_level = 'debug'
conn = remote('example.com', 1337)
# Read the welcome message
welcome_message = conn.recvline()
print(welcome_message.decode())
# Automated authentication
conn.recvuntil(b'Username:')
conn.sendline(b'mario_rossi')
conn.recvuntil(b'Password:')
conn.sendline(b'super_secret')
# Wait for the access confirmation
conn.recvuntil(b'Access Granted')
# Switch to interactive mode to explore
conn.interactive()
Timeout handling
from pwn import *
conn = remote('example.com', 1337, timeout=5)
try:
data = conn.recvuntil(b'Command:', timeout=5)
except EOFError:
print('The service closed the connection.')
except TimeoutError:
print('Timeout reached without receiving the prompt.')
Pattern matching with expect()
When the service can respond with variable output, expect() lets you wait for one of several patterns:
from pwn import *
conn = remote('example.com', 1337)
patterns = [b'Option 1', b'Option 2', b'Option 3']
index = conn.expect(patterns)
if index == 0:
print('Received Option 1')
conn.sendline(b'answer_1')
elif index == 1:
print('Received Option 2')
conn.sendline(b'answer_2')
else:
print('Received Option 3')
conn.sendline(b'answer_3')
expect() returns the index of the matching pattern in the provided list.
Main methods reference
| Method | Description |
|---|---|
remote(host, port) | Opens a remote TCP connection |
process(cmd) | Starts a local process |
recvline() | Reads one line (up to \n) |
recvuntil(pattern) | Reads until the specified string |
recvn(n) | Reads exactly n bytes |
recv(n) | Reads at most n bytes |
sendline(data) | Sends data followed by \n |
send(data) | Sends data without \n |
interactive() | Hands control to the user |
expect(patterns) | Waits for one of the patterns, returns its index |
close() | Closes the connection |
Resources
- Official documentation: docs.pwntools.com
- GitHub repository: github.com/Gallopsled/pwntools
Ethical note: pwntools must be used exclusively in authorised environments (CTF competitions, labs, your own systems). Unauthorised access to computer systems is illegal.
EC