
Um rootkit Linux eBPF com backdoor, C2, injeção de bibliotecas, sequestro de execução, persistência e capacidades de ocultação.
TripleCross é um rootkit Linux eBPF que demonstra as capacidades ofensivas da tecnologia eBPF.
TripleCross é inspirado em designs anteriores de implantes nesta área, notavelmente os trabalhos de Jeff Dileo na DEFCON 271, Pat Hogan na DEFCON 292, Guillaume Fournier e Sylvain Afchain também na DEFCON 293, e o Boopkit de Kris Nóva4. Reutilizamos e estendemos algumas das técnicas pioneiras dessas explorações anteriores das capacidades ofensivas da tecnologia eBPF.
Este rootkit foi criado para minha Tese de Bacharelado na UC3M. Mais detalhes sobre seu design são fornecidos no documento da tese.
Este rootkit é puramente para fins educacionais e acadêmicos. O software é fornecido "como está" e os autores não são responsáveis por qualquer dano ou incidente que possa ocorrer durante seu uso.
Não tente usar o TripleCross para violar a lei. O uso inadequado do software e das informações fornecidas pode resultar em acusações criminais.
A figura a seguir mostra a arquitetura do TripleCross e seus módulos.
A biblioteca de sockets brutos RawTCP_Lib usada para transmissões do rootkit é de minha autoria e possui seu próprio repositório.
A tabela a seguir descreve os principais arquivos e diretórios do código-fonte para facilitar sua navegação:
Este projeto de pesquisa foi testado nos seguintes ambientes:
| DISTRIBUIÇÃO | KERNEL | GCC | CLANG | GLIBC | |
|---|---|---|---|---|---|
| VERSÃO | Ubuntu 21.04 | 5.11.0 | 10.3.0 | 12.0.0 | 2.33 |
Recomendamos usar Ubuntu 21.04, que por padrão incorporará as versões de software mostradas aqui. Caso contrário, alguns dos problemas que você pode encontrar estão descritos aqui.
O código-fonte do rootkit é compilado usando dois Makefiles.```
cd src make all
cd client make
The following table describes the purpose of each Makefile in detail:
| MAKEFILE | COMMAND | DESCRIPTION | RESULTING FILES |
| ------------- | ------------- | ------------- | ------------- |
| src/client/Makefile | make | Compilation of the rootkit client | src/client/injector |
| src/Makefile | make help | Compilation of programs for testing rootkit capabilities, and the malicious program and library of the execution hijacking and library injection modules, respectively | src/helpers/simple_timer, src/helpers/simple_open, src/helpers/simple_execve, src/helpers/lib_injection.so, src/helpers/execve_hijack |
| src/Makefile | make kit | Compilation of the rootkit using the libbpf library | src/bin/kit |
| src/Makefile | make tckit | Compilation of the rootkit TC egress program | src/bin/tc.o |
### Instalação
Uma vez que os arquivos do rootkit são gerados em src/bin/, os programas *tc.o* e *kit* devem ser carregados em ordem. No exemplo a seguir, o backdoor do rootkit operará na interface de rede *enp0s3*:```
// TC egress program
sudo tc qdisc add dev enp0s3 clsact
sudo tc filter add dev enp0s3 egress bpf direct-action obj bin/tc.o sec classifier/egress
// Libbpf-powered rootkit
sudo ./bin/kit -t enp0s3
Existem dois scripts, packager.sh e deployer.sh, que compilam e instalam o rootkit automaticamente, exatamente como um atacante faria em um cenário de ataque real.
Executar o packager.sh irá gerar todos os arquivos do rootkit no diretório apps/.
Executar o deployer.sh irá instalar o rootkit e criar os arquivos de persistência.
Esses scripts devem primeiro ser configurados com os seguintes parâmetros para o funcionamento adequado do módulo de persistência:
| SCRIPT | CONSTANT | DESCRIPTION |
|---|---|---|
| src/helpers/deployer.sh | CRON_PERSIST | Tarefa do cron para executar após a reinicialização |
| src/helpers/deployer.sh | SUDO_PERSIST | Entrada sudo para conceder privilégios sem senha |
O rootkit pode sequestrar a execução de processos que chamam as chamadas de sistema sys_timerfd_settime ou sys_openat. Isso é alcançado sobrescrevendo a seção da Global Offset Table (GOT) na memória virtual do processo que faz a chamada. Isso leva à execução de uma biblioteca maliciosa (src/helpers/injection_lib.c). A biblioteca irá gerar uma shell reversa para a máquina do atacante e, em seguida, retorna o fluxo de execução para a função original sem travar o processo.
TripleCross está preparado para contornar técnicas comuns de endurecimento de ELF, incluindo:
Também está preparado para funcionar com código compatível com Intel CET.
A funcionalidade do módulo pode ser verificada usando dois programas de teste src/helpers/simple_timer.c e src/helpers/simple_open.c. Alternativamente, você pode tentar sequestrar qualquer processo do sistema (testado e funcionando com systemd).
A configuração do módulo é definida através das seguintes constantes:
O recebimento de uma shell reversa da máquina do atacante pode ser feito com o netcat:``` nc -nlvp <ATTACKER_PORT>
### Injeção de bibliotecas via técnica de sequestro de GOT
A técnica incorporada no TripleCross consiste em 5 estágios:
#### Localizando a GOT e o endereço de retorno
O rootkit sequestra a chamada de sistema usando um programa tracepoint. A partir daí, ele localiza o endereço na secção GOT que o stub PLT usou para fazer a chamada à função glibc responsável pela syscall.
Para alcançar a secção GOT, o programa eBPF usa o endereço de retorno armazenado na pilha. Observe que:
* O .text faz uma *chamada* para o .plt, então *rip* é salvo como *ret* na pilha.
* O .plt faz um *salto* para a glibc usando .got, então nenhum outro *rip* é salvo. Também não modifica ou salva o valor de *rbp*.
* A glibc faz uma *syscall*, que não salva *rip* na pilha, mas sim o salva em *rcx*.
<img src="https://assets.kitploit.com/production/public/readmes/5614/d216fa5b7b656bb52587027db28f3e3902fa8389d0b2944a1f7e870d6d2e6bee.jpg" float="left">
Portanto, para verificar a partir do eBPF se um endereço na pilha é o endereço de retorno que nos levará à GOT correta, devemos verificar se é o endereço de retorno do stub PLT que usa o endereço GOT que salta para a função glibc que faz a chamada de sistema que sequestramos no eBPF.
Duas técnicas para encontrar o endereço de retorno foram incorporadas:
* Com sys_timerfd_settime, o programa eBPF percorre a pilha para a frente usando os argumentos da syscall.
* Com sys_openat, o programa eBPF percorre a pilha usando os dados da estrutura *pt_regs* dos tracepoints para encontrar o endereço de retorno.
<img src="https://assets.kitploit.com/production/public/readmes/5614/61217fb3fd84bec65cbbee906dd27860e5e1c211912cfe450ea4cf9051fa480b.png" float="left">
#### Localizando funções-chave para o shellcode
O shellcode deve ser gerado dinamicamente para contornar ASLR e PIE, que alteram o endereço de funções como dlopen() a cada execução do programa.
<img src="https://assets.kitploit.com/production/public/readmes/5614/6cbb620495d8cb9711e499fd5b1ae9ea845c03d0c33019cf008b456a95d5ddd6.png" float="left">
#### Injetando shellcode em um code cave
Um code cave pode ser encontrado através de engenharia reversa de um ELF se ASLR e PIE estiverem desativados, mas geralmente esse não é o caso. O programa eBPF envia uma requisição a um programa rootkit em espaço de usuário que usa o sistema de arquivos /proc para localizar e escrever em um code cave na secção .text (executável).
<img src="https://assets.kitploit.com/production/public/readmes/5614/c7daea0eed684437b5c7d971d0f69f5aac9138861d44da36c5368be9f97666d1.png" float="left">
#### Sobrescrevendo a secção GOT
Dependendo se RELRO Parcial ou Completo está ativo no executável, o programa eBPF sobrescreve a secção GOT diretamente ou através do sistema de arquivos /proc.
<img src="https://assets.kitploit.com/production/public/readmes/5614/7e69ec2982ee8c77c39b42f364ab25e52c40d96890f7413b3afe04dde1b825c3.png" float="left">
#### Aguardando a próxima chamada de sistema
Quando a próxima syscall é emitida no programa sequestrado, a secção PLT usa a secção GOT modificada, sequestrando o fluxo de execução que é redirecionado para o shellcode no code cave. O shellcode está preparado para evitar que o programa falhe, e chama a biblioteca maliciosa (*src/helpers/lib_injection.so*). Esta biblioteca executa um fork() e inicia um shell reverso com a máquina atacante. Após isso, o fluxo de execução é restaurado.
<img src="https://assets.kitploit.com/production/public/readmes/5614/4e780cbcba855fe11a55f6a34709d83d855a4235960b15b69470233147f04318.png" float="left">
## Backdoor e C2
O backdoor funciona imediatamente sem necessidade de configuração. O backdoor pode ser controlado remotamente usando o programa cliente do rootkit:
| ARGUMENTOS DO CLIENTE | DESCRIÇÃO DA AÇÃO |
| ------------- | ------------- |
| ./injector -c \<IP da Vítima\> | Inicia um pseudo-shell em texto plano usando o módulo de sequestro de execução |
| ./injector -e \<IP da Vítima\> | Inicia um pseudo-shell criptografado comandando o backdoor com um gatilho baseado em padrão |
| ./injector -s \<IP da Vítima\> | Inicia um pseudo-shell criptografado comandando o backdoor com um gatilho multi-pacote (de ambos os tipos) |
| ./injector -p \<IP da Vítima\> | Inicia um phantom shell comandando o backdoor com um gatilho baseado em padrão |
| ./injector -a \<IP da Vítima\> | Ordena o rootkit a ativar todos os programas eBPF |
| ./injector -u \<IP da Vítima\> | Ordena o rootkit a desanexar todos os seus programas eBPF |
| ./injector -S \<IP da Vítima\> | Demonstra como o backdoor pode ocultar uma mensagem do kernel (PoC Simples) |
| ./injector -h | Exibe ajuda |
### Gatilhos do backdoor
As ações são enviadas ao backdoor usando gatilhos de backdoor, que indicam ao backdoor a ação a ser executada dependendo do valor do atributo **K3**:
| VALOR DE K3 | AÇÃO |
| ------------- | ------------- |
| 0x1F29 | Solicitação para iniciar uma conexão de pseudo-shell criptografado |
| 0x4E14 | Solicitação para iniciar uma conexão de phantom shell |
| 0x1D25 | Solicitação para carregar e anexar todos os programas eBPF do rootkit |
| 0x1D24 | Solicitação para desanexar todos os programas eBPF do rootkit (exceto o do backdoor) |
#### Gatilho baseado em padrão
Este gatilho oculta o comando e as informações do cliente para que possa ser reconhecido pelo backdoor, mas ao mesmo tempo parece suficientemente aleatório para um supervisor de rede externo. É baseado no gatilho usado pelo rootkit da NSA recentemente descoberto [Bvp47](https://www.pangulab.cn/files/The_Bvp47_a_top-tier_backdoor_of_us_nsa_equation_group.en.pdf).
<img src="https://assets.kitploit.com/production/public/readmes/5614/58cec7ee2dbd89b6c7d71d60c006a1a98d7b9165b20bdbe006467a82d5dc30ab.png" float="left">
#### Gatilho multi-pacote
Este gatilho consiste em múltiplos pacotes TCP nos quais o payload do backdoor está oculto nos cabeçalhos dos pacotes. Este design é baseado no implante [Hive](https://wikileaks.org/vault7/document/hive-DevelopersGuide/hive-DevelopersGuide.pdf) da CIA descrito no vazamento Vault 7. O seguinte payload é usado:
<img src="https://assets.kitploit.com/production/public/readmes/5614/45a8348c3d366af4941d9cca845c281fc8c5a565353fc8fe3fb91350f39dd5f8.png" float="left">
Um XOR rotativo é então calculado sobre o payload acima e ele é dividido em várias partes, dependendo do modo selecionado pelo cliente rootkit. O TripleCross suporta payloads ocultos no número de sequência TCP:
<img src="https://assets.kitploit.com/production/public/readmes/5614/2b9d7fd46f7133e3eeda694e0b4791fbed2a51616b7d2f14e989a9e0e56af9e2.png" float="left">
E na porta de origem TCP:
<img src="https://assets.kitploit.com/production/public/readmes/5614/1a6ea6da628a9902eaf55cc3c1549a2ecf26cba211275acdce6bc5491b34140c.png" float="left">
### Pseudo-shells do backdoor
O cliente pode estabelecer pseudo-shells do rootkit, uma conexão especial rootkit-para-rootkit que simula um programa shell, permitindo que o atacante execute comandos Linux remotamente e obtenha os resultados como se os estivesse executando diretamente na máquina infectada. Múltiplos pseudo-shells são incorporados no nosso rootkit:
#### Pseudo-shell em texto plano
Este shell é gerado após uma execução bem-sucedida do módulo de sequestro de execução, que executará um arquivo malicioso que estabelece uma conexão com o cliente rootkit da seguinte forma:
<img src="https://assets.kitploit.com/production/public/readmes/5614/6495b5b62c33ae136b8c965658d9c5f501e609029bde7fcefe7266966f8effbb.png" float="left">
<img src="https://assets.kitploit.com/production/public/readmes/5614/5301e208d9853760eabdc14772c57a3639f28d71d050ee82d151bff93a76cedf.png" float="right">
#### Pseudo-shell criptografado
Um pseudo-shell criptografado pode ser solicitado pelo cliente rootkit a qualquer momento, consistindo em uma conexão TLS entre o rootkit e o cliente rootkit. Dentro da conexão criptografada, um protocolo de transmissão é seguido para comunicar comandos e informações, semelhante ao dos pseudo-shells em texto plano.
Iniciar um pseudo-shell criptografado requer que o backdoor escute por gatilhos, que aceita tanto gatilhos baseados em padrão quanto ambos os tipos de gatilho multi-pacote:
<img src="https://assets.kitploit.com/production/public/readmes/5614/d4929247af8895f78522f28c4ac8087e74d76b91320c67e0b37ea841cd8869d0.png" float="left">
<img src="https://assets.kitploit.com/production/public/readmes/5614/6e2a72d04028212a4917397b75b052a4bdf3c0529fb6c5e336b7fc0a06571728.png" float="right">
#### Phantom shell
Um phantom shell usa uma combinação de programas XDP e TC para superar as limitações do eBPF na rede, especificamente que ele não pode gerar novos pacotes. Para isso, o backdoor modifica o tráfego existente, sobrescrevendo o payload com os dados da transmissão C2. Os pacotes originais não são perdidos, pois retransmissões TCP enviam o pacote original (sem modificações) novamente após um curto período.
O seguinte protocolo ilustra o tráfego durante a execução de um comando usando um phantom shell:
<img src="https://assets.kitploit.com/production/public/readmes/5614/0aafe6b672757e4e9d37402c72ce14893a8a7f198030b2f2386df631c345d16b.png" float="left">
Um phantom shell é solicitado pelo cliente rootkit que emite um comando a ser executado pelo backdoor:
<img src="https://assets.kitploit.com/production/public/readmes/5614/e07dec48ff6a22e708b6d4b0d762473cc6483f065011cd6cdccdac49f12f916b.png" float="left">
Após a máquina infectada enviar qualquer pacote TCP, o backdoor o sobrescreve e o cliente mostra a resposta:
<img src="https://assets.kitploit.com/production/public/readmes/5614/19bea585b78a0bb1d52aa7c63ff05a0111551a0cc767732775491641e1dec021.png" float="left">
## Módulo de sequestro de execução
Em princípio, um programa eBPF não pode iniciar a execução de um programa por si só. Este módulo mostra como um rootkit malicioso pode tirar proveito de programas benignos para executar código malicioso no espaço de usuário. Este módulo alcança dois objetivos:
* Executar um programa de usuário malicioso aproveitando a execução de outro programa.
* Ser transparente para o espaço de usuário, isto é, se sequestrarmos a execução de um programa para que outro seja executado, o programa original também deve ser executado com o menor atraso possível.
Este módulo funciona sequestrando a syscall sys_execve(), modificando seus argumentos para que um programa malicioso (*src/helpers/execve_hijack.c*) seja executado em seu lugar. Esta modificação é feita de tal forma que o programa malicioso pode então executar o programa original com os argumentos originais para evitar levantar suspeitas no espaço de usuário. O diagrama a seguir resume a funcionalidade geral:
<img src="https://assets.kitploit.com/production/public/readmes/5614/601610696506e303f91a7957ec2a3d61f73f7d0e036430a9f67bd80a6f19b2d3.png" float="left">
Os argumentos da chamada sys_execve() original são modificados de tal forma que os argumentos originais não são perdidos (usando argv[0]) para que o programa original possa ser executado após o malicioso:
<img src="https://assets.kitploit.com/production/public/readmes/5614/e483317a3bdac422cdfc49ca92acdcefe624ddceb5b2ed036ccec141c8d1e5e6.png" float="left">
Incorporamos um programa de teste de exemplo (*src/helpers/simple_execve.c*) para testar o módulo de sequestro de execução. O módulo também pode sequestrar qualquer chamada no sistema, dependendo da configuração:
| NOME DO ARQUIVO | CONSTANTE | DESCRIÇÃO |
| ------------- | ------------- | ------------- |
| src/common/constants.h | PATH_EXECUTION_HIJACK_PROGRAM | Localização do programa malicioso a ser executado ao conseguir sequestrar uma chamada sys_execve |
| src/common/constants.h | EXEC_HIJACK_ACTIVE | Desativar (0) ou ativar (1) o módulo de sequestro de execução |
| src/common/constants.h | TASK_COMM_RESTRICT_HIJACK_ACTIVE | Sequestrar qualquer chamada sys_execve (0) ou apenas aquelas indicadas em TASK_COMM_NAME_RESTRICT_HIJACK (1) |
| src/common/constants.h | TASK_COMM_NAME_RESTRICT_HIJACK | Nome do programa do qual sequestrar chamadas sys_execve |
Após um sequestro bem-sucedido, o módulo irá parar a si mesmo. O programa malicioso *execve_hijack* ouvirá por solicitações de um pseudo-shell em texto plano do cliente rootkit.
## Persistência do rootkit
Após a máquina infectada ser reinicializada, todos os programas eBPF serão descarregados do kernel e o programa rootkit em espaço de usuário será encerrado. Além disso, mesmo que o rootkit pudesse ser executado novamente automaticamente, ele não teria mais os privilégios de root necessários para anexar os programas eBPF novamente. O módulo de persistência do rootkit visa enfrentar esses dois desafios:
* Executar o rootkit automaticamente e sem interação do usuário após um evento de reinicialização da máquina.
* Uma vez que o rootkit adquiriu privilégios de root na primeira vez que foi executado na máquina, ele deve mantê-los mesmo após uma reinicialização.
O TripleCross usa dois arquivos secretos, criados em *cron.d* e *sudoers.d*, para implementar essa funcionalidade. Essas entradas garantem que o rootkit seja carregado automaticamente e com privilégios totais após uma reinicialização. Esses arquivos são criados e gerenciados pelo script *deployer.sh*:
<img src="https://assets.kitploit.com/production/public/readmes/5614/88500b779b9ad5ba771803900a8abfffd08f3a6be59518e690534779a4134cf8.png" float="left">
<img src="https://assets.kitploit.com/production/public/readmes/5614/5ae61ed98af6d7c8aa9448fed3de553712ffb5c63e95d98a6f4300ff407bce23.png" float="right">
O script contém duas constantes que devem ser configuradas para o usuário infectar no sistema alvo:
| SCRIPT | CONSTANTE | DESCRIÇÃO |
| ------------- | ------------- | ------------- |
| src/helpers/deployer.sh | CRON_PERSIST | Job do cron para executar após a reinicialização |
| src/helpers/deployer.sh | SUDO_PERSIST | Entrada do sudo para conceder privilégios sem senha |
## Sigilo do rootkit
O módulo de persistência é baseado na criação de arquivos adicionais, mas eles podem eventualmente ser encontrados pelo proprietário do sistema ou por alguma ferramenta de software, então existe um risco em deixá-los no sistema. Além disso, os arquivos do rootkit precisarão ser armazenados em algum local, onde podem ser descobertos.
Considerando o exposto, o módulo de sigilo fornece a seguinte funcionalidade:
* Ocultar completamente um diretório do usuário (para que possamos ocultar todos os arquivos do rootkit dentro).
* Ocultar arquivos específicos em um diretório (precisamos ocultar os arquivos de persistência, mas não podemos ocultar completamente os diretórios *sudoers.d* ou *cron.d*, pois pertencem ao funcionamento normal do sistema).
Os arquivos e diretórios ocultados pelo rootkit podem ser personalizados pelas seguintes constantes de configuração:
| NOME DO ARQUIVO | CONSTANTE | DESCRIÇÃO |
| ------------- | ------------- | ------------- |
| src/common/constants.h | SECRET_DIRECTORY_NAME_HIDE | Nome do diretório a ser ocultado |
| src/common/constants.h | SECRET_FILE_PERSISTENCE_NAME | Nome do arquivo a ser ocultado |
Por padrão, o TripleCross ocultará qualquer arquivo chamado "*ebpfbackdoor*" e um diretório chamado "*SECRETDIR*". Este módulo é ativado automaticamente após a instalação do rootkit.
A técnica usada para alcançar essa funcionalidade consiste em adulterar os argumentos da chamada de sistema sys_getdents():
<img src="https://assets.kitploit.com/production/public/readmes/5614/7f928351c1c07e7b6a534846c5374788449e03455191cddf8c7f02af2c885852.png" float="left">
## Licença
O rootkit TripleCross e o cliente rootkit são licenciados sob a licença GPLv3. Veja [LICENSE](https://github.com/h3xduck/TripleCross/blob/master/LICENSE).
A biblioteca [RawTCP_Lib](https://github.com/h3xduck/RawTCP_Lib) é licenciada sob a licença MIT.
O documento original da tese e as figuras incluídas são liberados sob [Creative Commons BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/).
J. Dileo. Evil eBPF: Abusos Práticos de um Runtime de Bytecode no Kernel. DEFCON 27. slides ↩
P. Hogan. Distorcendo a Realidade: Criando e Combatendo a Próxima Geração de Rootkits Linux usando eBPF. DEFCON 27. apresentação ↩
G. Fournier e S. Afchain. eBPF, pensei que fossemos amigos! DEFCON 29. slides ↩
| DIRETÓRIO | COMANDO |
|---|
| docs | Documento original da tese |
| src/client | Código-fonte do cliente rootkit |
| src/client/lib | Biblioteca compartilhada RawTCP_Lib |
| src/common | Constantes e configuração do rootkit. Também inclui a implementação de elementos comuns ao lado eBPF e do espaço de usuário do rootkit, como o ring buffer |
| src/ebpf | Código-fonte dos programas eBPF usados pelo rootkit |
| src/helpers | Inclui programas para testar a funcionalidade de vários módulos do rootkit, e também o programa malicioso e a biblioteca usados nos módulos de sequestro de execução e injeção de bibliotecas, respectivamente |
| src/libbpf | Contém a biblioteca libbpf integrada com o rootkit |
| src/user | Código-fonte dos programas do espaço de usuário usados pelos rootkits |
| src/vmlinux | Cabeçalhos contendo a definição de estruturas de dados do kernel (este é o método recomendado ao usar libbpf) |
| FILENAME | CONSTANT | DESCRIPTION |
|---|
| src/common/constants.h | TASK_COMM_NAME_INJECTION_ TARGET_TIMERFD_SETTIME | Nome do processo a ser sequestrado na chamada de sistema sys_timerfd_settime |
| src/common/constants.h | TASK_COMM_NAME_INJECTION_ TARGET_OPEN | Nome do processo a ser sequestrado na chamada de sistema sys_openat |
| src/helpers/injection_lib.c | ATTACKER_IP & ATTACKER_PORT | Endereço IP e porta da máquina do atacante |