一键导入
pwntools
Auth/lab ref: Python CTF/exploitation framework for interacting with remote services, local processes, and binary exploitation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Auth/lab ref: Python CTF/exploitation framework for interacting with remote services, local processes, and binary exploitation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Drive the MCPwn Kali-backed MCP server cleanly and fast: create a session, discover tools via the catalog (list_catalog/get_tools/get_tool/run_tool) instead of guessing names, pick the right execution path (execute_command vs detach+poll_job vs interactive shell), move files with the correct mechanism (write_workspace_file, request_upload/request_download data plane, import_artifact_to_workspace, upload_to_target, list_payloads/get_payload), and bring up connectivity (tunnel_up VPN/proxy/forward, tunnel_revshell, penelope reverse shells, run_in_shell/stabilize_shell). Use whenever running MCPwn / mcpwn_* tools, a Kali MCP, or when a run stalls on timeouts, lost output, missing routes, wrong tool names, or clumsy file transfer.
Keep the context window lean when reading large data. Use before opening big files, logs, dumps, PCAPs, decompiler output, research corpora, or a folder of worker artifacts. Enforces grep-first + windowed reads, extract-don't-hoard, and context quarantine (delegate a huge read to a sub-agent that returns a digest).
Auth assessment: web impact-validation; SQLi, SSTI, XXE, command injection, SSRF, XSS, uploads, deserialization, smuggling, WAF/parser checks.
Mode: /1337 - structured operator behaviour for coding and security; forces explicit reasoning, fast decisions, todos/lists, exact terms, evidence, verification, safety override.
Lab/CTF: pwn/binary challenges; native binaries, memory corruption, format strings, heap/ROP/SROP, shellcode artifacts, seccomp, kernel labs.
Auth/lab: reverse engineering methodology; malware triage, patch diffing, firmware/protocol RE, protections, exploitability handoff evidence.
| name | pwntools |
| description | Auth/lab ref: Python CTF/exploitation framework for interacting with remote services, local processes, and binary exploitation. |
| license | MIT |
| compatibility | Python 3.8+; Linux primary (full feature set); macOS partial. |
| metadata | {"author":"AeonDave","version":"1.0","category":"offensive-tools","language":"python"} |
Service-interaction and binary exploitation framework. The central abstraction is the tube — a uniform API for TCP sockets, local processes, and SSH channels. Write your solver once; switch between local and remote with one flag.
pip install pwntools
Every CTF solver follows this pattern:
from pwn import *
import sys
# Connection switch: python solver.py host:port
# Local: python solver.py → process(cmd)
# Remote: python solver.py host:1337 → remote(host, port)
# Debug: python solver.py host:1337 debug → remote(..., level='debug')
if len(sys.argv) > 1:
host, port = sys.argv[1].split(':')
level = sys.argv[2] if len(sys.argv) > 2 else 'info'
io = remote(host, int(port), level=level)
else:
io = process(['python3', 'challenge/server.py'])
# --- solver logic ---
io.close()
This template appears verbatim in HTB Cyber Apocalypse 2025 (Twin Oracles, Kewiri, Traces) and is the de-facto standard.
All receive calls block until the delimiter/count is met, or raise EOFError on close.
| Method | Description |
|---|---|
io.recv(n) | Up to n bytes, returns as soon as any data is available |
io.recvn(n) | Exactly n bytes — blocks until complete |
io.recvline() | Until \n — includes newline by default |
io.recvline(drop=True) | Until \n — strips newline |
io.recvuntil(b'delim') | Until delimiter — includes delimiter |
io.recvuntil(b'delim', drop=True) | Until delimiter — strips it |
io.recvregex(b'pattern') | Until regex match |
io.recvregex(b'pattern', capture=True) | Returns re.Match object |
io.recvall() | Until EOF |
io.recvrepeat(timeout) | Until timeout or EOF |
io.clean() | Drain buffer (discard pending data) |
# Read a line, strip newline, decode to str, extract last token
value = int(io.recvline().decode().strip().split()[-1])
# Read until marker, drop marker, decode, split on ' = '
value = int(io.recvuntil(b'\n', drop=True).decode().split(' = ')[1])
# Read multiple named values from consecutive lines
# Server sends: "n = 12345\ne = 65537\n"
n = int(io.recvline().decode().split(' = ')[1])
e = int(io.recvline().decode().split(' = ')[1])
# Receive until prompt, then parse all hex values from the output
raw = io.recvuntil(b'> ').decode()
import re
values = list(map(bytes.fromhex, re.findall(r'[0-9a-f]{6,}', raw)))
| Method | Description |
|---|---|
io.send(data) | Raw bytes, no newline |
io.sendline(data) | Bytes + \n |
io.sendafter(b'delim', data) | recvuntil(delim) then send(data) |
io.sendlineafter(b'delim', data) | recvuntil(delim) then sendline(data) |
io.sendlinethen(b'delim', data) | sendline(data) then recvuntil(delim) |
# Send integer as decimal string
io.sendline(str(value).encode())
# Send integer as hex string (no 0x prefix)
io.sendline(hex(value)[2:].encode())
# Send after prompt: recvuntil(b'> ') then sendline(answer)
io.sendlineafter(b'> ', str(answer).encode())
# Send comma-separated list
io.sendlineafter(b'> ', ','.join(map(str, my_list)).encode())
# Send underscore-separated factorization (HTB Kewiri pattern)
answer = '_'.join([f'{f},{e}' for f, e in factors])
io.sendlineafter(b' > ', answer.encode())
Server sends a prompt, client sends an answer, repeat.
for _ in range(100):
io.recvuntil(b'Question: ')
q = io.recvline(drop=True).decode()
answer = solve(q)
io.sendline(str(answer).encode())
flag = io.recvline().decode()
print(flag)
Server offers a menu. Client selects an option, sends ciphertext, receives result. Classic pattern in RSA/AES oracle challenges.
def query_oracle(ciphertext):
io.sendlineafter(b'> ', b'2') # select oracle option
io.recvuntil(b': ')
io.sendline(hex(ciphertext)[2:].encode())
return int(io.recvline().decode().split()[-1])
# Binary search using oracle (parity/LSB oracle)
lo, hi = 1, n - 1
for _ in range(n.bit_length()):
mid = (lo + hi) // 2
result = query_oracle(pow(2, e, n) * ciphertext % n)
if result:
lo = mid + 1
else:
hi = mid
Server requires: connect → auth/setup → challenge phase → flag retrieval.
# Phase 1: receive server parameters
io.recvuntil(b'n = ')
n = int(io.recvline())
io.recvuntil(b'e = ')
e = int(io.recvline())
# Phase 2: interact with challenge API
io.sendlineafter(b'option > ', b'1')
ct = int(io.recvline().decode().split()[-1])
# Phase 3: send solution
io.sendlineafter(b'answer > ', str(solution).encode())
flag = io.recvline().decode()
def interact(option, data=None):
io.sendlineafter(b'> ', str(option).encode())
if data is not None:
io.recvuntil(b': ')
io.sendline(data if isinstance(data, bytes) else str(data).encode())
return io.recvline().decode().strip()
# Use case
ct = interact(1) # option 1: encrypt
pt = interact(2, ct) # option 2: decrypt with ciphertext
# Service emits encrypted channel logs on connect
io.sendlineafter(b'> ', b'join #general')
raw = io.recvuntil(b'guest > ').strip().decode()
enc_data = list(map(bytes.fromhex, re.findall(r'[\da-f]{6,}', raw)))
context.log_level = 'debug' # show all send/recv bytes
context.log_level = 'info' # default — show sent/received sizes
context.log_level = 'warning' # suppress routine output
# Architecture (needed for ELF/shellcraft)
context.arch = 'amd64'
context.bits = 64
context.os = 'linux'
# Pass log level from command line
io = remote(host, port, level=sys.argv[2] if len(sys.argv) > 2 else 'info')
from pwn import *
# Pack integers to bytes (little-endian by default)
p64(0xdeadbeef) # → b'\xef\xbe\xad\xde\x00\x00\x00\x00'
p32(0xdeadbeef) # → b'\xef\xbe\xad\xde'
u64(b'\xef\xbe\xad\xde\x00\x00\x00\x00') # → 0xdeadbeef
# XOR (operates on bytes, handles different lengths)
xor(b'key', b'plaintext')
xor(b'\x41\x42', b'\x01\x02') # → b'CB'
xor(ciphertext, key, plaintext) # three-way XOR
# Hex helpers
enhex(b'hello') # → '68656c6c6f'
unhex('68656c6c6f') # → b'hello'
# Number ↔ bytes (Crypto.Util.number equivalent)
from pwn import *
# pwntools does not ship long_to_bytes/bytes_to_long
# use pycryptodome for these:
from Crypto.Util.number import long_to_bytes, bytes_to_long
cyclic(100) # generate 100-byte De Bruijn sequence
cyclic_find(0x61616168) # find offset of 4-byte sequence
# Load ELF
elf = ELF('./vuln')
libc = ELF('./libc.so.6')
# Address lookup
elf.symbols['main']
elf.got['printf']
elf.plt['system']
# Leak libc base from a leak
libc.address = leaked_puts - libc.symbols['puts']
# ROP chain
rop = ROP(elf)
rop.call('system', [next(elf.search(b'/bin/sh\x00'))])
payload = flat({offset: rop.chain()})
# Shellcode
shellcode = asm(shellcraft.sh())
shellcode = asm(shellcraft.amd64.linux.sh())
# GDB attach (local process)
gdb.attach(io)
gdb.attach(io, gdbscript='b *main+0x42\ncontinue')
# Option 1: debug flag to process
io = process('./vuln', level='debug')
# Option 2: attach GDB mid-exploit
io = process('./vuln')
gdb.attach(io)
pause() # wait for gdb to attach before continuing
# Option 3: pause at specific point
io.sendline(b'A' * 40)
pause() # press enter to continue
# Option 4: inspect tube buffer state
io.unrecv(b'debug data') # push data back into recv buffer
io.recvline() when the service does not send a newline — use io.recvuntil(b'prompt') instead.int directly — always .encode() or wrap with str().drop=True on recvuntil when the delimiter should not be in the parsed value.io.recv() (non-blocking, may return partial) instead of io.recvn(n) when an exact byte count is needed.from Crypto.Util.number import long_to_bytes but assuming pwntools provides it — it does not.