BROP - Blind Return Oriented Programming
Reading time: 7 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
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Basic Information
Ο στόχος αυτής της επίθεσης είναι να μπορέσουμε να καταχραστούμε ένα ROP μέσω μιας υπερχείλισης buffer χωρίς καμία πληροφορία για το ευάλωτο δυαδικό.
Αυτή η επίθεση βασίζεται στο εξής σενάριο:
- Μια ευπάθεια στο stack και γνώση του πώς να την ενεργοποιήσουμε.
- Μια εφαρμογή server που επανεκκινείται μετά από μια κατάρρευση.
Attack
1. Βρείτε την ευάλωτη απόσταση στέλνοντας ένα ακόμη χαρακτήρα μέχρι να ανιχνευθεί μια δυσλειτουργία του server
2. Brute-force canary για να το διαρρεύσετε
3. Brute-force αποθηκευμένες διευθύνσεις RBP και RIP στο stack για να τις διαρρεύσετε
Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με αυτές τις διαδικασίες εδώ (BF Forked & Threaded Stack Canaries) και εδώ (BF Addresses in the Stack).
4. Βρείτε το gadget STOP
Αυτό το gadget επιτρέπει βασικά να επιβεβαιωθεί ότι κάτι ενδιαφέρον εκτελέστηκε από το ROP gadget επειδή η εκτέλεση δεν κατέρρευσε. Συνήθως, αυτό το gadget θα είναι κάτι που σταματά την εκτέλεση και είναι τοποθετημένο στο τέλος της αλυσίδας ROP όταν αναζητάμε ROP gadgets για να επιβεβαιώσουμε ότι εκτελέστηκε ένα συγκεκριμένο ROP gadget.
5. Βρείτε το gadget BROP
Αυτή η τεχνική χρησιμοποιεί το ret2csu gadget. Και αυτό συμβαίνει επειδή αν αποκτήσετε πρόσβαση σε αυτό το gadget στη μέση κάποιων εντολών, αποκτάτε gadgets για να ελέγξετε rsi
και rdi
:
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png)
Αυτά θα είναι τα gadgets:
pop rsi; pop r15; ret
pop rdi; ret
Παρατηρήστε πώς με αυτά τα gadgets είναι δυνατό να ελέγξετε 2 παραμέτρους μιας συνάρτησης για να καλέσετε.
Επίσης, παρατηρήστε ότι το ret2csu gadget έχει μια πολύ μοναδική υπογραφή επειδή θα popάρει 6 καταχωρητές από το stack. Έτσι, στέλνοντας μια αλυσίδα όπως:
'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP
Αν το STOP εκτελείται, αυτό σημαίνει βασικά ότι χρησιμοποιήθηκε μια διεύθυνση που popάρει 6 καταχωρητές από το stack. Ή ότι η διεύθυνση που χρησιμοποιήθηκε ήταν επίσης μια διεύθυνση STOP.
Για να αφαιρεθεί αυτή η τελευταία επιλογή, εκτελείται μια νέα αλυσίδα όπως η παρακάτω και δεν πρέπει να εκτελεί το gadget STOP για να επιβεβαιώσει ότι η προηγούμενη εκτέλεσε pop 6 καταχωρητές:
'A' * offset + canary + rbp + ADDR
Γνωρίζοντας τη διεύθυνση του ret2csu gadget, είναι δυνατό να συμπεράνουμε τη διεύθυνση των gadgets για να ελέγξουμε rsi
και rdi
.
6. Βρείτε το PLT
Ο πίνακας PLT μπορεί να αναζητηθεί από 0x400000 ή από τη διαρρεύσουσα διεύθυνση RIP από το stack (αν χρησιμοποιείται PIE). Οι καταχωρήσεις του πίνακα είναι χωρισμένες κατά 16B (0x10B), και όταν καλείται μια συνάρτηση, ο server δεν καταρρέει ακόμη και αν οι παράμετροι δεν είναι σωστές. Επίσης, η έλεγχος της διεύθυνσης μιας καταχώρησης στο PLT + 6B επίσης δεν καταρρέει καθώς είναι ο πρώτος κώδικας που εκτελείται.
Επομένως, είναι δυνατό να βρείτε τον πίνακα PLT ελέγχοντας τις εξής συμπεριφορές:
'A' * offset + canary + rbp + ADDR + STOP
-> καμία κατάρρευση'A' * offset + canary + rbp + (ADDR + 0x6) + STOP
-> καμία κατάρρευση'A' * offset + canary + rbp + (ADDR + 0x10) + STOP
-> καμία κατάρρευση
7. Εύρεση strcmp
Η συνάρτηση strcmp
ρυθμίζει τον καταχωρητή rdx
στο μήκος της συμβολοσειράς που συγκρίνεται. Σημειώστε ότι rdx
είναι η τρίτη παράμετρος και πρέπει να είναι μεγαλύτερη από 0 προκειμένου να χρησιμοποιηθεί αργότερα write
για να διαρρεύσει το πρόγραμμα.
Είναι δυνατό να βρείτε τη θέση της strcmp
στον PLT με βάση τη συμπεριφορά της χρησιμοποιώντας το γεγονός ότι μπορούμε τώρα να ελέγξουμε τις 2 πρώτες παραμέτρους των συναρτήσεων:
- strcmp(<non read addr>, <non read addr>) -> κατάρρευση
- strcmp(<non read addr>, <read addr>) -> κατάρρευση
- strcmp(<read addr>, <non read addr>) -> κατάρρευση
- strcmp(<read addr>, <read addr>) -> καμία κατάρρευση
Είναι δυνατό να ελέγξετε αυτό καλώντας κάθε καταχώρηση του πίνακα PLT ή χρησιμοποιώντας τη PLT αργή διαδρομή που βασικά συνίσταται στο να καλέσετε μια καταχώρηση στον πίνακα PLT + 0xb (η οποία καλεί το dlresolve
) ακολουθούμενη στο stack από τον αριθμό καταχώρησης που θέλει να ελέγξει (ξεκινώντας από το μηδέν) για να σαρώσει όλες τις καταχωρήσεις PLT από την πρώτη:
- strcmp(<non read addr>, <read addr>) -> κατάρρευση
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
-> Θα καταρρεύσει- strcmp(<read addr>, <non read addr>) -> κατάρρευση
b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
- strcmp(<read addr>, <read addr>) -> καμία κατάρρευση
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
Θυμηθείτε ότι:
- BROP + 0x7 δείχνει στο
pop RSI; pop R15; ret;
- BROP + 0x9 δείχνει στο
pop RDI; ret;
- PLT + 0xb δείχνει σε μια κλήση στο dl_resolve.
Αφού βρείτε το strcmp
, είναι δυνατό να ρυθμίσετε το rdx
σε μια τιμή μεγαλύτερη από 0.
tip
Σημειώστε ότι συνήθως το rdx
θα φιλοξενεί ήδη μια τιμή μεγαλύτερη από 0, οπότε αυτό το βήμα μπορεί να μην είναι απαραίτητο.
8. Εύρεση Write ή ισοδύναμου
Τέλος, χρειάζεται ένα gadget που να εξάγει δεδομένα προκειμένου να εξάγει το δυαδικό. Και σε αυτό το σημείο είναι δυνατό να ελέγξετε 2 παραμέτρους και να ρυθμίσετε το rdx
μεγαλύτερο από 0.
Υπάρχουν 3 κοινές συναρτήσεις που θα μπορούσαν να καταχραστούν για αυτό:
puts(data)
dprintf(fd, data)
write(fd, data, len(data)
Ωστόσο, το αρχικό έγγραφο αναφέρει μόνο τη write
, οπότε ας μιλήσουμε γι' αυτήν:
Το τρέχον πρόβλημα είναι ότι δεν γνωρίζουμε πού βρίσκεται η συνάρτηση write μέσα στον PLT και δεν γνωρίζουμε έναν αριθμό fd για να στείλουμε τα δεδομένα στη socket μας.
Ωστόσο, γνωρίζουμε πού είναι ο πίνακας PLT και είναι δυνατό να βρούμε τη write με βάση τη συμπεριφορά της. Και μπορούμε να δημιουργήσουμε πολλές συνδέσεις με τον server και να χρησιμοποιήσουμε έναν υψηλό FD ελπίζοντας ότι θα ταιριάζει με κάποιες από τις συνδέσεις μας.
Υπογραφές συμπεριφοράς για να βρείτε αυτές τις συναρτήσεις:
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Αν εκτυπωθούν δεδομένα, τότε βρέθηκε η puts'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Αν εκτυπωθούν δεδομένα, τότε βρέθηκε η dprintf'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> Αν εκτυπωθούν δεδομένα, τότε βρέθηκε η write
Automatic Exploitation
References
- Original paper: https://www.scs.stanford.edu/brop/bittau-brop.pdf
- https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop
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.