12 KiB
Injeção de Thread no macOS via Porta de Tarefa
Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
- Se você quer ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF, confira os PLANOS DE ASSINATURA!
- Adquira o material oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção de NFTs exclusivos
- Junte-se ao grupo 💬 Discord ou ao grupo do telegram ou siga-me no Twitter 🐦 @carlospolopm.
- Compartilhe suas técnicas de hacking enviando PRs para os repositórios do GitHub HackTricks e HackTricks Cloud.
Código
- https://github.com/bazad/threadexec
- https://gist.github.com/knightsc/bd6dfeccb02b77eb6409db5601dcef36
1. Sequestro de Thread
Inicialmente, a função task_threads()
é invocada na porta de tarefa para obter uma lista de threads da tarefa remota. Uma thread é selecionada para o sequestro. Esta abordagem diverge dos métodos convencionais de injeção de código, pois a criação de uma nova thread remota é proibida devido à nova mitigação que bloqueia thread_create_running()
.
Para controlar a thread, thread_suspend()
é chamado, interrompendo sua execução.
As únicas operações permitidas na thread remota envolvem parar e iniciar a mesma, recuperar e modificar seus valores de registradores. Chamadas de função remotas são iniciadas configurando os registradores x0
a x7
para os argumentos, ajustando pc
para a função desejada e ativando a thread. Garantir que a thread não trave após o retorno requer detecção do retorno.
Uma estratégia envolve registrar um manipulador de exceções para a thread remota usando thread_set_exception_ports()
, definindo o registrador lr
para um endereço inválido antes da chamada da função. Isso desencadeia uma exceção após a execução da função, enviando uma mensagem para a porta de exceção, permitindo a inspeção do estado da thread para recuperar o valor de retorno. Alternativamente, como adotado do exploit triple_fetch de Ian Beer, lr
é configurado para entrar em loop infinito. Os registradores da thread são então monitorados continuamente até que pc
aponte para essa instrução.
2. Portas Mach para comunicação
A fase subsequente envolve o estabelecimento de portas Mach para facilitar a comunicação com a thread remota. Essas portas são fundamentais na transferência de direitos de envio e recebimento arbitrários entre tarefas.
Para comunicação bidirecional, dois direitos de recebimento Mach são criados: um na tarefa local e outro na tarefa remota. Em seguida, um direito de envio para cada porta é transferido para a tarefa correspondente, possibilitando a troca de mensagens.
Focando na porta local, o direito de recebimento é mantido pela tarefa local. A porta é criada com mach_port_allocate()
. O desafio está em transferir um direito de envio para esta porta para a tarefa remota.
Uma estratégia envolve o uso de thread_set_special_port()
para colocar um direito de envio para a porta local no THREAD_KERNEL_PORT
da thread remota. Então, a thread remota é instruída a chamar mach_thread_self()
para recuperar o direito de envio.
Para a porta remota, o processo é essencialmente invertido. A thread remota é direcionada a gerar uma porta Mach através de mach_reply_port()
(já que mach_port_allocate()
é inadequado devido ao seu mecanismo de retorno). Após a criação da porta, mach_port_insert_right()
é invocado na thread remota para estabelecer um direito de envio. Esse direito é então armazenado no kernel usando thread_set_special_port()
. De volta à tarefa local, thread_get_special_port()
é usado na thread remota para adquirir um direito de envio para a nova porta Mach alocada na tarefa remota.
A conclusão dessas etapas resulta no estabelecimento de portas Mach, preparando o terreno para comunicação bidirecional.
3. Primitivas Básicas de Leitura/Escrita de Memória
Nesta seção, o foco é utilizar a primitiva de execução para estabelecer primitivas básicas de leitura e escrita de memória. Esses passos iniciais são cruciais para obter mais controle sobre o processo remoto, embora as primitivas neste estágio não sirvam para muitos propósitos. Em breve, elas serão atualizadas para versões mais avançadas.
Leitura e Escrita de Memória Usando Primitiva de Execução
O objetivo é realizar leitura e escrita de memória usando funções específicas. Para ler memória, funções com a seguinte estrutura são utilizadas:
uint64_t read_func(uint64_t *address) {
return *address;
}
E para escrever na memória, funções semelhantes a esta estrutura são usadas:
void write_func(uint64_t *address, uint64_t value) {
*address = value;
}
Estas funções correspondem às instruções de montagem dadas:
_read_func:
ldr x0, [x0]
ret
_write_func:
str x1, [x0]
ret
Identificando Funções Adequadas
Uma varredura de bibliotecas comuns revelou candidatos apropriados para essas operações:
- Leitura de Memória:
A função
property_getName()
da biblioteca runtime do Objective-C é identificada como uma função adequada para leitura de memória. A função está descrita abaixo:
const char *property_getName(objc_property_t prop) {
return prop->name;
}
Essa função efetivamente age como a read_func
ao retornar o primeiro campo de objc_property_t
.
- Escrita de Memória:
Encontrar uma função pré-construída para escrita de memória é mais desafiador. No entanto, a função
_xpc_int64_set_value()
da libxpc é uma candidata adequada com a seguinte desmontagem:
__xpc_int64_set_value:
str x1, [x0, #0x18]
ret
Para realizar uma escrita de 64 bits em um endereço específico, a chamada remota é estruturada como:
_xpc_int64_set_value(address - 0x18, value)
Com essas primitivas estabelecidas, o cenário está preparado para a criação de memória compartilhada, marcando um progresso significativo no controle do processo remoto.
4. Configuração de Memória Compartilhada
O objetivo é estabelecer memória compartilhada entre tarefas locais e remotas, simplificando a transferência de dados e facilitando a chamada de funções com múltiplos argumentos. A abordagem envolve o uso de libxpc
e seu tipo de objeto OS_xpc_shmem
, que é construído sobre entradas de memória Mach.
Visão Geral do Processo:
- Alocação de Memória:
- Alocar a memória para compartilhamento usando
mach_vm_allocate()
. - Usar
xpc_shmem_create()
para criar um objetoOS_xpc_shmem
para a região de memória alocada. Esta função gerenciará a criação da entrada de memória Mach e armazenará o direito de envio Mach no deslocamento0x18
do objetoOS_xpc_shmem
.
- Criando Memória Compartilhada no Processo Remoto:
- Alocar memória para o objeto
OS_xpc_shmem
no processo remoto com uma chamada remota paramalloc()
. - Copiar o conteúdo do objeto
OS_xpc_shmem
local para o processo remoto. No entanto, esta cópia inicial terá nomes de entrada de memória Mach incorretos no deslocamento0x18
.
- Corrigindo a Entrada de Memória Mach:
- Utilizar o método
thread_set_special_port()
para inserir um direito de envio para a entrada de memória Mach na tarefa remota. - Corrigir o campo de entrada de memória Mach no deslocamento
0x18
sobrescrevendo-o com o nome da entrada de memória remota.
- Finalizando a Configuração de Memória Compartilhada:
- Validar o objeto
OS_xpc_shmem
remoto. - Estabelecer o mapeamento de memória compartilhada com uma chamada remota para
xpc_shmem_remote()
.
Seguindo esses passos, a memória compartilhada entre as tarefas locais e remotas será configurada de forma eficiente, permitindo transferências de dados diretas e a execução de funções que requerem múltiplos argumentos.
Trechos de Código Adicionais
Para alocação de memória e criação de objeto de memória compartilhada:
mach_vm_allocate();
xpc_shmem_create();
Para criar e corrigir o objeto de memória compartilhada no processo remoto:
malloc(); // for allocating memory remotely
thread_set_special_port(); // for inserting send right
Lembre-se de lidar corretamente com os detalhes dos Mach ports e nomes de entrada de memória para garantir que a configuração de memória compartilhada funcione adequadamente.
5. Alcançando Controle Total
Após estabelecer com sucesso a memória compartilhada e obter capacidades de execução arbitrária, essencialmente ganhamos controle total sobre o processo alvo. As funcionalidades-chave que possibilitam esse controle são:
- Operações de Memória Arbitrárias:
- Realize leituras de memória arbitrárias invocando
memcpy()
para copiar dados da região compartilhada. - Execute escritas de memória arbitrárias usando
memcpy()
para transferir dados para a região compartilhada.
- Manipulação de Chamadas de Função com Múltiplos Argumentos:
- Para funções que requerem mais de 8 argumentos, organize os argumentos adicionais na pilha em conformidade com a convenção de chamadas.
- Transferência de Mach Port:
- Transfira Mach ports entre tarefas através de mensagens Mach via ports previamente estabelecidos.
- Transferência de Descritor de Arquivo:
- Transfira descritores de arquivo entre processos usando fileports, uma técnica destacada por Ian Beer em
triple_fetch
.
Esse controle abrangente está encapsulado na biblioteca threadexec, fornecendo uma implementação detalhada e uma API amigável para interação com o processo vítima.
Considerações Importantes:
- Garanta o uso adequado de
memcpy()
para operações de leitura/escrita de memória para manter a estabilidade do sistema e a integridade dos dados. - Ao transferir Mach ports ou descritores de arquivo, siga os protocolos adequados e gerencie os recursos de forma responsável para evitar vazamentos ou acessos não intencionais.
Seguindo essas diretrizes e utilizando a biblioteca threadexec
, é possível gerenciar e interagir com processos em um nível granular de forma eficiente, alcançando controle total sobre o processo alvo.
Referências
Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
- Se você quer ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF, confira os PLANOS DE ASSINATURA!
- Adquira o material oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção de NFTs exclusivos
- Junte-se ao grupo 💬 Discord ou ao grupo telegram ou siga-me no Twitter 🐦 @carlospolopm.
- Compartilhe suas técnicas de hacking enviando PRs para os repositórios github HackTricks e HackTricks Cloud.