Overview
Overview of official_template.py found in cryptocat’s github.
Python Exploitation Template (pwntools)
This script is a general-purpose binary exploitation skeleton designed for vulnerability research and Capture the Flag (CTF) challenges. It leverages pwntools to streamline tasks such as process launching, debugging, and payload construction.
Imports
from pwn import *
- Imports the pwntools library, which provides utilities for exploitation:
- Process interaction (
process
,remote
). - Payload generation (
cyclic
,flat
). - Debugger integration (
gdb.debug
). - ELF binary inspection (
ELF
).
- Process interaction (
Execution Context Management
def start(argv=[], *a, **kw):
if args.GDB:
return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
elif args.REMOTE:
return remote(sys.argv[1], sys.argv[2], *a, **kw)
else:
return process([exe] + argv, *a, **kw)
- Purpose: Provides a flexible way to launch the binary in three modes:
--GDB
: Run the binary under GDB with a predefined script.--REMOTE
: Connect to a remote service withremote(host, port)
.- Default: Launches the binary locally.
- Benefit: Single function to handle local debugging, remote exploitation, and automated testing without modifying the code.
Finding Instruction Pointer (EIP/RIP) Offset
def find_ip(payload):
p = process(exe, level='warn')
p.sendlineafter(b'>', payload)
p.wait()
# ip_offset = cyclic_find(p.corefile.pc) # x86
ip_offset = cyclic_find(p.corefile.read(p.corefile.sp, 4)) # x64
warn('located EIP/RIP offset at {a}'.format(a=ip_offset))
return ip_offset
- Purpose: Identifies the offset to the instruction pointer (EIP on x86, RIP on x64).
- Workflow:
- Launches the vulnerable binary with reduced logging (
warn
level). - Sends a cyclic pattern as input to trigger a buffer overflow.
- Waits for the crash, then reads the crash address from the core dump.
- Uses
cyclic_find
to compute the exact offset where execution control is overwritten.
- Launches the vulnerable binary with reduced logging (
- Notes:
p.corefile.pc
: Program counter (for x86).p.corefile.read(p.corefile.sp, 4)
: Reads 4 bytes from stack pointer (for x64).- Essential for payload construction, as it determines where to place the return address overwrite.
Debugger Script
Can be modified by adding breakpoints in key areas for register/memory analysis.
gdbscript = '''
init-pwndbg
continue
'''.format(**locals())
- Purpose: Preloaded GDB script for debugging.
- init-pwndbg: Loads pwndbg extensions.
- continue: Immediately continues execution upon debugger start.
- Benefit: Eliminates repetitive GDB setup during iterative testing.
Binary and ELF Context
Modify this depending on binary name, level of logging.
exe = './vuln'
elf = context.binary = ELF(exe, checksec=False)
context.log_level = 'debug'
- exe: Path to the target binary.
- ELF: Loads binary into pwntools’ ELF object for symbol resolution.
checksec=False
: Skips security feature checks (NX, PIE, RELRO) for faster loading.context.log_level = 'debug'
: Provides verbose runtime output for troubleshooting.
Exploit Development Section
Modify this to match the remote target’s libc library.
# Lib-C library, can use pwninit/patchelf to patch binary
# libc = ELF("./libc.so.6")
# ld = ELF("./ld-2.27.so")
- Placeholder for loading external libc and dynamic loader files.
- Useful when dealing with remote binaries where custom libc is required.
- Tools:
- pwninit: Automates patching binaries with correct libc.
- patchelf: Manually patches binary’s dynamic dependencies.
Finding Offset
offset = find_ip(cyclic(500))
- Generates a cyclic pattern of 500 bytes.
- Calls
find_ip()
to determine instruction pointer overwrite offset. - Output: An integer representing the exact location in the buffer where RIP/EIP is overwritten.
Exploit Execution
io = start()
- Starts the target process depending on the chosen mode (
GDB
,REMOTE
, or local).
Payload Construction
Add payload here.
payload = flat({
offset: [
]
})
- flat(): Creates a structured payload with precise control over offsets.
- Key Idea: Place exploit primitives at the correct buffer offset.
- Example Payloads (to be added depending on technique):
- Shellcode.
- Return-to-libc (system + “/bin/sh”).
- ROP chains.
- Jump to
win()
function.
Payload Delivery
Modify this depending on binary’s prompt.
io.sendlineafter(b'>', payload)
io.recvuntil(b'Thank you!')
io.interactive()
- sendlineafter: Waits for prompt
>
before sending payload. - recvuntil: Ensures synchronization by reading output up to
Thank you!
. Could userecvall()
- interactive(): Drops into an interactive shell if exploitation is successful.
Key Takeaways
- Template Usage: Flexible, modular structure suitable for CTF and real-world exploitation.
- Offset Discovery: Automates the tedious process of finding buffer overflow offsets.
- GDB Integration: Streamlines debugging with pwndbg and predefined scripts.
- Payload Building: Provides a clean scaffold for various exploitation techniques (ROP, shellcode injection, ret2libc).
- Remote Support: Easily switches between local and remote environments for exploit testing.