This code contains a use-after-free (UAF) vulnerability, which is a type of memory corruption issue. Here’s a breakdown of the vulnerability:
Key Points of the Vulnerability:
x
is Freed but Still Used- The
init()
function allocates memory forx
and initializes itsflag
field with"bico"
. - The
free_memory()
function (option 5) freesx
usingfree(x)
, but does not setx
toNULL
. - After freeing,
x
becomes a dangling pointer, meaning it still points to the freed memory.
- The
- Use of Freed Memory
- Even after
x
is freed, the program continues to use it in:print_heap()
(option 1) → Accessesx->flag
.- Option 3 → Prints
x->flag
. check_win()
(option 4) → Checksx->flag
for the value"pico"
.
- Even after
- Allocation Control via
alloc_object()
(Option 2)- This function allows the user to allocate a chunk of arbitrary size and write data into it.
- If the newly allocated chunk occupies the same memory previously used by
x
, the attacker can overwritex->flag
with"pico"
to trigger the win condition.
Exploitation Steps:
- Free
x
(Option 5) → Makesx
a dangling pointer. - Allocate a new chunk (Option 2) with a size matching
sizeof(object)
(which is 35 bytes:10+10+10+5
).- Due to heap management (e.g., glibc’s
malloc
), this new allocation may reuse the freedx
’s memory.
- Due to heap management (e.g., glibc’s
- Write
"pico"
into the new allocation → Overwritesx->flag
. - Call
check_win()
(Option 4) → Sincex->flag
is now"pico"
, the program prints the flag.
✗ heap3 (black@d4rk-pr0xy) ⇝ nc tethys.picoctf.net 65429
freed but still in use
now memory untracked
do you smell the bug?
1. Print Heap
2. Allocate object
3. Print x->flag
4. Check for win
5. Free x
6. Exit
Enter your choice: 5
1. Print Heap
2. Allocate object
3. Print x->flag
4. Check for win
5. Free x
6. Exit
Enter your choice: 2
Size of object allocation: 35
Data for flag: qwertyuiopasdfghjklzxcvbnm1234pico
1. Print Heap
2. Allocate object
3. Print x->flag
4. Check for win
5. Free x
6. Exit
Enter your choice: 3
x = pico
1. Print Heap
2. Allocate object
3. Print x->flag
4. Check for win
5. Free x
6. Exit
Enter your choice: 4
YOU WIN!!11!!
picoCTF{now_thats**************}
Why This Works:
- After
free(x)
, the memory is returned to the heap manager but not zeroed out. - If a new allocation occupies the same space,
x->flag
can be controlled by user input. - The
check_win()
function comparesx->flag
with"pico"
, allowing an attacker to manipulate it.
Mitigation:
- Nullify the pointer after freeing:
void free_memory() { free(x); x = NULL; // Prevent UAF }
- Use-after-free detectors (e.g., AddressSanitizer).
- Avoid accessing freed memory by ensuring pointers are invalidated after
free()
.
This is a classic heap-based use-after-free bug that can lead to arbitrary code execution or, in this case, a fake win condition bypass.