
kfd, abreviação de kernel file descriptor, é um projeto para ler e escrever memória do kernel em dispositivos Apple.
Aviso rápido: não tenho a intenção de adicionar offsets para outros dispositivos e versões do iOS.
kfd, abreviação de kernel file descriptor, é um projeto para ler e escrever memória do kernel em dispositivos Apple. Ele aproveita diversas vulnerabilidades que podem ser exploradas para obter PTEs pendentes, que serão referidas como uma primitiva PUAF, abreviação de "physical use-after-free". Em seguida, ele realoca certos objetos do kernel dentro dessas páginas físicas e os manipula diretamente a partir do espaço de usuário por meio das PTEs pendentes, a fim de alcançar uma primitiva KRKW, abreviação de "kernel read/write". O código do exploit está totalmente contido em uma biblioteca, libkfd, mas o projeto também contém wrappers executáveis simples para iOS e macOS. A API pública do libkfd é bastante pequena e intuitiva:
enum puaf_method {
puaf_physpuppet,
puaf_smith,
puaf_landa,
};
enum kread_method {
kread_kqueue_workloop_ctl,
kread_sem_open,
};
enum kwrite_method {
kwrite_dup,
kwrite_sem_open,
};
u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method);
void kread(u64 kfd, u64 kaddr, void* uaddr, u64 size);
void kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size);
void kclose(u64 kfd);
kopen() conceitualmente abre um "descritor de arquivo do kernel". Ela recebe os seguintes 4
argumentos:
puaf_pages: O número alvo de páginas físicas com PTEs pendentes.puaf_method: O método usado para obter a primitiva PUAF, com as seguintes opções:
puaf_physpuppet:
puaf_smith:
puaf_landa:
kread_method: O método usado para obter a primitiva kread() inicial.kwrite_method: O método usado para obter a primitiva kwrite() inicial.Se o exploit for bem-sucedido, kopen() retorna um descritor de arquivo opaco de 64 bits. Na
prática, isso é apenas um ponteiro de espaço de usuário para uma estrutura necessária ao libkfd. No
entanto, como essa estrutura não deve ser acessada fora da biblioteca, ela é retornada como um
inteiro opaco. Se o exploit não for bem-sucedido, a biblioteca imprimirá uma mensagem de erro,
dormirá por 30 segundos e sairá com um código de status 1. Ela dorme por 30 segundos porque o kernel
pode entrar em pânico na saída para certos métodos PUAF que exigem uma limpeza pós-KRKW (por exemplo,
puaf_smith).
kread() e kwrite() são os equivalentes no espaço de usuário de copyout() e copyin(),
respectivamente. Observe que as opções para kread_method e kwrite_method são descritas em um
artigo técnico separado. Além disso, as primitivas iniciais concedidas
por esses métodos podem ser usadas para construir uma primitiva KRKW melhor. Por fim, kclose()
simplesmente fecha o descritor de arquivo do kernel. Todas elas recebem como primeiro argumento o
inteiro opaco retornado por kopen().
No Xcode, abra a pasta raiz do projeto e conecte seu dispositivo iOS.
Em um terminal, navegue até a pasta raiz do projeto.
Opcionalmente, para aumentar os limites global e por processo de descritores de arquivo, o que
melhorará a taxa de sucesso especialmente em execuções consecutivas, execute o comando make s e
digite a senha do sudo.
make b.make r.make br.Este README apresentou uma visão geral de alto nível do projeto kfd. Depois que uma primitiva PUAF é alcançada, o restante do exploit é genérico. Portanto, extraí a parte comum dos exploits para um artigo técnico dedicado:
Além disso, dividi a parte específica da vulnerabilidade dos exploits usados para alcançar a primitiva PUAF em artigos técnicos distintos, listados abaixo em ordem cronológica de descoberta:
No entanto, observe que esses write-ups foram escritos para um público que já está familiarizado com o sistema de memória virtual do XNU.