From 9bf5e7e63a230318af2d1e0190d5ccc9aef388e1 Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 29 Sep 2025 08:59:36 +0000 Subject: [PATCH] Translated ['', 'src/binary-exploitation/ios-exploiting/ios-physical-uaf --- .../ios-physical-uaf-iosurface.md | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md index 765cc3432..31bda8a8a 100644 --- a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md +++ b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md @@ -1,23 +1,23 @@ -# iOS Physical Use-After-Free via IOSurface +# iOS Physical Use After Free via IOSurface {{#include ../../banners/hacktricks-training.md}} ## Physical use-after-free -Este é um resumo do post em [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html); além disso, mais informações sobre exploit que usa esta técnica podem ser encontradas em [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) +Este é um resumo do post [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html); mais informações sobre exploits que usam esta técnica podem ser encontradas em [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) ### Gerenciamento de memória no XNU -O espaço de endereçamento de memória virtual para processos de usuário no iOS vai de **0x0 até 0x8000000000**. No entanto, esses endereços não mapeiam diretamente a memória física. Em vez disso, o **kernel** usa **tabelas de páginas** para traduzir endereços virtuais em endereços **físicos** reais. +O **espaço de endereçamento de memória virtual** para processos de usuário no iOS vai de **0x0 até 0x8000000000**. No entanto, esses endereços não mapeiam diretamente para memória física. Em vez disso, o **kernel** usa **page tables** para traduzir endereços virtuais em endereços **físicos** reais. -#### Níveis das tabelas de páginas no iOS +#### Níveis das page tables no iOS -As tabelas de páginas são organizadas hierarquicamente em três níveis: +As page tables são organizadas hierarquicamente em três níveis: 1. **L1 Page Table (Level 1)**: * Cada entrada aqui representa uma grande faixa de memória virtual. -* Ela cobre **0x1000000000 bytes** (ou **256 GB**) de memória virtual. +* Cobre **0x1000000000 bytes** (ou **256 GB**) de memória virtual. 2. **L2 Page Table (Level 2)**: * Uma entrada aqui representa uma região menor de memória virtual, especificamente **0x2000000 bytes** (32 MB). * Uma entrada L1 pode apontar para uma tabela L2 se não puder mapear toda a região por si só. @@ -25,21 +25,21 @@ As tabelas de páginas são organizadas hierarquicamente em três níveis: * Este é o nível mais fino, onde cada entrada mapeia uma única página de memória de **4 KB**. * Uma entrada L2 pode apontar para uma tabela L3 se for necessário controle mais granular. -#### Mapeamento de virtual para físico +#### Mapeamento de virtual para memória física -* **Mapeamento direto (Block Mapping)**: -* Algumas entradas em uma tabela de páginas mapeiam diretamente uma faixa de endereços virtuais para uma faixa contígua de endereços físicos (como um atalho). -* **Ponteiro para tabela de páginas filha**: -* Se for necessário controle mais fino, uma entrada em um nível (por exemplo, L1) pode apontar para uma **tabela de páginas filha** no próximo nível (por exemplo, L2). +* **Direct Mapping (Block Mapping)**: +* Algumas entradas em uma page table mapeiam diretamente uma faixa de endereços virtuais para uma faixa contígua de endereços físicos (como um atalho). +* **Pointer to Child Page Table**: +* Se for necessário controle mais fino, uma entrada em um nível (por exemplo, L1) pode apontar para uma **child page table** no próximo nível (por exemplo, L2). #### Exemplo: Mapeando um endereço virtual -Suponha que você tente acessar o endereço virtual **0x1000000000**: +Digamos que você tente acessar o endereço virtual **0x1000000000**: 1. **L1 Table**: -* O kernel verifica a entrada da tabela L1 correspondente a esse endereço virtual. Se ela tiver um **ponteiro para uma tabela L2**, ele irá para essa tabela L2. +* O kernel verifica a entrada correspondente na L1. Se ela contiver um **pointer to an L2 page table**, vai para essa L2. 2. **L2 Table**: -* O kernel verifica a tabela L2 para um mapeamento mais detalhado. Se essa entrada apontar para uma **tabela L3**, ele prossegue para lá. +* O kernel verifica a L2 para um mapeamento mais detalhado. Se essa entrada apontar para uma **L3 page table**, prossegue para lá. 3. **L3 Table**: * O kernel consulta a entrada final L3, que aponta para o **endereço físico** da página de memória real. @@ -47,8 +47,8 @@ Suponha que você tente acessar o endereço virtual **0x1000000000**: Se você escrever o endereço físico **0x800004000** no primeiro índice da tabela L2, então: -* Endereços virtuais de **0x1000000000** até **0x1002000000** mapeiam para endereços físicos de **0x800004000** até **0x802004000**. -* Isto é um **mapeamento de bloco** no nível L2. +* Endereços virtuais de **0x1000000000** a **0x1002000000** mapeiam para endereços físicos de **0x800004000** a **0x802004000**. +* Isso é um **block mapping** no nível L2. Alternativamente, se a entrada L2 apontar para uma tabela L3: @@ -58,40 +58,40 @@ Alternativamente, se a entrada L2 apontar para uma tabela L3: Um **physical use-after-free** (UAF) ocorre quando: -1. Um processo **aloca** alguma memória como **legível e gravável**. -2. As **tabelas de páginas** são atualizadas para mapear essa memória para um endereço físico específico que o processo pode acessar. +1. Um processo **aloca** alguma memória como **readable and writable**. +2. As **page tables** são atualizadas para mapear essa memória para um endereço físico específico que o processo pode acessar. 3. O processo **desaloca** (libera) a memória. -4. Porém, devido a um **bug**, o kernel **esquece de remover o mapeamento** das tabelas de páginas, mesmo marcando a memória física correspondente como livre. -5. O kernel pode então **realocar essa memória física "liberada"** para outros fins, como **dados do kernel**. +4. Porém, devido a um **bug**, o kernel **esquece de remover o mapeamento** das page tables, mesmo marcando a memória física correspondente como livre. +5. O kernel pode então **realocar essa memória física "liberada"** para outros fins, como **kernel data**. 6. Como o mapeamento não foi removido, o processo ainda pode **ler e escrever** nessa memória física. -Isso significa que o processo pode acessar **páginas da memória do kernel**, que podem conter dados sensíveis ou estruturas, potencialmente permitindo que um atacante **manipule a memória do kernel**. +Isso significa que o processo pode acessar **páginas de memória do kernel**, que podem conter dados sensíveis ou estruturas, potencialmente permitindo que um atacante **manipule memória do kernel**. ### IOSurface Heap Spray -Como o atacante não controla quais páginas específicas do kernel serão alocadas para a memória liberada, ele usa uma técnica chamada **heap spray**: +Como o atacante não controla quais páginas do kernel serão alocadas para a memória liberada, ele usa uma técnica chamada **heap spray**: 1. O atacante **cria um grande número de objetos IOSurface** na memória do kernel. -2. Cada objeto IOSurface contém um **valor mágico** em um de seus campos, tornando-o fácil de identificar. -3. Eles **escaneiam as páginas liberadas** para ver se algum desses objetos IOSurface caiu em uma página liberada. -4. Quando encontram um objeto IOSurface em uma página liberada, podem usá-lo para **ler e escrever** na memória do kernel. +2. Cada objeto IOSurface contém um **magic value** em um de seus campos, tornando-o fácil de identificar. +3. Eles **varrem as páginas liberadas** para ver se algum desses objetos IOSurface caiu em uma página liberada. +4. Quando encontram um objeto IOSurface em uma página liberada, podem usá-lo para **ler e escrever memória do kernel**. Mais informações sobre isso em [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) > [!TIP] -> Esteja ciente de que dispositivos iOS 16+ (A12+) trazem mitigações de hardware (como PPL ou SPTM) que tornam técnicas de physical UAF muito menos viáveis. -> PPL aplica proteções MMU estritas em páginas relacionadas a code signing, entitlements e dados sensíveis do kernel, então, mesmo que uma página seja reutilizada, escritas do userland ou de código kernel comprometido em páginas protegidas por PPL são bloqueadas. -> Secure Page Table Monitor (SPTM) estende o PPL endurecendo as próprias atualizações das tabelas de páginas. Ele garante que mesmo código privilegiado do kernel não possa remapear silenciosamente páginas liberadas ou adulterar mapeamentos sem passar por verificações seguras. -> KTRR (Kernel Text Read-Only Region) bloqueia a seção de código do kernel como somente leitura após o boot. Isso impede quaisquer modificações em tempo de execução ao código do kernel, fechando um grande vetor de ataque que exploits de physical UAF frequentemente exploram. -> Além disso, alocações `IOSurface` são menos previsíveis e mais difíceis de mapear em regiões acessíveis pelo usuário, o que torna o truque de “escaneamento por valor mágico” muito menos confiável. E `IOSurface` agora é protegido por entitlements e restrições de sandbox. +> Tenha em mente que dispositivos iOS 16+ (A12+) trazem mitigações de hardware (como PPL ou SPTM) que tornam técnicas de physical UAF muito menos viáveis. +> PPL aplica proteções MMU estritas em páginas relacionadas a code signing, entitlements e dados sensíveis do kernel; assim, mesmo que uma página seja reutilizada, escritas vindas do userland ou de código do kernel comprometido para páginas protegidas por PPL são bloqueadas. +> Secure Page Table Monitor (SPTM) estende o PPL ao endurecer as próprias atualizações de page tables. Ele garante que até mesmo código privilegiado do kernel não possa remapear silenciosamente páginas liberadas ou manipular mapeamentos sem passar por checagens seguras. +> KTRR (Kernel Text Read-Only Region) tranca a seção de código do kernel como read-only após o boot. Isso previne modificações em tempo de execução do código do kernel, fechando um vetor de ataque majoritário que exploits de physical UAF costumam explorar. +> Além disso, alocações de `IOSurface` são menos previsíveis e mais difíceis de mapear em regiões acessíveis por usuário, o que torna o truque de “magic value scanning” muito menos confiável. E `IOSurface` agora é protegido por entitlements e restrições de sandbox. ### Processo passo a passo do Heap Spray -1. **Spray IOSurface Objects**: O atacante cria muitos objetos IOSurface com um identificador especial ("valor mágico"). +1. **Spray IOSurface Objects**: O atacante cria muitos objetos IOSurface com um identificador especial ("magic value"). 2. **Scan Freed Pages**: Eles verificam se algum dos objetos foi alocado em uma página liberada. -3. **Read/Write Kernel Memory**: Manipulando campos no objeto IOSurface, obtêm a capacidade de realizar **reads e writes arbitrários** na memória do kernel. Isso permite: +3. **Read/Write Kernel Memory**: Ao manipular campos no objeto IOSurface, obtêm a capacidade de realizar **arbitrary reads and writes** na memória do kernel. Isso permite: * Usar um campo para **ler qualquer valor 32-bit** na memória do kernel. -* Usar outro campo para **escrever valores 64-bit**, alcançando uma primitiva estável de **kernel read/write**. +* Usar outro campo para **escrever valores 64-bit**, alcançando um primitivo estável de **kernel read/write**. Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for: ```c @@ -148,25 +148,25 @@ free(surfaceIDs); return 0; } ``` -### Alcançando leitura/escrita no kernel com IOSurface +### Alcançando Leitura/Escrita no Kernel com IOSurface -Após obter controle sobre um objeto IOSurface na memória do kernel (mapeado para uma página física liberada acessível a partir do userspace), podemos usá-lo para **operações arbitrárias de leitura e escrita no kernel**. +Depois de obter controle sobre um objeto IOSurface na memória do kernel (mapeado para uma página física liberada acessível a partir do userspace), podemos usá-lo para operações arbitrárias de leitura e escrita no kernel. **Key Fields in IOSurface** -O objeto IOSurface tem dois campos cruciais: +O objeto IOSurface possui dois campos cruciais: -1. **Use Count Pointer**: Permite uma **leitura de 32 bits**. -2. **Indexed Timestamp Pointer**: Permite uma **escrita de 64 bits**. +1. **Use Count Pointer**: Permite uma leitura de **32 bits**. +2. **Indexed Timestamp Pointer**: Permite uma escrita de **64 bits**. -Ao sobrescrever esses ponteiros, fazemos com que apontem para endereços arbitrários na memória do kernel, permitindo operações de leitura e escrita. +Ao sobrescrever esses ponteiros, os redirecionamos para endereços arbitrários na memória do kernel, habilitando operações de leitura/escrita. -#### Leitura de 32 bits no kernel +#### Leitura de kernel de 32 bits Para realizar uma leitura: 1. Sobrescreva o **use count pointer** para apontar para o endereço alvo menos um deslocamento de 0x14 bytes. -2. Use o método `get_use_count` para ler o valor nesse endereço. +2. Use o método `get_use_count` para ler o valor naquele endereço. ```c uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) { uint64_t args[1] = {surfaceID}; @@ -184,11 +184,11 @@ iosurface_set_use_count_pointer(info.object, orig); return value; } ``` -#### 64-Bit Kernel Write +#### Escrita no kernel de 64 bits Para realizar uma escrita: -1. Sobrescreva o **indexed timestamp pointer** com o endereço de destino. +1. Sobrescreva o **indexed timestamp pointer** com o endereço alvo. 2. Use o método `set_indexed_timestamp` para escrever um valor de 64 bits. ```c void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) { @@ -203,13 +203,13 @@ set_indexed_timestamp(info.client, info.surface, value); iosurface_set_indexed_timestamp_pointer(info.object, orig); } ``` -#### Exploit Flow Recap +#### Recapitulação do Fluxo do Exploit -1. **Trigger Physical Use-After-Free**: páginas liberadas estão disponíveis para reutilização. -2. **Spray IOSurface Objects**: aloque muitos objetos IOSurface com um único "magic value" na kernel memory. -3. **Identify Accessible IOSurface**: localize um IOSurface em uma página liberada que você controla. -4. **Abuse Use-After-Free**: modifique ponteiros no objeto IOSurface para habilitar **kernel read/write** arbitrário via métodos IOSurface. +1. **Trigger Physical Use-After-Free**: Páginas liberadas ficam disponíveis para reutilização. +2. **Spray IOSurface Objects**: Alocar muitos objetos IOSurface com um "magic value" único na memória do kernel. +3. **Identify Accessible IOSurface**: Localizar um IOSurface em uma página liberada que você controla. +4. **Abuse Use-After-Free**: Modificar ponteiros no objeto IOSurface para permitir **kernel read/write** arbitrários via métodos do IOSurface. -Com essas primitivas, o exploit fornece **32-bit reads** controladas e **64-bit writes** para kernel memory. Passos adicionais do jailbreak podem envolver primitivas de read/write mais estáveis, que podem requerer contornar proteções adicionais (por exemplo, PPL em dispositivos arm64e mais novos). +Com essas primitivas, o exploit fornece **32-bit reads** controladas e **64-bit writes** para a memória do kernel. Passos adicionais do jailbreak podem envolver primitivos de leitura/escrita mais estáveis, os quais podem requerer contornar proteções adicionais (por exemplo, PPL em dispositivos arm64e mais novos). {{#include ../../banners/hacktricks-training.md}}