BROP - Blind Return Oriented Programming

Υποστηρίξτε το HackTricks

Βασικές Πληροφορίες

Ο στόχος αυτής της επίθεσης είναι να καταχραστεί ένα ROP μέσω ενός buffer overflow χωρίς καμία πληροφορία για το ευάλωτο δυαδικό. Αυτή η επίθεση βασίζεται στο ακόλουθο σενάριο:

  • Μια ευπαθής στοίβα και γνώση για το πώς να την ενεργοποιήσετε.

  • Ένα εφαρμογή διακομιστή που επανεκκινείται μετά από κάθε κατάρρευση.

Επίθεση

1. Εύρεση ευπαθούς μετατόπισης αποστέλλοντας έναν επιπλέον χαρακτήρα μέχρι να ανιχνευθεί μια δυσλειτουργία του διακομιστή

2. Βίαιη αναζήτηση canary για διαρροή

3. Βίαιη αναζήτηση αποθηκευμένων RBP και RIP διευθύνσεων στη στοίβα για διαρροή τους

Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με αυτές τις διαδικασίες εδώ (BF Forked & Threaded Stack Canaries) και εδώ (BF Διευθύνσεις στη Στοίβα).

4. Εύρεση του gadget στάσης

Αυτό το gadget επιτρέπει ουσιαστικά να επιβεβαιωθεί ότι κάτι ενδιαφέρον εκτελέστηκε από το ROP gadget επειδή η εκτέλεση δεν κατέρρευσε. Συνήθως, αυτό το gadget θα είναι κάτι που σταματά την εκτέλεση και θα βρίσκεται στο τέλος της αλυσίδας ROP κατά την αναζήτηση ROP gadgets για να επιβεβαιώσετε ότι ένα συγκεκριμένο ROP gadget εκτελέστηκε.

5. Εύρεση BROP gadget

Αυτή η τεχνική χρησιμοποιεί το ret2csu gadget. Και αυτό οφείλεται στο γεγονός ότι αν έχετε πρόσβαση σε αυτό το gadget στη μέση ορισμένων οδηγιών, λαμβάνετε gadgets για να ελέγξετε τα rsi και rdi:

Αυτά θα ήταν τα gadgets:

  • pop rsi; pop r15; ret

  • pop rdi; ret

Παρατηρήστε πώς με αυτά τα gadgets είναι δυνατό να ελέγξετε 2 ορίσματα μιας συνάρτησης προς κλήση.

Επίσης, παρατηρήστε ότι το ret2csu gadget έχει μια πολύ μοναδική υπογραφή επειδή θα αποσυρθούν 6 καταχωρητές από τη στοίβα. Έτσι, αποστέλλοντας μια αλυσίδα όπως:

'A' * μετατόπιση + canary + rbp + ΔΙΕΥΘΥΝΣΗ + 0xdead * 6 + STOP

Αν το STOP εκτελεστεί, αυτό σημαίνει βασικά ότι χρησιμοποιήθηκε μια διεύθυνση που αποσύρει 6 καταχωρητές από τη στοίβα. Ή ότι η χρησιμοποιηθείσα διεύθυνση ήταν επίσης μια διεύθυνση STOP.

Για να αφαιρέσετε αυτήν την τελευταία επιλογή, εκτελείται μια νέα αλυσίδα όπως η ακόλουθη και δεν πρέπει να εκτελεστεί το STOP gadget για να επιβεβαιωθεί ότι η προηγούμενη αποσύρθηκε 6 καταχωρητές:

'A' * μετατόπιση + canary + rbp + ΔΙΕΥΘΥΝΣΗ

Γνωρίζοντας τη διεύθυνση του ret2csu gadget, είναι δυνατό να συμπεράνετε τη διεύθυνση των gadgets για τον έλεγχο του rsi και rdi.

6. Εύρεση PLT

Η πίνακας PLT μπορεί να αναζητηθεί από το 0x400000 ή από τη διευθύνση RIP που διέρρευσε από τη στοίβα (εάν χρησιμοποιείται PIE). Τα στοιχεία του πίνακα είναι χωρισμένα κατά 16B (0x10B), και όταν καλείται μια συνάρτηση ο διακομιστής δεν καταρρέει ακόμα και αν τα ορίσματα δεν είναι σωστά. Επίσης, η ελέγχουμε τη διεύθυνση ενός στοιχείου στο PLT + 6B δεν καταρρέει καθώς είναι ο πρώτος κώδικας που εκτελείται.

