mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/basic-stack-binary-exploitation-met
This commit is contained in:
parent
e2cbe38192
commit
54fe06f064
@ -47,10 +47,12 @@ Segment Sections...
|
||||
|
||||
Υποδεικνύει τη διαδρομή του φορτωτή που θα χρησιμοποιηθεί για να φορτώσει το δυαδικό αρχείο στη μνήμη.
|
||||
|
||||
> Συμβουλή: Τα στατικά συνδεδεμένα ή στατικά-PIE δυαδικά αρχεία δεν θα έχουν είσοδο `INTERP`. Σε αυτές τις περιπτώσεις δεν εμπλέκεται δυναμικός φορτωτής, γεγονός που απενεργοποιεί τεχνικές που βασίζονται σε αυτόν (π.χ., `ret2dlresolve`).
|
||||
|
||||
### LOAD
|
||||
|
||||
Αυτές οι επικεφαλίδες χρησιμοποιούνται για να υποδείξουν **πώς να φορτώσετε ένα δυαδικό αρχείο στη μνήμη.**\
|
||||
Κάθε **LOAD** επικεφαλίδα υποδεικνύει μια περιοχή **μνήμης** (μέγεθος, δικαιώματα και ευθυγράμμιση) και υποδεικνύει τα bytes του ELF **δυαδικού αρχείου που θα αντιγραφούν εκεί**.
|
||||
Κάθε επικεφαλίδα **LOAD** υποδεικνύει μια περιοχή **μνήμης** (μέγεθος, δικαιώματα και ευθυγράμμιση) και υποδεικνύει τα bytes του ELF **δυαδικού αρχείου που θα αντιγραφούν εκεί**.
|
||||
|
||||
Για παράδειγμα, η δεύτερη έχει μέγεθος 0x1190, θα πρέπει να βρίσκεται στη διεύθυνση 0x1fc48 με δικαιώματα ανάγνωσης και εγγραφής και θα γεμίσει με 0x528 από την απόσταση 0xfc48 (δεν γεμίζει όλο τον κρατημένο χώρο). Αυτή η μνήμη θα περιέχει τα τμήματα `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
@ -62,13 +64,21 @@ Segment Sections...
|
||||
|
||||
Αυτό αποθηκεύει πληροφορίες μεταδεδομένων προμηθευτή σχετικά με το δυαδικό αρχείο.
|
||||
|
||||
- Στο x86-64, `readelf -n` θα δείξει τις σημαίες `GNU_PROPERTY_X86_FEATURE_1_*` μέσα στο `.note.gnu.property`. Αν δείτε `IBT` και/ή `SHSTK`, το δυαδικό αρχείο έχει κατασκευαστεί με CET (Παρακολούθηση Έμμεσων Κλάδων και/ή Σκιά Στοίβας). Αυτό επηρεάζει το ROP/JOP επειδή οι στόχοι έμμεσων κλάδων πρέπει να ξεκινούν με μια εντολή `ENDBR64` και οι επιστροφές ελέγχονται σε σχέση με μια σκιά στοίβας. Δείτε τη σελίδα CET για λεπτομέρειες και σημειώσεις παράκαμψης.
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
{{#endref}}
|
||||
|
||||
### GNU_EH_FRAME
|
||||
|
||||
Ορίζει την τοποθεσία των πινάκων αποσυμπίεσης στοίβας, που χρησιμοποιούνται από αποσφαλματωτές και συναρτήσεις χειρισμού εξαιρέσεων C++.
|
||||
Ορίζει τη θέση των πινάκων αποσυμπίεσης στοίβας, που χρησιμοποιούνται από αποσφαλματωτές και συναρτήσεις χειρισμού εξαιρέσεων C++.
|
||||
|
||||
### GNU_STACK
|
||||
|
||||
Περιέχει τη ρύθμιση της άμυνας κατά της εκτέλεσης στοίβας. Εάν είναι ενεργοποιημένη, το δυαδικό αρχείο δεν θα μπορεί να εκτελεί κώδικα από τη στοίβα.
|
||||
Περιέχει τη ρύθμιση της άμυνας κατά της εκτέλεσης από τη στοίβα. Αν είναι ενεργοποιημένο, το δυαδικό αρχείο δεν θα μπορεί να εκτελεί κώδικα από τη στοίβα.
|
||||
|
||||
- Ελέγξτε με `readelf -l ./bin | grep GNU_STACK`. Για να το αλλάξετε αναγκαστικά κατά τη διάρκεια δοκιμών μπορείτε να χρησιμοποιήσετε `execstack -s|-c ./bin`.
|
||||
|
||||
### GNU_RELRO
|
||||
|
||||
@ -76,11 +86,17 @@ Segment Sections...
|
||||
|
||||
Στο προηγούμενο παράδειγμα, αντιγράφει 0x3b8 bytes στη διεύθυνση 0x1fc48 ως μόνο για ανάγνωση επηρεάζοντας τα τμήματα `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
Σημειώστε ότι το RELRO μπορεί να είναι μερικό ή πλήρες, η μερική έκδοση δεν προστατεύει το τμήμα **`.plt.got`**, το οποίο χρησιμοποιείται για **lazy binding** και χρειάζεται αυτόν τον χώρο μνήμης για να έχει **δικαιώματα εγγραφής** για να γράψει τη διεύθυνση των βιβλιοθηκών την πρώτη φορά που αναζητείται η τοποθεσία τους.
|
||||
Σημειώστε ότι το RELRO μπορεί να είναι μερικό ή πλήρες, η μερική έκδοση δεν προστατεύει το τμήμα **`.plt.got`**, το οποίο χρησιμοποιείται για **τεμπέλη σύνδεση** και χρειάζεται αυτόν τον χώρο μνήμης για να έχει **δικαιώματα εγγραφής** για να γράψει τη διεύθυνση των βιβλιοθηκών την πρώτη φορά που αναζητείται η τοποθεσία τους.
|
||||
|
||||
> Για τεχνικές εκμετάλλευσης και ενημερωμένες σημειώσεις παράκαμψης, ελέγξτε τη συγκεκριμένη σελίδα:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
### TLS
|
||||
|
||||
Ορίζει έναν πίνακα καταχωρήσεων TLS, ο οποίος αποθηκεύει πληροφορίες σχετικά με τις τοπικές μεταβλητές νήματος.
|
||||
Ορίζει έναν πίνακα εισόδων TLS, ο οποίος αποθηκεύει πληροφορίες σχετικά με τις μεταβλητές τοπικής νήματος.
|
||||
|
||||
## Επικεφαλίδες Τμημάτων
|
||||
|
||||
@ -145,26 +161,26 @@ 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**.
|
||||
- **String table**: Περιέχει όλα τα strings που χρειάζεται το ELF αρχείο (αλλά όχι αυτά που χρησιμοποιούνται πραγματικά από το πρόγραμμα). Για παράδειγμα, περιέχει ονόματα τμημάτων όπως `.text` ή `.data`. Και αν το `.text` είναι στο offset 45 στον πίνακα strings, θα χρησιμοποιήσει τον αριθμό **45** στο πεδίο **name**.
|
||||
- Για να βρείτε πού είναι ο πίνακας strings, το ELF περιέχει έναν δείκτη στον πίνακα strings.
|
||||
- **Symbol table**: Περιέχει πληροφορίες για τα σύμβολα όπως το όνομα (απόσταση στον πίνακα strings), διεύθυνση, μέγεθος και περισσότερα μεταδεδομένα σχετικά με το σύμβολο.
|
||||
- **Symbol table**: Περιέχει πληροφορίες για τα symbols όπως το όνομα (offset στον πίνακα strings), διεύθυνση, μέγεθος και περισσότερα μεταδεδομένα σχετικά με το symbol.
|
||||
|
||||
### Κύριες Ενότητες
|
||||
### Main Sections
|
||||
|
||||
- **`.text`**: Οι εντολές του προγράμματος που πρέπει να εκτελούνται.
|
||||
- **`.data`**: Παγκόσμιες μεταβλητές με καθορισμένη τιμή στο πρόγραμμα.
|
||||
- **`.bss`**: Παγκόσμιες μεταβλητές που έχουν μείνει μη αρχικοποιημένες (ή αρχικοποιημένες σε μηδέν). Οι μεταβλητές εδώ αρχικοποιούνται αυτόματα σε μηδέν, αποτρέποντας έτσι την προσθήκη άχρηστων μηδενικών στο δυαδικό.
|
||||
- **`.rodata`**: Σταθερές παγκόσμιες μεταβλητές (τμήμα μόνο για ανάγνωση).
|
||||
- **`.tdata`** και **`.tbss`**: Όπως οι .data και .bss όταν χρησιμοποιούνται μεταβλητές τοπικές σε νήματα (`__thread_local` σε C++ ή `__thread` σε C).
|
||||
- **`.tdata`** και **`.tbss`**: Όπως οι .data και .bss όταν χρησιμοποιούνται μεταβλητές τοπικού νήματος (`__thread_local` σε C++ ή `__thread` σε C).
|
||||
- **`.dynamic`**: Δείτε παρακάτω.
|
||||
|
||||
## Σύμβολα
|
||||
## Symbols
|
||||
|
||||
Τα σύμβολα είναι μια ονομαστική τοποθεσία στο πρόγραμμα που μπορεί να είναι μια συνάρτηση, ένα παγκόσμιο αντικείμενο δεδομένων, μεταβλητές τοπικές σε νήματα...
|
||||
Symbols είναι μια ονομασμένη τοποθεσία στο πρόγραμμα που μπορεί να είναι μια συνάρτηση, ένα παγκόσμιο αντικείμενο δεδομένων, μεταβλητές τοπικού νήματος...
|
||||
```
|
||||
readelf -s lnstat
|
||||
|
||||
@ -190,10 +206,14 @@ Num: Value Size Type Bind Vis Ndx Name
|
||||
- **Όνομα**
|
||||
- **Δεσμευτικά χαρακτηριστικά** (ασθενές, τοπικό ή παγκόσμιο): Ένα τοπικό σύμβολο μπορεί να προσπελαστεί μόνο από το ίδιο το πρόγραμμα, ενώ τα παγκόσμια σύμβολα μοιράζονται εκτός του προγράμματος. Ένα ασθενές αντικείμενο είναι για παράδειγμα μια συνάρτηση που μπορεί να παρακαμφθεί από μια διαφορετική.
|
||||
- **Τύπος**: NOTYPE (κανένας τύπος καθορισμένος), OBJECT (παγκόσμια μεταβλητή δεδομένων), FUNC (συνάρτηση), SECTION (ενότητα), FILE (αρχείο πηγαίου κώδικα για αποσφαλμάτωση), TLS (μεταβλητή τοπικού νήματος), GNU_IFUNC (έμμεση συνάρτηση για ανακατανομή)
|
||||
- **Δείκτης ενότητας** όπου βρίσκεται
|
||||
- **Δείκτης Ενότητας** όπου βρίσκεται
|
||||
- **Τιμή** (διεύθυνση στη μνήμη)
|
||||
- **Μέγεθος**
|
||||
|
||||
#### GNU Symbol Versioning (dynsym/dynstr/gnu.version)
|
||||
|
||||
Η σύγχρονη glibc χρησιμοποιεί εκδόσεις συμβόλων. Θα δείτε καταχωρήσεις στα `.gnu.version` και `.gnu.version_r` και ονόματα συμβόλων όπως `strlen@GLIBC_2.17`. Ο δυναμικός συνδέτης μπορεί να απαιτεί μια συγκεκριμένη έκδοση κατά την επίλυση ενός συμβόλου. Όταν δημιουργείτε χειροκίνητες ανακατανομές (π.χ. ret2dlresolve) πρέπει να παρέχετε τον σωστό δείκτη έκδοσης, διαφορετικά η επίλυση αποτυγχάνει.
|
||||
|
||||
## Δυναμική Ενότητα
|
||||
```
|
||||
readelf -d lnstat
|
||||
@ -229,9 +249,26 @@ Tag Type Name/Value
|
||||
0x000000006ffffff9 (RELACOUNT) 15
|
||||
0x0000000000000000 (NULL) 0x0
|
||||
```
|
||||
Ο φάκελος NEEDED υποδεικνύει ότι το πρόγραμμα **χρειάζεται να φορτώσει τη συγκεκριμένη βιβλιοθήκη** προκειμένου να συνεχίσει. Ο φάκελος NEEDED ολοκληρώνεται μόλις η κοινή **βιβλιοθήκη είναι πλήρως λειτουργική και έτοιμη** προς χρήση.
|
||||
Ο φάκελος NEEDED υποδεικνύει ότι το πρόγραμμα **χρειάζεται να φορτώσει τη συγκεκριμένη βιβλιοθήκη** για να συνεχίσει. Ο φάκελος NEEDED ολοκληρώνεται μόλις η κοινή **βιβλιοθήκη είναι πλήρως λειτουργική και έτοιμη** προς χρήση.
|
||||
|
||||
## Relocations
|
||||
### Σειρά αναζήτησης του δυναμικού φορτωτή (RPATH/RUNPATH, $ORIGIN)
|
||||
|
||||
Οι καταχωρίσεις `DT_RPATH` (παρωχημένο) και/ή `DT_RUNPATH` επηρεάζουν το πού αναζητά ο δυναμικός φορτωτής τις εξαρτήσεις. Γενική σειρά:
|
||||
|
||||
- `LD_LIBRARY_PATH` (αγνοείται για προγράμματα setuid/sgid ή αλλιώς "ασφαλούς εκτέλεσης")
|
||||
- `DT_RPATH` (μόνο αν απουσιάζει το `DT_RUNPATH`)
|
||||
- `DT_RUNPATH`
|
||||
- `ld.so.cache`
|
||||
- προεπιλεγμένοι φάκελοι όπως `/lib64`, `/usr/lib64`, κ.λπ.
|
||||
|
||||
`$ORIGIN` μπορεί να χρησιμοποιηθεί μέσα στο RPATH/RUNPATH για να αναφέρεται στον φάκελο του κύριου αντικειμένου. Από την οπτική γωνία ενός επιτιθέμενου, αυτό έχει σημασία όταν ελέγχετε τη διάταξη του συστήματος αρχείων ή το περιβάλλον. Για σκληρυμένα δυαδικά αρχεία (AT_SECURE), οι περισσότερες μεταβλητές περιβάλλοντος αγνοούνται από τον φορτωτή.
|
||||
|
||||
- Εξετάστε με: `readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- Γρήγορη δοκιμή: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (δείχνει αποφάσεις διαδρομής αναζήτησης)
|
||||
|
||||
> Συμβουλή για Priv-esc: Προτιμήστε να εκμεταλλευτείτε τα εγγράψιμα RUNPATH ή τα κακώς ρυθμισμένα μονοπάτια σχετικά με το `$ORIGIN` που ανήκουν σε εσάς. Οι LD_PRELOAD/LD_AUDIT αγνοούνται σε περιβάλλοντα ασφαλούς εκτέλεσης (setuid).
|
||||
|
||||
## Μετατοπίσεις
|
||||
|
||||
Ο φορτωτής πρέπει επίσης να μετατοπίσει τις εξαρτήσεις αφού τις έχει φορτώσει. Αυτές οι μετατοπίσεις υποδεικνύονται στον πίνακα μετατοπίσεων σε μορφές REL ή RELA και ο αριθμός των μετατοπίσεων δίνεται στις δυναμικές ενότητες RELSZ ή RELASZ.
|
||||
```
|
||||
@ -274,7 +311,6 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
00000001fea0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 perror@GLIBC_2.17 + 0
|
||||
00000001fea8 000b00000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0
|
||||
00000001feb0 000c00000402 R_AARCH64_JUMP_SL 0000000000000000 putc@GLIBC_2.17 + 0
|
||||
00000001feb8 000d00000402 R_AARCH64_JUMP_SL 0000000000000000 opendir@GLIBC_2.17 + 0
|
||||
00000001fec0 000e00000402 R_AARCH64_JUMP_SL 0000000000000000 fputc@GLIBC_2.17 + 0
|
||||
00000001fec8 001100000402 R_AARCH64_JUMP_SL 0000000000000000 snprintf@GLIBC_2.17 + 0
|
||||
00000001fed0 001200000402 R_AARCH64_JUMP_SL 0000000000000000 __snprintf_chk@GLIBC_2.17 + 0
|
||||
@ -310,7 +346,7 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
|
||||
Αν το **πρόγραμμα φορτωθεί σε διαφορετική θέση** από τη προτιμώμενη διεύθυνση (συνήθως 0x400000) επειδή η διεύθυνση είναι ήδη χρησιμοποιούμενη ή λόγω **ASLR** ή οποιουδήποτε άλλου λόγου, μια στατική μετάθεση **διορθώνει τους δείκτες** που είχαν τιμές περιμένοντας το δυαδικό να φορτωθεί στη προτιμώμενη διεύθυνση.
|
||||
|
||||
Για παράδειγμα, οποιαδήποτε ενότητα τύπου `R_AARCH64_RELATIV` θα πρέπει να έχει τροποποιήσει τη διεύθυνση με το μεταθετικό σφάλμα συν την τιμή προσθέτου.
|
||||
Για παράδειγμα, οποιαδήποτε ενότητα τύπου `R_AARCH64_RELATIV` θα πρέπει να έχει τροποποιήσει τη διεύθυνση με το μεταθετικό σφάλμα συν την τιμή προσθήκης.
|
||||
|
||||
### Δυναμικές Μεταθέσεις και GOT
|
||||
|
||||
@ -318,13 +354,31 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
|
||||
### Πίνακας Σύνδεσης Διαδικασιών
|
||||
|
||||
Η ενότητα PLT επιτρέπει την εκτέλεση καθυστερημένης σύνδεσης, που σημαίνει ότι η επίλυση της τοποθεσίας μιας συνάρτησης θα εκτελείται την πρώτη φορά που θα προσπελαστεί.
|
||||
Η ενότητα PLT επιτρέπει την εκτέλεση καθυστερημένης σύνδεσης, που σημαίνει ότι η επίλυση της τοποθεσίας μιας συνάρτησης θα πραγματοποιηθεί την πρώτη φορά που θα προσπελαστεί.
|
||||
|
||||
Έτσι, όταν ένα πρόγραμμα καλεί τη malloc, στην πραγματικότητα καλεί την αντίστοιχη τοποθεσία του `malloc` στον PLT (`malloc@plt`). Την πρώτη φορά που καλείται, επιλύει τη διεύθυνση του `malloc` και την αποθηκεύει, έτσι ώστε την επόμενη φορά που θα κληθεί η `malloc`, αυτή η διεύθυνση να χρησιμοποιείται αντί του κώδικα PLT.
|
||||
Έτσι, όταν ένα πρόγραμμα καλεί το malloc, στην πραγματικότητα καλεί την αντίστοιχη τοποθεσία του `malloc` στον PLT (`malloc@plt`). Την πρώτη φορά που καλείται, επιλύει τη διεύθυνση του `malloc` και την αποθηκεύει, ώστε την επόμενη φορά που θα κληθεί το `malloc`, αυτή η διεύθυνση να χρησιμοποιείται αντί για τον κώδικα του PLT.
|
||||
|
||||
#### Σύγχρονη συμπεριφορά σύνδεσης που επηρεάζει την εκμετάλλευση
|
||||
|
||||
- `-z now` (Πλήρης RELRO) απενεργοποιεί την καθυστερημένη σύνδεση; οι καταχωρήσεις PLT εξακολουθούν να υπάρχουν αλλά ο GOT/PLT είναι χαρτογραφημένος σε μόνο ανάγνωση, οπότε τεχνικές όπως **GOT overwrite** και **ret2dlresolve** δεν θα λειτουργήσουν κατά του κύριου δυαδικού (οι βιβλιοθήκες μπορεί να είναι ακόμα μερικώς RELRO). Δείτε:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
- `-fno-plt` κάνει τον μεταγλωττιστή να καλεί εξωτερικές συναρτήσεις μέσω της **καταχώρησης GOT απευθείας** αντί να περνάει από το stub του PLT. Θα δείτε ακολουθίες κλήσεων όπως `mov reg, [got]; call reg` αντί για `call func@plt`. Αυτό μειώνει την κατάχρηση της υποθετικής εκτέλεσης και αλλάζει ελαφρώς την αναζήτηση gadget ROP γύρω από τα stubs του PLT.
|
||||
|
||||
- PIE vs static-PIE: Το PIE (ET_DYN με `INTERP`) χρειάζεται τον δυναμικό φορτωτή και υποστηρίζει τη συνήθη μηχανική PLT/GOT. Το Static-PIE (ET_DYN χωρίς `INTERP`) έχει μεταθέσεις που εφαρμόζονται από τον φορτωτή του πυρήνα και κανένα `ld.so`; αναμένετε καμία επίλυση PLT κατά την εκτέλεση.
|
||||
|
||||
> Αν το GOT/PLT δεν είναι επιλογή, στραφείτε σε άλλους γράψιμους δείκτες κώδικα ή χρησιμοποιήστε κλασικό ROP/SROP στο libc.
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/aw2exec-got-plt.md
|
||||
{{#endref}}
|
||||
|
||||
## Αρχικοποίηση Προγράμματος
|
||||
|
||||
Αφού το πρόγραμμα έχει φορτωθεί, ήρθε η ώρα να εκτελεστεί. Ωστόσο, ο πρώτος κώδικας που εκτελείται **δεν είναι πάντα η συνάρτηση `main`**. Αυτό συμβαίνει επειδή, για παράδειγμα, σε C++ αν μια **παγκόσμια μεταβλητή είναι ένα αντικείμενο μιας κλάσης**, αυτό το αντικείμενο πρέπει να **αρχικοποιηθεί** **πριν** εκτελεστεί το main, όπως στο:
|
||||
Αφού το πρόγραμμα έχει φορτωθεί, είναι ώρα να τρέξει. Ωστόσο, ο πρώτος κώδικας που εκτελείται **δεν είναι πάντα η συνάρτηση `main`**. Αυτό συμβαίνει επειδή, για παράδειγμα, σε C++ αν μια **παγκόσμια μεταβλητή είναι ένα αντικείμενο μιας κλάσης**, αυτό το αντικείμενο πρέπει να **αρχικοποιηθεί** **πριν** εκτελεστεί το main, όπως στο:
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
// g++ autoinit.cpp -o autoinit
|
||||
@ -352,12 +406,22 @@ return 0;
|
||||
__attributte__((constructor)) //Add a constructor to execute before
|
||||
__attributte__((destructor)) //Add to the destructor list
|
||||
```
|
||||
Από την προοπτική ενός μεταγλωττιστή, για να εκτελούνται αυτές οι ενέργειες πριν και μετά την εκτέλεση της συνάρτησης `main`, είναι δυνατόν να δημιουργηθεί μια συνάρτηση `init` και μια συνάρτηση `fini` που θα αναφέρονται στην δυναμική ενότητα ως **`INIT`** και **`FIN`**. και τοποθετούνται στις ενότητες `init` και `fini` του ELF.
|
||||
Από την προοπτική ενός μεταγλωττιστή, για να εκτελούνται αυτές οι ενέργειες πριν και μετά την εκτέλεση της `main` συνάρτησης, είναι δυνατόν να δημιουργηθεί μια `init` συνάρτηση και μια `fini` συνάρτηση που θα αναφέρονται στην δυναμική ενότητα ως **`INIT`** και **`FIN`**. και τοποθετούνται στις ενότητες `init` και `fini` του ELF.
|
||||
|
||||
Η άλλη επιλογή, όπως αναφέρθηκε, είναι να αναφερθούν οι λίστες **`__CTOR_LIST__`** και **`__DTOR_LIST__`** στις εγγραφές **`INIT_ARRAY`** και **`FINI_ARRAY`** στη δυναμική ενότητα και το μήκος τους υποδεικνύεται από **`INIT_ARRAYSZ`** και **`FINI_ARRAYSZ`**. Κάθε εγγραφή είναι ένας δείκτης συνάρτησης που θα καλείται χωρίς παραμέτρους.
|
||||
Η άλλη επιλογή, όπως αναφέρθηκε, είναι να αναφερθούν οι λίστες **`__CTOR_LIST__`** και **`__DTOR_LIST__`** στις εγγραφές **`INIT_ARRAY`** και **`FINI_ARRAY`** στην δυναμική ενότητα και το μήκος αυτών υποδεικνύεται από **`INIT_ARRAYSZ`** και **`FINI_ARRAYSZ`**. Κάθε εγγραφή είναι ένας δείκτης συνάρτησης που θα καλείται χωρίς παραμέτρους.
|
||||
|
||||
Επιπλέον, είναι επίσης δυνατό να υπάρχει μια **`PREINIT_ARRAY`** με **δείκτες** που θα εκτελούνται **πριν** από τους δείκτες **`INIT_ARRAY`**.
|
||||
|
||||
#### Σημείωση εκμετάλλευσης
|
||||
|
||||
- Κάτω από το Partial RELRO αυτές οι πίνακες βρίσκονται σε σελίδες που είναι ακόμα εγγράψιμες πριν το `ld.so` αλλάξει το `PT_GNU_RELRO` σε μόνο ανάγνωση. Αν αποκτήσετε μια αυθαίρετη εγγραφή αρκετά νωρίς ή μπορείτε να στοχεύσετε τις εγγράψιμες λίστες μιας βιβλιοθήκης, μπορείτε να αναλάβετε τον έλεγχο της ροής εκτέλεσης αντικαθιστώντας μια εγγραφή με μια συνάρτηση της επιλογής σας. Κάτω από το Full RELRO είναι μόνο για ανάγνωση κατά την εκτέλεση.
|
||||
|
||||
- Για κακή χρήση της καθυστερημένης σύνδεσης του δυναμικού συνδέτη για την επίλυση αυθαίρετων συμβόλων κατά την εκτέλεση, δείτε τη σελίδα που είναι αφιερωμένη:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2dlresolve.md
|
||||
{{#endref}}
|
||||
|
||||
### Σειρά Αρχικοποίησης
|
||||
|
||||
1. Το πρόγραμμα φορτώνεται στη μνήμη, οι στατικές παγκόσμιες μεταβλητές αρχικοποιούνται στο **`.data`** και οι μη αρχικοποιημένες μηδενίζονται στο **`.bss`**.
|
||||
@ -365,7 +429,7 @@ __attributte__((destructor)) //Add to the destructor list
|
||||
3. Οι συναρτήσεις **`PREINIT_ARRAY`** εκτελούνται.
|
||||
4. Οι συναρτήσεις **`INIT_ARRAY`** εκτελούνται.
|
||||
5. Αν υπάρχει μια εγγραφή **`INIT`**, καλείται.
|
||||
6. Αν είναι μια βιβλιοθήκη, το dlopen τελειώνει εδώ, αν είναι πρόγραμμα, είναι ώρα να καλέσουμε το **πραγματικό σημείο εισόδου** (συνάρτηση `main`).
|
||||
6. Αν είναι βιβλιοθήκη, το dlopen τελειώνει εδώ, αν είναι πρόγραμμα, είναι ώρα να καλέσετε το **πραγματικό σημείο εισόδου** (συνάρτηση `main`).
|
||||
|
||||
## Αποθήκευση Τοπικών Νημάτων (TLS)
|
||||
|
||||
@ -375,8 +439,35 @@ __attributte__((destructor)) //Add to the destructor list
|
||||
|
||||
Όταν αυτό χρησιμοποιείται, οι ενότητες **`.tdata`** και **`.tbss`** χρησιμοποιούνται στο ELF. Οι οποίες είναι όπως η `.data` (αρχικοποιημένη) και η `.bss` (μη αρχικοποιημένη) αλλά για TLS.
|
||||
|
||||
Κάθε μεταβλητή θα έχει μια εγγραφή στην κεφαλίδα TLS που θα καθορίζει το μέγεθος και την απόσταση TLS, η οποία είναι η απόσταση που θα χρησιμοποιήσει στην τοπική περιοχή δεδομένων του νήματος.
|
||||
Κάθε μεταβλητή θα έχει μια εγγραφή στην κεφαλίδα TLS που καθορίζει το μέγεθος και την απόσταση TLS, που είναι η απόσταση που θα χρησιμοποιήσει στην τοπική περιοχή δεδομένων του νήματος.
|
||||
|
||||
Ο `__TLS_MODULE_BASE` είναι ένα σύμβολο που χρησιμοποιείται για να αναφέρεται στη βασική διεύθυνση της αποθήκευσης τοπικών νημάτων και δείχνει στην περιοχή μνήμης που περιέχει όλα τα τοπικά δεδομένα νημάτων ενός module.
|
||||
Ο `__TLS_MODULE_BASE` είναι ένα σύμβολο που χρησιμοποιείται για να αναφέρεται στη βασική διεύθυνση της αποθήκευσης τοπικών νημάτων και δείχνει στην περιοχή μνήμης που περιέχει όλα τα τοπικά δεδομένα νήματος ενός module.
|
||||
|
||||
## Βοηθητικός Διανυσματικός (auxv) και vDSO
|
||||
|
||||
Ο πυρήνας του Linux περνά έναν βοηθητικό διανυσματικό σε διαδικασίες που περιέχει χρήσιμες διευθύνσεις και σημαίες για την εκτέλεση:
|
||||
|
||||
- `AT_RANDOM`: δείχνει σε 16 τυχαία bytes που χρησιμοποιούνται από την glibc για το stack canary και άλλους σπόρους PRNG.
|
||||
- `AT_SYSINFO_EHDR`: βασική διεύθυνση της χαρτογράφησης vDSO (χρήσιμο για να βρείτε syscalls και gadgets `__kernel_*`).
|
||||
- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, κ.λπ.
|
||||
|
||||
Ως επιτιθέμενος, αν μπορείτε να διαβάσετε μνήμη ή αρχεία κάτω από `/proc`, μπορείτε συχνά να διαρρεύσετε αυτά χωρίς διαρροή πληροφοριών στη διαδικασία στόχο:
|
||||
```bash
|
||||
# Show the auxv of a running process
|
||||
cat /proc/$(pidof target)/auxv | xxd
|
||||
|
||||
# From your own process (helper snippet)
|
||||
#include <sys/auxv.h>
|
||||
#include <stdio.h>
|
||||
int main(){
|
||||
printf("AT_RANDOM=%p\n", (void*)getauxval(AT_RANDOM));
|
||||
printf("AT_SYSINFO_EHDR=%p\n", (void*)getauxval(AT_SYSINFO_EHDR));
|
||||
}
|
||||
```
|
||||
Leaking `AT_RANDOM` σας δίνει την τιμή του canary αν μπορείτε να αποδεσμεύσετε αυτόν τον δείκτη; `AT_SYSINFO_EHDR` σας δίνει μια βάση vDSO για να εξορύξετε gadgets ή για να καλέσετε γρήγορες syscalls απευθείας.
|
||||
|
||||
## References
|
||||
|
||||
- ld.so(8) – Dynamic Loader search order, RPATH/RUNPATH, secure-execution rules (AT_SECURE): https://man7.org/linux/man-pages/man8/ld.so.8.html
|
||||
- getauxval(3) – Auxiliary vector and AT_* constants: https://man7.org/linux/man-pages/man3/getauxval.3.html
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user