PWN Cheatsheet (Userland)

Complete binary exploitation reference for CTF - from dangerous functions to advanced exploitation techniques

December 15, 2025 December 13, 2025 Info
Author Author Hung Nguyen Tuong

Dangerous Sinks

Input functions

HàmChức năngHành vi dừng & kết thúcNguy hiểm vìMức độ
gets()Đọc input từ stdinDừng khi gặp \n hoặc EOF, thay \n bằng \0Không kiểm tra buffer size, buffer overflow 100%Critical
scanf("%s")Đọc chuỗi từ stdinDừng khi gặp whitespace (\n, space, \t), thêm \0 vào cuốiKhông giới hạn độ dài, buffer overflowCritical
scanf("%[^\n]")Đọc đến newlineDừng khi gặp \n, thêm \0, không consume \nKhông giới hạn độ dài, buffer overflowCritical
read()Đọc n bytes từ fdDừng khi đủ n bytes hoặc EOF, không thêm \0Không thêm null terminator, off-by-one nếu dùng như stringHigh
fgets()Đọc tối đa n-1 bytesDừng khi đủ n-1 bytes, gặp \n, hoặc EOF, thêm \0, giữ \n nếu cóAn toàn hơn nhưng có thể off-by-one nếu tính sai sizeMedium
getchar()/fgetc()Đọc 1 ký tựTrả về 1 ký tự hoặc EOFCần kiểm tra EOF, có thể tràn nếu loop không đúngMedium

String copy/manipulation functions

HàmChức năngHành vi dừng & kết thúcNguy hiểm vìMức độ
strcpy()Copy chuỗiDừng khi gặp \0 trong src, thêm \0 vào destKhông kiểm tra dest size, buffer overflowCritical
strcat()Nối chuỗiTìm \0 trong dest, copy src đến đó, dừng khi gặp \0 trong srcKhông kiểm tra dest size, buffer overflowCritical
sprintf()Format vào bufferDừng khi format xong, thêm \0Không kiểm tra buffer size, buffer overflow + format stringCritical
vsprintf()sprintf với va_listDừng khi format xong, thêm \0Không kiểm tra buffer size, buffer overflow + format stringCritical
strncpy()Copy tối đa n bytesDừng khi đủ n bytes hoặc gặp \0, chỉ thêm \0 nếu src ngắn hơn nKhông đảm bảo null-terminate nếu src >= n bytesHigh
strncat()Nối tối đa n bytesTìm \0 dest, copy n bytes từ src, luôn thêm \0Off-by-one: thêm \0 ngoài n bytesHigh
memcpy()Copy n bytesCopy đúng n bytes, không thêm \0, không dừng ở \0Không kiểm tra overlap, không null-terminateMedium
memmove()Copy n bytes (safe overlap)Copy đúng n bytes, không thêm \0, xử lý overlapKhông null-terminateMedium
snprintf()Format vào buffer với limitDừng khi đủ n-1 bytes hoặc format xong, thêm \0Format string bugs, trả về số bytes “cần” (không phải đã ghi)Medium

String length/search functions

HàmChức năngHành vi dừngNguy hiểm vìMức độ
strlen()Đếm độ dàiDừng khi gặp \0Không kiểm tra buffer boundary, crash nếu không có \0High
strtok()Tokenize stringDừng khi gặp delimiter, thay delimiter bằng \0Modify input string, static internal state (not thread-safe)Medium
strstr()Tìm substringDừng khi gặp \0Crash nếu strings không null-terminatedMedium

Output functions

HàmChức năngHành vi dừngNguy hiểm vìMức độ
printf(user_input)Format outputFormat theo format stringFormat string attack: leak/write arbitrary memoryCritical
fprintf(fp, user_input)Format output to fileFormat theo format stringFormat string attackCritical
puts()In chuỗi + newlineIn đến \0, tự động thêm \nAn toàn cho output nhưng có thể leak data nếu không có \0Low
write()Ghi n bytesGhi đúng n bytes, không dừng ở \0An toàn cho output, nhưng có thể leak nếu n > actual dataLow

Format string functions