Επομένως, είναι δυνατό να βρείτε τον πίνακα PLT ελέγχοντας την ακόλουθη συμπεριφορά:

  • 'A' * μετατόπιση + canary + rbp + ΔΙΕΥΘΥΝΣΗ + STOP -> χωρίς κατάρρευση

  • 'A' * μετατόπιση + canary + rbp + (ΔΙΕΥΘΥΝΣΗ + 0x6) + STOP -> χωρίς κατάρρευση

  • 'A' * μετατόπιση + canary + rbp + (ΔΙΕΥΘΥΝΣΗ + 0x10) + STOP -> χωρίς κατάρρευση

7. Εύρεση strcmp

Η συνάρτηση strcmp ορίζει τον καταχωρητή rdx στο μήκος του συμβολοσειράς που συγκρίνεται. Σημειώστε ότι το rdx είναι το τρίτο όρισμα και χρειαζόμαστε να είναι μεγαλύτερο από 0 για να χρησιμοποιήσουμε αργότερα την write για να διαρρεύσουμε το πρόγραμμα.

Είναι δυνατό να βρεθεί η τοποθεσία του strcmp στο PLT βασιζόμενο στη συμπεριφορά του χρησιμοποιώντας το γεγονός ότι τώρα μπορούμε να ελέγξουμε τα 2 πρώτα ορίσματα των συναρτήσεων:

  • strcmp(<μη αναγνωσμένη διεύθυνση>, <μη αναγνωσμένη διεύθυνση>) -> κατάρρευση

  • strcmp(<μη αναγνωσμένη διεύθυνση>, <αναγνωσμένη διεύθυνση>) -> κατάρρευση

  • strcmp(<αναγνωσμένη διεύθυνση>, <μη αναγνωσμένη διεύθυνση>) -> κατάρρευση

  • strcmp(<αναγνωσμένη διεύθυνση>, <αναγνωσμένη διεύθυνση>) -> χωρίς κατάρρευση

Είναι δυνατό να ελεγχθεί αυτό καλώντας κάθε είσοδο του πίνακα PLT ή χρησιμοποιώντας τη PLT slow path που ουσιαστικά αποτελείται από το κάλεσμα ενός στοιχείου στον πίνακα PLT + 0xb (που καλεί το dlresolve) ακολουθούμενο στη στοίβα από τον αριθμό εισόδου που επιθυμεί κανείς να εξετάσει (ξεκινώντ

8. Εύρεση Write ή ισοδύναμου

Τέλος, απαιτείται ένα εργαλείο που εξαγάγει δεδομένα για να εξαχθεί το δυαδικό. Και αυτή τη στιγμή είναι δυνατόν να ελέγξουμε 2 ορίσματα και να ορίσουμε το rdx μεγαλύτερο από 0.

Υπάρχουν 3 κοινές συναρτήσεις που μπορούν να καταχραστούν γι' αυτό:

  • puts(data)

  • dprintf(fd, data)

  • write(fd, data, len(data)

Ωστόσο, το αρχικό έγγραφο αναφέρει μόνο τη write, οπότε ας μιλήσουμε γι' αυτήν:

Το τρέχον πρόβλημα είναι ότι δεν γνωρίζουμε πού βρίσκεται η συνάρτηση write μέσα στο PLT και δεν γνωρίζουμε έναν αριθμό fd για να στείλουμε τα δεδομένα στο socket μας.

Ωστόσο, γνωρίζουμε πού βρίσκεται ο πίνακας PLT και είναι δυνατόν να βρούμε την write βασιζόμενοι στην συμπεριφορά της. Και μπορούμε να δημιουργήσουμε πολλαπλές συνδέσεις με τον εξυπηρετητή και να χρησιμοποιήσουμε ένα υψηλό 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

Αυτόματη Εκμετάλλευση

Αναφορές

Last updated