
Implante de canal oculto DNS para Red Teams.
WEASEL é um pequeno implante em memória que utiliza Python 3 sem dependências. O cliente beacon envia uma pequena quantidade de informações de identificação sobre seu host para uma zona DNS que você controla. O servidor WEASEL pode instruir os clientes a executar comandos pré-definidos ou arbitrários.
WEASEL é uma carga útil do estágio 1, projetada para ser difícil de detectar e útil para recuperar o acesso quando seus estágios completos e barulhentos são capturados.
Status
Consulte o uso no README do cliente e no README do servidor para instruções específicas.
Para iniciar o servidor ou o cliente, execute os scripts diretamente ou passe-os para o interpretador Python.
Certifique-se de que cada domínio C2 tenha um registro NS apontando para o endereço IP do host que executa o server.py.
O WEASEL requer Python 3.6+.
O cliente é autossuficiente e usa apenas bibliotecas padrão, portanto, pode ser executado em macOS, Linux, etc.
O servidor tem algumas dependências do pip, incluídas no requirements.txt do servidor. O servidor deve ser executado no Linux, mas não há nada que impeça sua execução no macOS ou outros *nix.
Neste caso, não é necessário ofuscar e minimizar o beacon. As declarações de impressão são preservadas. Como no Uso acima, certifique-se de que os registros NS para o(s) domínio(s) em servers no beacon.py apontem para o endereço IP do server.py.
No host do servidor:
sudo python3 server.py
No host da vítima (pode ser o mesmo do servidor):
python3 beacon.py
Você não precisa entender nada disso para usar o WEASEL.
O Beacon se comunica via DNS usando consultas e respostas AAAA. Ele não usa registros TXT devido ao fato de serem conhecidos por serem usados por malwares e túneis DNS. As equipes azuis geralmente têm detecções de tunelamento DNS que alertam sobre grandes consultas TXT.
O lado do cliente não precisa de root para operar, não usa sockets brutos e não cria pacotes DNS malformados. Ele usa interfaces regulares fornecidas pelo sistema e pela linguagem para fazer solicitações DNS. As informações são codificadas + criptografadas nos próprios registros.
Este beacon foi projetado para ser lento e discreto, com pouca largura de banda. Deve nos informar em quais hosts está e nos dar uma maneira de lançar estágios adicionais conforme necessário, e nada mais. Embora tenha suporte a comandos arbitrários, não se destina a ser usado como um shell interativo regular ou canal de comunicação.
WEASEL é um estágio 1 que você mantém em execução, garantindo acesso contínuo à medida que seus estágios completos (e, portanto, mais barulhentos) são capturados.
O WEASEL foi inicialmente direcionado para servidores com alto tempo de atividade, onde tínhamos um vetor de exploração/ponto de apoio confiável. Evitar a forense era uma prioridade alta. Como resultado, ele não possui recursos de persistência nativos.
Você pode torná-lo persistente adicionando sua execução à sua técnica de persistência favorita, o que fica como exercício para o leitor :)
Uma solicitação (do cliente) é uma única consulta AAAA para um nome formatado como:
<preâmbulo><dados>.<fluxo>.<sessão>.domínio.tld
O preâmbulo tem 2 bytes. O Preâmbulo[0] é o número de sequência desse pacote. O Preâmbulo[1] é o número total de pacotes nesse fluxo.
Os dados são limitados a 50 bytes (configurável) e contêm a carga útil. A carga útil é codificada em base32 com um alfabeto personalizado.
Primeiro, todos os caracteres 'w' são trocados por '-'.
Em seguida, o caractere de preenchimento é trocado de '=' para 'w' para estar em conformidade com o conjunto de caracteres DNS: [a-z0-9] e [-].
Não trocamos '=' por '-' diretamente porque o preenchimento estará sempre no final da string, e terminar um nome de host em '---' é suspeito e contra a RFC do DNS. Dessa forma, quando uma string tiver preenchimento, ela terminará em 'www', que é menos suspeito e está em conformidade com a RFC.
Uma resposta (do servidor) é composta por uma ou mais respostas AAAA.
Cada resposta AAAA é uma carga útil criptografada de 16 bytes representada como um endereço IPv6 usando socket.inet_ntop. As respostas em uma resposta DNS não mantêm sua ordem durante o trânsito, portanto, são sequenciadas e remontadas como as solicitações do cliente.
A carga útil do transporte é uma string de elementos de dados separados pelo caractere ^.
As solicitações e respostas seguem este formato:
<tipo>|<dados>
| Tipo | Significado (remetente) | AKA | Dados |
|---|---|---|---|
| 0 | Reconhecido | ACK | Hex aleatório |
| 1 | Check-in (cliente) | PING | Hex aleatório |
| 2 | Encerre-se (servidor), encerrando-me (cliente) | FIN | |
| 3 | Mensagem de inicialização (cliente) | SYN | `versão |
| 4 | Reconectar (servidor) | RST | |
| 5 | Definir intervalo de callback (servidor) | segundos | |
| 6 | Obter dados da interface de rede | eth0 1.2.3.4/24\neth1 fe80:::/64\n... | |
| 8 | Avaliar código Python3 arbitrário de até 666 bytes (servidor), retornando os primeiros 400 bytes da saída (cliente) | EVAL | script oneliner python3 |
| 9 | Executar comando arbitrário de até 666 bytes (servidor), retornando os primeiros 400 bytes da saída (cliente) | EXEC | comando bash |
As sessões são de longa duração: um cliente inicia uma sessão quando o beacon é executado pela primeira vez, e essa sessão deve durar todo o tempo em que o beacon estiver ativo naquele cliente. Observe que, como o beacon está na memória e não é persistente, os dados da sessão são armazenados na memória do processo Python. Qualquer nova invocação do beacon iniciará uma nova sessão.
Iniciar uma sessão envolve o cliente criar uma mensagem com um preâmbulo não-dados exclusivamente identificador (para sinalizar ao servidor que esta é uma nova sessão): a concatenação de uma chave pública Diffie-Hellman de 32 bytes e um IV AES aleatório de 16 bytes.