HàmFormat specifiers nguy hiểmNguy hiểm vìMức độ
printf/fprintf/sprintf%n, %hn, %hhnGhi giá trị vào địa chỉ trên stackCritical
%x, %p, %sLeak stack/heap/memory contentsCritical
%<number>$xDirect parameter access, bypass stackCritical

Memory allocation/management

HàmChức năngNguy hiểm vìMức độ
alloca()Allocate trên stackKhông kiểm tra stack space, stack overflowCritical
malloc(user_size)Allocate heapInteger overflow trong size, heap overflow sau đóHigh
realloc()Resize allocationUse-after-free nếu fail, pointer invalidationHigh
free()Giải phóng memoryDouble-free, use-after-free bugsCritical

System/execution functions

HàmChức năngNguy hiểm vìMức độ
system(user_input)Execute shell commandCommand injection, RCECritical
exec*() familyExecute programCommand injection nếu dùng shellCritical
popen()Execute command + pipeCommand injectionCritical
dlopen()/dlsym()Load shared libraryLoad arbitrary .so, code executionCritical

File operations

HàmChức năngNguy hiểm vìMức độ
open() với O_CREATTạo fileRace condition (TOCTOU), arbitrary file writeHigh
fopen(user_path)Mở filePath traversal, arbitrary file read/writeHigh
chmod()/chown()Đổi permissionsRace condition, privilege escalationHigh

Integer vulnerabilities

Loại lỗiPattern codeInput/Điều kiệnKết quảExploitMức độ
Integer OverflowUnsigned: size_t len = a + b;
malloc(len);

Signed: int total = count * size;
malloc(total);
Unsigned: a = 0xFFFFFFFF, b = 1

Signed: count = 0x40000000, size = 4
Unsigned: len = 0

Signed: total = 0 (wrap)
Allocate 0 bytes → heap overflowCritical
Integer UnderflowUnsigned: size_t remaining = len - offset;
memcpy(buf, src, remaining);

Signed: int space = bufsize - used;
if(space > 0) read(fd, buf, space);
Unsigned: len = 10, offset = 20

Signed: used = -10, bufsize = 100
Unsigned: remaining = 0xFFFFFFF6 (huge)

Signed: space = 110
Copy massive amount hoặc bypass check → overflowCritical
Sign ConfusionDirect cast: void process(int size)
malloc(size);

Bypass check: if(size < MAX) malloc(size); với sizeint
size = -1Direct: malloc(0xFFFFFFFF) → fail/huge

Bypass: -1 < MAX → pass, cast thành unsigned huge
Allocate fail → NULL deref hoặc bypass checkCritical
Type TruncationDowncast: size_t len = strlen(s);
int n = len;

Width mismatch: unsigned long len;
read(0, &len, 8);
char buf[len];
Downcast: len = 0x100000001

Width: len = 0x1FFFFFFFF
Downcast: n = 1

Width (32-bit): buf[0xFFFFFFFF]
Dùng truncated value → undersize buffer/stack overflowCritical
Width Confusionuint32_t a; uint64_t b;
b = a * 1000;
a = 5000000Overflow trong multiply trước castSilent overflowHigh
Off-by-one via Underflowfor(i = len-1; i >= 0; i--) với size_t ilen = 0i = 0xFFFFFFFF (never stop)Infinite loop, OOB accessHigh

Exploitation Techniques

Initial checklist

Checklist:

  • Libc version → offsets, heap mechanics; Libc GOT overwrite (glibc < 2.39)
  • Seccomp → xác định syscalls bị chặn
  • NX disabled → có thể dùng shellcode
  • PIE disabled + Partial RELRO → GOT overwrite
  • PIE enabled → cần leak binary base
  • Full RELRO → GOT read-only, không có GOT overwrite
  • Static binary → khó phân tích (binary lớn), không có GOT/PLT, không cần leak libc

Information leaking

Chung: Overread qua output functions (puts, printf, write) để leak data từ stack/heap

Libc leak

  • Unsorted bin/Smallbin: UAF hoặc uninitialized allocate → fd/bk pointer trỏ về main_arena
  • Heap overflow: overflow để leak unsorted bin pointers
  • GOT entry: leak địa chỉ hàm đã được resolve (puts, printf, read,…)
  • Format string: %s để đọc GOT entry hoặc libc addresses từ stack
  • Overread: vùng có libc addresses (stack, GOT, heap)

