
Polimórfico criptografador que transforma shellcode, PE e arquivos COFF em payloads ofuscados e independentes de posição com criptografia RC4 e cifra de bloco aleatória, além de geração de instruções lixo usando a biblioteca AsmJit.
Apresentado em
O Shoggoth é um projeto open-source baseado em C++ e na biblioteca asmjit usado para criptografar shellcode, arquivos PE e COFF de forma polimórfica.
O Shoggoth irá gerar um arquivo de saída que armazena o payload e seu loader correspondente em uma forma ofuscada. Como o conteúdo da saída é independente de posição, ele pode ser executado diretamente como um shellcode. Durante a execução do payload, ele se descriptografa em tempo de execução. Além da rotina de criptografia, o Shoggoth também adiciona instruções lixo, que não alteram nada, entre as rotinas.
Comecei a desenvolver este projeto para estudar diferentes abordagens de geração dinâmica de instruções, práticas de montagem e detecção de assinaturas. Pretendo atualizar regularmente o repositório com meus novos aprendizados.
As funcionalidades atuais estão listadas abaixo:
O fluxo geral de execução do Shoggoth para um arquivo de entrada pode ser visto na imagem abaixo. Você pode observar este fluxo com as configurações padrão.

Basicamente, o Shoggoth primeiro mescla o shellcode do loader pré-compilado de acordo com o modo escolhido (arquivo COFF ou PE) e o arquivo de entrada. Em seguida, adiciona múltiplas instruções lixo que gera a este payload mesclado. O stub contendo o loader, a instrução lixo e o payload é criptografado primeiro com criptografia RC4 e depois com criptografia de bloco gerada aleatoriamente, combinando os descriptografadores correspondentes. Finalmente, adiciona uma instrução lixo ao bloco resultante.
Enquanto o Shoggoth gera instruções aleatoriamente para stubs lixo ou rotinas de criptografia, ele usa a biblioteca AsmJit.
AsmJit é uma biblioteca leve para geração de código de máquina escrita em linguagem C++. Ela pode gerar código de máquina para arquiteturas X86, X86_64 e AArch64, e suporta instruções base e todas as extensões recentes. AsmJit permite especificar códigos de operação, registradores, operandos imediatos, rótulos de chamada e incorporar valores arbitrários em qualquer deslocamento dentro do código. Ao gerar algumas instruções de montagem usando AsmJit, é suficiente chamar a função da API que corresponde à operação de montagem necessária com valores de operandos da classe Assembler. Para cada chamada de API, o AsmJit mantém informações de código e realocação em sua estrutura interna CodeHolder. Após chamar as funções da API de todos os comandos de montagem a serem gerados, sua classe JitRuntime pode ser usada para copiar o código do CodeHolder para a memória com permissão executável e realocá-lo.
Enquanto procurava por uma biblioteca de geração de código, encontrei o AsmJit e vi que ele é amplamente usado por muitos projetos populares. Por isso decidi usá-lo para minhas necessidades. Não sei se o Shoggoth é o primeiro projeto a usá-lo no contexto de equipe vermelha, mas acredito que pode ser uma referência para implementações futuras.
O Shoggoth pode ser usado para criptografar arquivos PE e COFF fornecidos, de modo que ambos possam ser executados como um shellcode graças a loaders pré-compilados independentes de posição. Simplesmente usei o método C para Shellcode para obter a versão PIC de loaders PE e COFF bem conhecidos que modifiquei para meus projetos antigos. Para compilação, usei o Makefile do projeto HandleKatz, que é um dump do LSASS na forma PIC.
Basicamente, para obter um shellcode com a técnica C para Shellcode, removi todas as variáveis globais no código-fonte do loader, armazenei todas as strings na pilha e resolvi os endereços das funções da API do Windows carregando e analisando as DLLs necessárias em tempo de execução. Depois, determinei o ponto de entrada com um script de linker e compilei o código usando MinGW com várias flags de compilação. Extraí a seção .text do arquivo executável gerado e obtive o shellcode do loader. Como o arquivo executável obtido após editar o código como acima não contém outras seções além da seção .text, o código nesta seção pode ser usado como independente de posição.
O código-fonte deles pode ser visto e editado nos diretórios COFFLoader e PELoader. As versões compiladas desses códigos-fonte podem ser encontradas no diretório stub. Por enquanto, se você quiser editar ou alterar esses loaders, deve obedecer às assinaturas e substituir os binários pré-compilados do diretório stub.
Para passar argumentos para um BOF, use a opção '--coff-arg'. O Shoggoth espera uma string hexadecimal pré-formatada contendo os argumentos empacotados, que pode ser criada usando o script beacon_generate.py da TrustedSec. Uma cópia deste script foi incluída como COFFArgGenerator/beacon_generate.py. (Muitos agradecimentos a @Octoberfest7)
O Shoggoth primeiro usa uma das cifras de fluxo, o algoritmo RC4, para criptografar o payload que obtém. Após gerar aleatoriamente a chave usada aqui, ele criptografa o payload com essa chave. O stub descriptografador, que descriptografa o payload em tempo de execução, é criado dinamicamente e montado usando AsmJit. Os registradores usados no stub são selecionados aleatoriamente para cada amostra.
Referenciei o código da Nayuki para a implementação do algoritmo RC4 que usei no Shoggoth.
Após a primeira criptografia ser realizada, o Shoggoth usa a segunda criptografia, que é uma cifra de bloco gerada aleatoriamente. Com a segunda criptografia, ele criptografa tanto o descriptografador RC4 quanto, opcionalmente, o stub que contém o payload, instruções lixo e o loader criptografados com RC4. Ele divide o bloco a ser criptografado em blocos de 8 bytes e usa instruções geradas aleatoriamente para cada bloco. Essas instruções incluem ADD, SUB, XOR, NOT, NEG, INC, DEC, ROL e ROR. Os operandos para essas instruções também são selecionados aleatoriamente.
A lógica de geração de instruções lixo é fortemente inspirada no incrível projeto SGN de Ege Balci. O Shoggoth pode selecionar instruções lixo baseadas em saltar sobre bytes aleatórios, instruções sem efeitos colaterais, chamadas de função falsas e instruções que têm efeitos colaterais mas mantêm valores iniciais. Todas essas instruções são selecionadas aleatoriamente e geradas chamando as funções correspondentes da API da biblioteca AsmJit. Além disso, para aumentar tanto o tamanho quanto as diferentes combinações, essas funções de geração são chamadas recursivamente.
Há muitos lugares onde instruções lixo podem ser colocadas na primeira versão do Shoggoth. Por exemplo, podemos colocar instruções lixo entre instruções da cifra de bloco ou instruções da cifra RC4. No entanto, para fins de demonstração, deixei-os para as versões seguintes para evitar a complexidade extra dos payloads gerados.
Não compilei o projeto principal. Por isso, você precisa compilá-lo por conta própria. Opcionalmente, se você quiser editar o código-fonte do loader PE ou do loader COFF, deve ter o MinGW em sua máquina para compilá-los usando os Makefiles fornecidos.
______ _ _
/ _____) | _ | |
( (____ | |__ ___ ____ ____ ___ _| |_| |__
\____ \| _ \ / _ \ / _ |/ _ |/ _ (_ _) _ \
_____) ) | | | |_| ( (_| ( (_| | |_| || |_| | | |
(______/|_| |_|\___/ \___ |\___ |\___/ \__)_| |_|
(_____(_____|
by @R0h1rr1m
"Tekeli-li! Tekeli-li!"
Uso de Shoggoth.exe:
-h | --help Mostra a mensagem de ajuda.
-v | --verbose Ativa saída mais detalhada.
-i | --input <Caminho de Entrada> Caminho de entrada do payload a ser criptografado. (Obrigatório)
-o | --output <Caminho de Saída> Caminho de saída para o payload criptografado. (Obrigatório)
-s | --seed <Valor> Define o valor da semente para a randomização.
-m | --mode <Valor do Modo> Define o modo de criptografia do payload. Os modos disponíveis são: (Obrigatório)
[*] raw - Shoggoth não anexa um stub de loader. (Modo padrão)
[*] pe - Shoggoth anexa um stub de loader PE. A entrada deve ser um PE x64 válido.
[*] coff - Shoggoth anexa um stub de loader COFF. A entrada deve ser um COFF x64 válido.
--coff-arg <Argumento> Define o argumento para o loader COFF. Gere esta string usando COFFArgGenerator/beacon_generate.py.
exemplo: --coff-arg 0a0000000600000068656c6c6f00
Usado apenas no modo de loader COFF. (Agradecimentos a @Octoberfest7)
-k | --key <Chave de Criptografia> Define a primeira chave de criptografia em vez de uma chave aleatória.
--dont-do-first-encryption Não faz a primeira criptografia (cifra de fluxo).
--dont-do-second-encryption Não faz a segunda criptografia (cifra de bloco).
--encrypt-only-decryptor Criptografa apenas o stub descriptografador na segunda criptografia.
"Era uma coisa terrível, indescritível, maior que qualquer trem de metrô - uma congérie disforme de bolhas protoplasmáticas, vagamente autoluminosas, e com miríades de olhos temporários se formando e se desformando como pústulas de luz esverdeada por toda a frente que preenchia o túnel e avançava sobre nós, esmagando os pinguins enlouquecidos e deslizando sobre o chão brilhante que ela e sua espécie tinham varrido tão maldosamente de todo lixo." ~ H. P. Lovecraft, Nas Montanhas da Loucura
Um Shoggoth é um monstro fictício no Mitos de Cthulhu. As criaturas foram mencionadas de passagem no ciclo de sonetos de H. P. Lovecraft, Fungi from Yuggoth (1929–30), e posteriormente descritas em detalhe em sua novela Nas Montanhas da Loucura (1931). Elas são capazes de formar quaisquer órgãos ou apêndices que necessitem para a tarefa em questão, embora seu estado usual seja uma massa contorcida de olhos, bocas e tentáculos ondulantes.
Como essas criaturas são como uma massa senciente de carne gelatinosa auto-modelável e não têm forma fixa nas descrições de Lovecraft, quis dar esse nome a uma ferramenta de Criptografia Polimórfica. 🙂
Apenas para testes de segurança autorizados. O uso indevido desta ferramenta contra sistemas sem permissão explícita é ilegal.