Leaking libc address with ROP
Γρήγορη Περίληψη
Βρείτε την ανακοχή υπερχείλισης
Βρείτε το gadget
POP_RDI
, τα gadgetsPUTS_PLT
καιMAIN
Χρησιμοποιήστε τα προηγούμενα gadgets για να διαρρεύσετε τη διεύθυνση μνήμης της puts ή μιας άλλης συνάρτησης της libc και βρείτε την έκδοση της libc (κατεβάστε την)
Με τη βιβλιοθήκη, υπολογίστε το ROP και εκμεταλλευτείτε το
Άλλα εκπαιδευτικά μαθήματα και δυαδικά για εξάσκηση
Αυτό το εκπαιδευτικό μάθημα θα εκμεταλλευτεί τον κώδικα/δυαδικό που προτείνεται σε αυτό το μάθημα: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Άλλα χρήσιμα μαθήματα: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
Κώδικας
Όνομα αρχείου: vuln.c
Πρότυπο διαρροής LIBC με ROP
Κατεβάστε το exploit και τοποθετήστε το στον ίδιο φάκελο με το ευπαθές δυαδικό αρχείο και δώστε τα απαιτούμενα δεδομένα στο σενάριο:
pageLeaking libc - template1- Εύρεση της μετατόπισης
Το πρότυπο χρειάζεται μια μετατόπιση πριν συνεχίσει με την εκμετάλλευση. Αν δεν παρέχεται κάποια, θα εκτελέσει τον απαραίτητο κώδικα για να τη βρει (προεπιλεγμένα OFFSET = ""
):
Εκτελέστε python template.py
θα ανοίξει μια κονσόλα GDB με το πρόγραμμα να καταρρέει. Μέσα σε αυτή τη κονσόλα GDB εκτελέστε x/wx $rsp
για να λάβετε τα bytes που θα αντικαταστήσουν το RIP. Τέλος, πάρτε το offset χρησιμοποιώντας μια κονσόλα python:
Αφού βρείτε τη μετατόπιση (σε αυτήν την περίπτωση 40), αλλάξτε τη μεταβλητή OFFSET μέσα στο πρότυπο χρησιμοποιώντας αυτήν την τιμή.
OFFSET = "A" * 40
Μια άλλη μέθοδος θα ήταν να χρησιμοποιήσετε: pattern create 1000
-- εκτέλεση μέχρι το ret -- pattern search $rsp
από το GEF.
2- Εύρεση Gadgets
Τώρα πρέπει να βρούμε ROP gadgets μέσα στο δυαδικό αρχείο. Αυτά τα ROP gadgets θα είναι χρήσιμα για να καλέσουμε τη συνάρτηση puts
για να βρούμε τη libc που χρησιμοποιείται, και αργότερα για να εκτελέσουμε την τελική εκμετάλλευση.
Το PUTS_PLT
χρειάζεται για να καλέσει τη συνάρτηση puts.
Το MAIN_PLT
χρειάζεται για να καλέσει τη κύρια συνάρτηση ξανά μετά από μια αλληλεπίδραση για να εκμεταλλευτεί την υπερχείλιση ξανά (άπειροι γύροι εκμετάλλευσης). Χρησιμοποιείται στο τέλος κάθε ROP για να καλέσει το πρόγραμμα ξανά.
Το POP_RDI χρειάζεται για να περάσει ένα παράμετρο στην κληθείσα συνάρτηση.
Σε αυτό το στάδιο δεν χρειάζεται να εκτελέσετε τίποτα καθώς τα πάντα θα βρεθούν από το pwntools κατά την εκτέλεση.
3- Εύρεση βιβλιοθήκης libc
Τώρα είναι η ώρα να βρούμε ποια έκδοση της βιβλιοθήκης libc χρησιμοποιείται. Για να το κάνουμε αυτό, θα διαρρεύσουμε τη διεύθυνση στη μνήμη της συνάρτησης puts
και στη συνέχεια θα ψάξουμε σε ποια έκδοση βιβλιοθήκης βρίσκεται η έκδοση του puts σε αυτή τη διεύθυνση.
Για να το κάνετε αυτό, η πιο σημαντική γραμμή του εκτελούμενου κώδικα είναι:
Αυτό θα στείλει μερικά bytes μέχρι να είναι δυνατή η αντικατάσταση του RIP: OFFSET
.
Στη συνέχεια, θα ορίσει τη διεύθυνση του gadget POP_RDI
ώστε η επόμενη διεύθυνση (FUNC_GOT
) να αποθηκευτεί στον κατάλογο RDI. Αυτό γίνεται επειδή θέλουμε να καλέσουμε την puts περνώντας την διεύθυνση του PUTS_GOT
ως τη διεύθυνση στη μνήμη της συνάρτησης puts που αποθηκεύεται στη διεύθυνση που δείχνει το PUTS_GOT
.
Στη συνέχεια, θα κληθεί το PUTS_PLT
(με το PUTS_GOT
μέσα στον κατάλογο RDI) έτσι ώστε η puts να διαβάσει το περιεχόμενο μέσα στο PUTS_GOT
(η διεύθυνση της συνάρτησης puts στη μνήμη) και θα το εκτυπώσει.
Τέλος, καλείται ξανά η κύρια συνάρτηση ώστε να μπορέσουμε να εκμεταλλευτούμε ξανά την υπερχείλιση.
Με αυτόν τον τρόπο έχουμε εξαπατήσει τη συνάρτηση puts να εκτυπώσει τη διεύθυνση στη μνήμη της συνάρτησης puts (που βρίσκεται μέσα στη βιβλιοθήκη libc). Τώρα που έχουμε αυτήν τη διεύθυνση μπορούμε να αναζητήσουμε ποια έκδοση της libc χρησιμοποιείται.
Καθώς εκμεταλλευόμαστε ένα τοπικό δυαδικό αρχείο, δεν είναι απαραίτητο να βρούμε ποια έκδοση της libc χρησιμοποιείται (απλά βρείτε τη βιβλιοθήκη στο /lib/x86_64-linux-gnu/libc.so.6
).
Ωστόσο, σε ένα περίπτωση απομακρυσμένης εκμετάλλευσης θα εξηγήσω εδώ πώς μπορείτε να το βρείτε:
3.1- Αναζήτηση για έκδοση libc (1)
Μπορείτε να αναζητήσετε ποια βιβλιοθήκη χρησιμοποιείται στην ιστοσελίδα: https://libc.blukat.me/ Θα σας επιτρέψει επίσης να κατεβάσετε την ανακαλυφθείσα έκδοση της libc
3.2- Αναζήτηση για έκδοση libc (2)
Μπορείτε επίσης να κάνετε:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
Αυτό θα πάρει λίγο χρόνο, είστε υπομονετικοί. Για να λειτουργήσει αυτό, χρειαζόμαστε:
Όνομα συμβόλου Libc:
puts
Διευρυμένη διεύθυνση Libc:
0x7ff629878690
Μπορούμε να καταλάβουμε ποια libc πιθανότατα χρησιμοποιείται.
Λαμβάνουμε 2 αντιστοιχίσεις (θα πρέπει να δοκιμάσετε τη δεύτερη αν η πρώτη δεν λειτουργεί). Κατεβάστε την πρώτη:
Αντιγράψτε το libc από libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
στον τρέχοντα κατάλογο μας.
3.3- Άλλες συναρτήσεις για διαρροή
4- Εύρεση βασισμένης διεύθυνσης της βιβλιοθήκης libc & εκμετάλλευση
Σε αυτό το σημείο πρέπει να γνωρίζουμε τη βιβλιοθήκη libc που χρησιμοποιείται. Καθώς εκμεταλλευόμαστε ένα τοπικό δυαδικό αρχείο, θα χρησιμοποιήσω απλώς: /lib/x86_64-linux-gnu/libc.so.6
Έτσι, στην αρχή του template.py
αλλάξτε τη μεταβλητή libc σε: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Ορίστε τη διαδρομή της βιβλιοθήκης όταν την γνωρίζετε
Δίνοντας τη διαδρομή προς τη βιβλιοθήκη libc, το υπόλοιπο του exploit θα υπολογιστεί αυτόματα.
Μέσα στη συνάρτηση get_addr
θα υπολογιστεί η βασική διεύθυνση της βιβλιοθήκης libc:
Σημειώστε ότι η τελική βάση διεύθυνσης της libc πρέπει να τελειώνει σε 00. Αν αυτό δεν ισχύει στην περίπτωσή σας, ενδέχεται να έχετε διαρρεύσει μια εσφαλμένη βιβλιοθήκη.
Στη συνέχεια, η διεύθυνση της συνάρτησης system
και η διεύθυνση του string "/bin/sh" θα υπολογιστούν από τη βάση της libc και δεδομένης της βιβλιοθήκης libc.
Τέλος, το exploit εκτέλεσης του /bin/sh θα προετοιμαστεί για αποστολή:
Ας εξηγήσουμε αυτό το τελικό ROP.
Το τελευταίο ROP (rop1
) τελείωσε καλώντας ξανά τη συνάρτηση main, οπότε μπορούμε να εκμεταλλευτούμε ξανά το overflow (γι' αυτό είναι ξανά εδώ το OFFSET
). Στη συνέχεια, θέλουμε να καλέσουμε το POP_RDI
δείχνοντας στη διεύθυνση του "/bin/sh" (BINSH
) και να καλέσουμε τη συνάρτηση system (SYSTEM
) επειδή η διεύθυνση του "/bin/sh" θα περάσει ως παράμετρος.
Τέλος, καλείται η διεύθυνση της συνάρτησης exit έτσι ώστε η διαδικασία να τερματιστεί κανονικά και να μην παράγεται κανένα συναγερμός.
Με αυτόν τον τρόπο το exploit θα εκτελέσει ένα _/bin/sh_** shell.**
4(2)- Χρησιμοποιώντας ONE_GADGET
Θα μπορούσατε επίσης να χρησιμοποιήσετε το ONE_GADGET για να αποκτήσετε ένα shell αντί να χρησιμοποιήσετε το system και το "/bin/sh". Το ONE_GADGET θα βρει μέσα στη βιβλιοθήκη libc κάποιον τρόπο να αποκτήσετε ένα shell χρησιμοποιώντας μόνο μια διεύθυνση ROP.
Ωστόσο, συνήθως υπάρχουν κάποιοι περιορισμοί, οι πιο συνηθισμένοι και εύκολοι να αποφευχθούν είναι όπως [rsp+0x30] == NULL
. Καθώς ελέγχετε τις τιμές μέσα στο RSP, απλά πρέπει να στείλετε μερικές περισσότερες τιμές NULL ώστε ο περιορισμός να αποφευχθεί.
ΑΡΧΕΙΟ EXPLOIT
Μπορείτε να βρείτε ένα πρότυπο για την εκμετάλλευση αυτής της ευπάθειας εδώ:
pageLeaking libc - templateΣυνηθισμένα προβλήματα
MAIN_PLT = elf.symbols['main'] δεν βρέθηκε
Αν το σύμβολο "main" δεν υπάρχει. Τότε μπορείτε να βρείτε πού βρίσκεται ο κώδικας του main:
και ορίστε τη διεύθυνση χειροκίνητα:
Η συνάρτηση Puts δεν βρέθηκε
Αν το δυαδικό αρχείο δεν χρησιμοποιεί τη συνάρτηση Puts, πρέπει να ελέγξετε αν χρησιμοποιεί
sh: 1: %s%s%s%s%s%s%s%s: not found
sh: 1: %s%s%s%s%s%s%s%s: not found
Αν βρείτε αυτό το σφάλμα μετά τη δημιουργία όλων των εκμεταλλεύσεων: sh: 1: %s%s%s%s%s%s%s%s: not found
Δοκιμάστε να αφαιρέσετε 64 bytes από τη διεύθυνση του "/bin/sh":
Last updated