Bonus: Cross Two Structs (heap-havoc)¶
Tools: nc, GDB, objdump
A program takes two names as command-line arguments and copies each onto the heap. Overflowing the first name reaches into the second name's struct, where a function pointer sits that nobody checks before calling.
Goal¶
Overflow out of one heap object, across into the next struct, and set a callback so the program calls a hidden winner() function that prints the flag.
Background¶
The program allocates two struct internet objects back-to-back on the heap.
Each has an 8-byte name buffer, and the program copies argv[1] and argv[2] into them with strcpy(), which has no length check.
Each struct ends with a callback function pointer that main() calls if it is not NULL; both start NULL.
A winner() function prints the flag, and nothing in the normal flow ever points a callback at it.
This binary is 32-bit, so every field and pointer is 4 bytes.
Your Task¶
- Work out the layout of
struct internet, and the distance from the firstnamebuffer to the second struct'scallbackfield. - Find
winner()'s address withobjdump -dornm(the binary is not a PIE, so it is fixed). - Build
argv[1]so the overflow landswinner()'s address on the second struct'scallback. One field in between is the second struct'snamepointer, whichmain()passes tostrcpy()after your overflow, so it must stay a valid writable address. - Capture the flag locally, then against the remote service.
Build & Run¶
Locally, pass the two names as arguments:
A placeholder flag.txt is included so this works out of the box; it is not the real flag.
The deployed service cannot take argv over a socket, so it reads two lines from you and re-execs the binary with them as argv[1] and argv[2].
Connect with netcat and send your two arguments as two lines:
Because argv[1] contains raw address bytes, build it with solve/solve.sh or solve/exploit.py rather than typing it.
Check Your Work¶
You have solved it when winner() runs and prints the flag, instead of "No winners this time".
Be ready to explain why the second struct's name field had to hold a valid writable address rather than filler.
Submit the flag: https://ctf.security.cs.pub.ro/so