python pwntools CTF exploit security binary pwn

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+D or 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

MethodDescription
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

Ethical note: pwntools must be used exclusively in authorised environments (CTF competitions, labs, your own systems). Unauthorised access to computer systems is illegal.