Install & Compatibility
Where this runs
tested against v4.15.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.621s · 221.3MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 8.9s · import 0.577s · 229MB
226MB installed
● package 226MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
pwn
✓ from pwn import *
✗ import pwntools; from pwntools import pwn
The main API is exposed via the 'pwn' module, not 'pwntools'. While wildcard import is common for quick CTF scripts, explicit imports are recommended for larger projects.
remote
✓ from pwn import remote
Used for connecting to remote services.
process
✓ from pwn import process
Used for interacting with local binaries.
ELF
✓ from pwn import ELF
Used for parsing and interacting with ELF executables.
ROP
✓ from pwn import ROP
Used for building Return-Oriented Programming (ROP) chains.
asm
✓ from pwn import asm
Used for assembling shellcode.
log
✓ from pwn import log
Provides structured logging functions like `log.info`, `log.success`, `log.error`.
This quickstart demonstrates how to connect to a remote service, send data (e.g., a simple buffer overflow payload using `p64` for packing), and receive responses. It highlights setting `context.arch` and `context.os`, which are crucial for correct behavior in many pwntools operations. Replace `HOST` and `PORT` with your target challenge details.
from pwn import *
# Configure global context for architecture and OS (important for assembly/disassembly, packing)
context.arch = 'amd64' # Example: ARM, i386, amd64
context.os = 'linux' # Example: windows, freebsd
context.log_level = 'info' # Debug, info, warn, error, critical
# --- Example: Interact with a remote service ---
# Replace with the actual challenge host and port
HOST = 'challenge.example.com'
PORT = 1337
try:
log.info(f"Connecting to {HOST}:{PORT}...")
# Establish a connection to the remote service
io = remote(HOST, PORT)
log.success("Connected!")
# Receive initial data (e.g., a banner)
banner = io.recvline()
log.info(f"Received banner: {banner.decode(errors='ignore').strip()}")
# Send some input (e.g., a simple payload for a buffer overflow)
# pwntools handles bytes automatically for send/recv
payload = b'A' * 72 + p64(0xdeadbeef) # 72 bytes of 'A', then an 8-byte address
io.sendline(payload)
log.info(f"Sent payload: {payload!r}")
# Receive the response after sending data
response = io.recvall()
log.info(f"Received full response: {response.decode(errors='ignore').strip()}")
io.close()
log.success("Connection closed.")
except PwnlibException as e:
log.error(f"Pwntools error: {e}")
except Exception as e:
log.error(f"General error: {e}")
pwntools --version
Debug
Known issues
breakingPwntools has dropped official support for Python 2. While older versions worked with Python 2, current versions (4.x and above) are Python 3 only. Many older online tutorials or code snippets might be for Python 2, leading to syntax errors or unexpected behavior in Python 3.fixEnsure you are running your scripts with `python3` and adapt any Python 2 specific syntax (e.g., `print` statements, string vs. bytes handling) to Python 3.
affects: < 4.0.0 (Python 2 supported), >= 4.0.0 (Python 3 only)
gotchaFailure to correctly set `context.arch` and `context.os` can lead to incorrect assembly/disassembly, packing/unpacking (e.g., `p64`, `u64`), ROP chain generation, or shellcode execution. Pwntools defaults to `i386` and `linux` if not specified, which may not match your target.fixAlways set `context.arch` (e.g., 'amd64', 'i386', 'arm') and `context.os` (e.g., 'linux', 'windows', 'freebsd') at the beginning of your script to match the target binary/system. Example: `context.arch = 'amd64'; context.os = 'linux'`
affects: All versions
gotchaThe common practice `from pwn import *` imports all public symbols from the `pwn` module directly into your script's namespace. This can lead to name collisions with other variables or functions defined in your script or other imported modules, making debugging harder.fixPrefer explicit imports for functions/classes you need, e.g., `from pwn import remote, process, ELF, ROP, flat, asm, log`. Alternatively, use `import pwn` and then access functions via `pwn.remote()`, `pwn.process()`, etc.
affects: All versions
gotchaPython 3 differentiates strictly between `str` (unicode text) and `bytes` (sequence of bytes). IO functions like `send`, `sendline`, `recv`, `recvline` in pwntools expect and return `bytes`. Mixing `str` with `bytes` without explicit encoding/decoding will raise `TypeError`.fixAlways ensure data sent to `io.send*` functions are `bytes` (e.g., `b'hello'` or `'hello'.encode('utf-8')`). Decode received `bytes` to `str` if needed for printing or manipulation (e.g., `io.recvline().decode('utf-8', errors='ignore')`). affects: All Python 3 versions of pwntools
Errors
Common errors & fixes
ImportError: No module named pwn
The pwntools library (specifically the 'pwn' module) is not installed or not accessible in your current Python environment.
fixInstall pwntools using pip: `pip install pwntools`. If using virtual environments, ensure your environment is activated.
TypeError: 'str' does not support the buffer interface
You are attempting to send a Python 3 `str` object to a pwntools function (like `io.send()`, `io.sendline()`, or `asm()`) that explicitly expects a `bytes` object.
fixConvert your string to bytes using `.encode()` or use a byte literal: `io.sendline('my string'.encode('utf-8'))` or `io.sendline(b'my string')`. pwnlib.exception.PwnlibException: Unknown architecture <ARCH_NAME>
The `context.arch` variable is either unset or set to an invalid/unsupported architecture string when an architecture-dependent function (like `asm()` or `ELF().disasm()`) is called.
fixSet `context.arch` to a valid architecture string at the beginning of your script, e.g., `context.arch = 'amd64'` or `context.arch = 'arm'`. Consult pwntools documentation for supported architecture names.
socket.gaierror: [Errno -2] Name or service not known
The hostname or IP address provided to `pwn.remote(host, port)` is invalid, misspelled, or cannot be resolved by your system's DNS.
fixVerify that the `host` string in your `remote()` call is correct and resolvable. Check for typos. Ensure you have an active network connection.
IndexError: cyclic_find could not find pattern
The `cyclic_find()` function could not locate the specific unique pattern (often used to find offsets in buffer overflows) within the provided input.
fixEnsure the pattern you are searching for is exactly present in the input you're examining (e.g., from a crash dump). The `cyclic` pattern generated might be too short, or the offset is outside the range searched.
Upgrade
Version history
4.15.0latest on PyPI · released Oct 12, 2025
Audit
Dependencies
angroptionalOften used for symbolic execution and more advanced binary analysis alongside pwntools; a heavy, optional dependency.