Xác định libc version: Leak nhiều hàm từ GOT, tra libc database (https://libc.rip/)

Heap leak

  • Tcache/Fastbin UAF: fd pointer trỏ đến chunk tiếp theo (glibc ≥ 2.26)
  • Largebin: fd_nextsize/bk_nextsize chứa heap addresses
  • Uninitialized allocate: malloc không zero memory
  • Heap overflow: đọc metadata chunk khác
  • Format string: leak heap pointer từ stack
  • Overread: vùng có heap pointers

Stack leak

  • Format string: %p hoặc %x để leak stack values
  • __environ: pointer → environ trên stack → tính stack address
  • Stack overflow: overread để leak data
  • Overread: vùng có stack addresses, canary, return address

PIE leak

  • Format string: leak return address hoặc function pointer từ stack
  • __environ → AAR: đọc return address trên stack
  • Function pointer: leak địa chỉ hàm từ GOT/BSS
  • Heap overflow: leak function pointer nếu có trên heap
  • Overread: vùng có PIE-relative addresses

Canary leak

  • Format string: canary thường ở stack offset cố định
  • Stack overflow: overread để leak canary
  • __environ → AAR: đọc canary từ stack
  • TLS manipulation: ghi vào TLS section để overwrite canary

Arbitrary read/write

AAW (Arbitrary Address Write)

  • Format string: %n để ghi
  • Tcache poisoning: overwrite tcache->next → malloc trả về địa chỉ bất kỳ
  • Fastbin attack: overwrite fd, cần fake size hoặc fill tcache
  • Unsorted bin attack: ghi main_arena address qua bk pointer
  • Heap overflow: overwrite metadata để control allocation
  • OOB: array index không check bound
  • FSOP: manipulate FILE structure

AAR (Arbitrary Address Read)

  • Format string: %s với địa chỉ trên stack
  • Tcache/Fastbin control: allocate tại địa chỉ muốn đọc
  • Heap overflow: đọc metadata chunk khác
  • OOB: đọc ngoài bound
  • FSOP: manipulate FILE structure

Code execution

Shellcode (NX disabled)

  • Ghi shellcode lên stack/heap/bss (vùng có quyền X)
  • Nhảy đến shellcode qua return address/GOT overwrite
  • Shellcode staging: shellcode nhỏ đọc shellcode lớn
  • Lưu ý: kiểm tra seccomp (có thể cần ORW thay execve), shellcode có thể chứa null

Return-oriented Programming (ROP)

  • Stack alignment: RSP align 16 bytes trước call
  • RBP: cần hợp lệ (không null/invalid)
  • Register control: control đủ registers cho function call
  • Stack pivoting: pivot RSP đến BSS/heap/GOT
  • SROP: rt_sigreturn để set toàn bộ registers

One-gadget / Magic gadget

  • Kiểm tra constraints trước dùng (có thể cần ROP setup)
  • Stack alignment vẫn critical
  • Tiện nhưng ROP vẫn ổn định hơn, trên remote chưa chắc đã chạy được.

System() call

  • Overwrite GOT: hàm control được (puts, printf, setvbuf) → system
  • Setup RDI: “/bin/sh” (có trong libc)
  • Stack alignment 16 bytes: critical, có thể cần RBP hợp lệ

Hooks (glibc ≤ 2.34)

  • Function pointers: __malloc_hook, __free_hook, __realloc_hook
  • Leak libc → overwrite hook → trigger malloc/free/realloc

FSOP (File Stream Oriented Programming)

  • Manipulate _IO_FILE structure
  • Trigger qua exit(), fclose(), overflow
  • _IO_vtable_check bypass (modern glibc)
  • House of Apple/Kiwi: modern FSOP techniques

Libc GOT Overwrite

https://github.com/n132/Libc-GOT-Hijacking

Heap exploitation

Tcache (glibc ≥ 2.26)

  • Tcache poisoning: overwrite fd → malloc return arbitrary address
  • Tcache dup: double free (glibc < 2.29 không check)
  • Tcache key bypass: overwrite key field để bypass double-free check (glibc ≥ 2.29)
  • Struct location: heap_base + 0x10

Fastbin

  • Fill tcache: để chunk free vào fastbin
  • Fastbin attack: overwrite fd, cần fake size
  • Fastbin dup: double free → allocate cùng chunk 2 lần
  • House of Spirit: fake chunk (stack) → free() → allocate

Unsorted bin / Smallbin / Largebin

  • Fake chunk: fake size để free vào bin (lưu ý prev_inuse chunk sau)
  • Unsorted bin attack: ghi main_arena+offset qua bk pointer (dùng để leak/AAW)
  • Largebin attack: overwrite fd_nextsize → arbitrary write
  • House of Einherjar: consolidate qua fake prev_size

House of techniques

https://github.com/shellphish/how2heap

Lưu ý

  • Alignment 16 bytes (64-bit): Tất cả bins (tcache, small, large, unsorted, fast) - địa chỉ trả về chia hết cho 16, kích thước chunk là bội số 16
  • Tạo padding chunk (rào chắn top chunk) tránh merge khi free
  • Unsorted bin attack corrupt list → chỉ dùng 1 lần
  • Safe-linking (glibc ≥ 2.32): fd được mangle (chunk_addr >> 12) ^ real_fd → cần heap leak để decode/encode

Advanced techniques

Race condition

  • TOCTOU (Time-of-Check-Time-of-Use): Check lúc A nhưng sử dụng lúc B → race thay đổi giữa 2 lúc
  • Shared variable: Nhiều thread dùng chung biến toàn cục → data race → corruption
  • Exploit: Tạo nhiều threads để race condition

Seccomp bypass (alternative syscalls)

Mục đíchSyscall chínhSyscall thay thếGhi chú
Mở fileopenopenat, creat, open_by_handle_atopenat linh hoạt hơn với dirfd
Đọc filereadreadv, pread64, preadv, preadv2preadv đọc từ offset cụ thể
Ghi filewritewritev, pwrite64, pwritev, pwritev2writev ghi nhiều buffer cùng lúc
Đóng filecloseclose_rangeclose_range đóng nhiều fd cùng lúc
Spawn shellexecveexecveatexecveat cho phép exec từ fd
Tạo processforkclone, clone3, vforkclone linh hoạt hơn fork
Copy dataread + writesendfile, splice, copy_file_rangeTransfer trực tiếp giữa fd
Quản lý memorymmapmmap2, mremap, remap_file_pagesmprotect để thay đổi permission
Lấy thông tin filestatfstat, lstat, newfstatat, statxstatx là version mới nhất
Thay đổi directorychdirfchdirfchdir dùng fd thay vì path
Đổi tên/di chuyểnrenamerenameat, renameat2renameat2 có thêm flags
Xóa fileunlinkunlinkatunlinkat có thể xóa cả directory
Tạo directorymkdirmkdiratmkdirat relative to dirfd
Socket operationssocket, connectsocketpair, accept, accept4Để network communication
Đọc directorygetdentsgetdents64List files trong directory

Partial overwrite

  • Overwrite 1-2 byte cuối để nhảy đến địa chỉ gần
  • Dùng khi không đủ overflow
  • Có thể cần brute-force ASLR

Stack pivoting

Dùng leave; ret gadget để pivot RSP đến GOT/BSS/heap

Sau khi pivot:

  • Tiếp tục ROP chain: dùng gadgets từ vùng mới để gọi functions, setup registers
  • Thực thi shellcode: nếu pivot đến heap/BSS có shellcode sẵn sàng

RWX segment creation

  • mprotect(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC) qua ROP
  • mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, ...)
  • Compile với -z execstack (rare)

TLS/Thread manipulation

  • Malloc large size (>0x21000): mmap ngay trước TLS → heap overflow, hay OOB để:
  • Leak/Overwrite TLS: main canary, master canary, tcache perthread struct, stack guard

Random number prediction

  • Predict random() output
  • Overwrite seed trong memory
  • Predict dùng ctype functions
  • Time-based seed: brute-force time()