
Crypteur polymorphe qui transforme les fichiers shellcode, PE et COFF en charges utiles obscurcies et indépendantes de la position avec chiffrement RC4 et par blocs aléatoires, ainsi qu'une génération d'instructions poubelles à l'aide de la bibliothèque AsmJit.
Présenté à
Shoggoth est un projet open source basé sur C++ et la bibliothèque asmjit, utilisé pour chiffrer de manière polymorphe un shellcode, un fichier PE ou COFF donné.
Shoggoth génère un fichier de sortie qui stocke la charge utile et son chargeur correspondant sous une forme obscurcie. Comme le contenu de la sortie est indépendant de la position, il peut être exécuté directement en tant que shellcode. Pendant l'exécution de la charge utile, elle se déchiffre elle-même à l'exécution. En plus de la routine de chiffrement, Shoggoth ajoute également des instructions poubelles, qui ne changent rien, entre les routines.
J'ai commencé à développer ce projet pour étudier différentes approches de génération dynamique d'instructions, les pratiques d'assembly et les détections de signatures. Je prévois de mettre à jour régulièrement le dépôt avec mes nouveaux apprentissages.
Les fonctionnalités actuelles sont listées ci-dessous :
Le flux d'exécution général de Shoggoth pour un fichier d'entrée est visible dans l'image ci-dessous. Vous pouvez observer ce flux avec les configurations par défaut.
En gros, Shoggoth fusionne d'abord le shellcode du chargeur précompilé selon le mode choisi (fichier COFF ou PE) avec le fichier d'entrée. Il ajoute ensuite plusieurs instructions poubelles qu'il génère à cette charge utile fusionnée. Le stub contenant le chargeur, les instructions poubelles et la charge utile est d'abord chiffré avec RC4, puis avec un chiffrement par bloc généré aléatoirement, en combinant les déchiffreurs correspondants. Enfin, il ajoute une instruction poubelle au bloc résultant.
Lorsque Shoggoth génère aléatoirement des instructions pour les stubs poubelles ou les routines de chiffrement, il utilise la bibliothèque AsmJit.
AsmJit est une bibliothèque légère pour la génération de code machine écrite en C++. Elle peut générer du code machine pour les architectures X86, X86_64 et AArch64, et prend en charge les instructions de base ainsi que toutes les extensions récentes. AsmJit permet de spécifier des codes opération, des registres, des opérandes immédiats, des étiquettes d'appel, et d'intégrer des valeurs arbitraires à n'importe quel décalage dans le code. Pour générer certaines instructions assembly en utilisant AsmJit, il suffit d'appeler la fonction API correspondant à l'opération assembly requise avec des valeurs d'opérandes assembly de la classe Assembler. Pour chaque appel API, AsmJit conserve les informations de code et de relocalisation dans sa structure interne CodeHolder. Après avoir appelé les fonctions API de toutes les commandes assembly à générer, sa classe JitRuntime peut être utilisée pour copier le code de CodeHolder vers la mémoire avec une permission d'exécution et le relocaliser.
Lors de la recherche d'une bibliothèque de génération de code, j'ai rencontré AsmJit et j'ai vu qu'elle était largement utilisée par de nombreux projets populaires. C'est pourquoi j'ai décidé de l'utiliser pour mes besoins. Je ne sais pas si Shoggoth est le premier projet à l'utiliser dans le contexte d'une équipe rouge, mais je pense qu'il peut servir de référence pour de futures implémentations.
Shoggoth peut être utilisé pour chiffrer des fichiers PE et COFF donnés, de sorte que les deux puissent être exécutés en tant que shellcode grâce à des chargeurs précompilés indépendants de la position. J'ai simplement utilisé la méthode C vers Shellcode pour obtenir la version PIC de chargeurs PE et COFF bien connus que j'ai modifiés pour mes anciens projets. Pour la compilation, j'ai utilisé le Makefile du projet HandleKatz, un dumper LSASS sous forme PIC.
En gros, pour obtenir un shellcode avec la technique C vers Shellcode, j'ai supprimé toutes les variables globales dans le code source du chargeur, fait en sorte que toutes les chaînes soient stockées dans la pile, et résolu les adresses des fonctions de l'API Windows en chargeant et en analysant les DLL nécessaires à l'exécution. Ensuite, j'ai déterminé le point d'entrée avec un script d'éditeur de liens et compilé le code en utilisant MinGW avec divers drapeaux de compilation. J'ai extrait la section .text du fichier exécutable généré et obtenu le shellcode du chargeur. Comme le fichier exécutable obtenu après modification du code comme ci-dessus ne contient que la section .text, le code de cette section peut être utilisé comme indépendant de la position.
Le code source de ces chargeurs peut être consulté et modifié dans les répertoires COFFLoader et PELoader. Les versions compilées de ces codes sources se trouvent dans le répertoire stub. Pour l'instant, si vous souhaitez modifier ou changer ces chargeurs, vous devez respecter les signatures et remplacer les binaires précompilés du répertoire stub.
Pour passer des arguments à un BOF, utilisez l'option '--coff-arg'. Shoggoth attend une chaîne hexadécimale préformatée contenant les arguments compressés, qui peut être créée en utilisant le script beacon_generate.py de TrustedSec. Une copie de ce script est incluse sous COFFArgGenerator/beacon_generate.py. (Merci à @Octoberfest7)
Shoggoth utilise d'abord l'un des chiffrements par flux, l'algorithme RC4, pour chiffrer la charge utile qu'il obtient. Après avoir généré aléatoirement la clé utilisée ici, il chiffre la charge utile avec cette clé. Le stub de déchiffrement, qui déchiffre la charge utile pendant l'exécution, est créé dynamiquement et assemblé à l'aide d'AsmJit. Les registres utilisés dans le stub sont sélectionnés aléatoirement pour chaque échantillon.
Je me suis référé au code de Nayuki pour l'implémentation de l'algorithme RC4 que j'utilise dans Shoggoth.
Après le premier chiffrement, Shoggoth utilise le second chiffrement qui est un chiffrement par bloc généré aléatoirement. Avec le second chiffrement, il chiffre à la fois le déchiffreur RC4 et éventuellement le stub contenant la charge utile, les instructions poubelles et le chargeur chiffrés avec RC4. Il divise le bloc à chiffrer en blocs de 8 octets et utilise des instructions générées aléatoirement pour chaque bloc. Ces instructions incluent ADD, SUB, XOR, NOT, NEG, INC, DEC, ROL et ROR. Les opérandes de ces instructions sont également sélectionnés aléatoirement.
La logique de génération d'instructions poubelles est fortement inspirée de l'incroyable projet SGN d'Ege Balci. Shoggoth peut sélectionner des instructions poubelles basées sur le saut par-dessus des octets aléatoires, des instructions sans effets de bord, des fausses appels de fonctions, et des instructions qui ont des effets de bord mais conservent les valeurs initiales. Toutes ces instructions sont sélectionnées aléatoirement et générées en appelant les fonctions API correspondantes de la bibliothèque AsmJit. De plus, pour augmenter à la fois la taille et les différentes combinaisons, ces fonctions de génération sont appelées récursivement.
Il y a de nombreux endroits où des instructions poubelles peuvent être placées dans la première version de Shoggoth. Par exemple, nous pouvons mettre des instructions poubelles entre les instructions du chiffrement par bloc ou du chiffrement RC4. Cependant, pour des raisons de démonstration, je les ai laissées pour les versions suivantes afin d'éviter la complexité supplémentaire des charges utiles générées.
Je n'ai pas compilé le projet principal. C'est pourquoi vous devez le compiler vous-même. Optionnellement, si vous souhaitez modifier le code source du chargeur PE ou du chargeur COFF, vous devez avoir MinGW sur votre machine pour les compiler en utilisant les Makefiles fournis.
______ _ _
/ _____) | _ | |
( (____ | |__ ___ ____ ____ ___ _| |_| |__
\____ \| _ \ / _ \ / _ |/ _ |/ _ (_ _) _ \
_____) ) | | | |_| ( (_| ( (_| | |_| || |_| | | |
(______/|_| |_|\___/ \___ |\___ |\___/ \__)_| |_|
(_____(_____|
par @R0h1rr1m
"Tekeli-li! Tekeli-li!"
Utilisation de Shoggoth.exe :
-h | --help Affiche le message d'aide.
-v | --verbose Active les sorties plus détaillées.
-i | --input <Chemin d'entrée> Chemin d'entrée de la charge utile à chiffrer. (Obligatoire)
-o | --output <Chemin de sortie> Chemin de sortie pour l'entrée chiffrée. (Obligatoire)
-s | --seed <Valeur> Définit la valeur de graine pour l'aléatoire.
-m | --mode <Valeur du mode> Définit le mode de chiffrement de la charge utile. Modes disponibles : (Obligatoire)
[*] raw - Shoggoth n'ajoute pas de stub de chargeur. (Mode par défaut)
[*] pe - Shoggoth ajoute un stub de chargeur PE. L'entrée doit être un PE x64 valide.
[*] coff - Shoggoth ajoute un stub de chargeur COFF. L'entrée doit être un COFF x64 valide.
--coff-arg <Argument> Définit l'argument pour le chargeur COFF. Générez cette chaîne en utilisant COFFArgGenerator/beacon_generate.py.
exemple : --coff-arg 0a0000000600000068656c6c6f00
Utilisé uniquement en mode chargeur COFF. (Merci à @Octoberfest7)
-k | --key <Clé de chiffrement> Définit la première clé de chiffrement au lieu d'une clé aléatoire.
--dont-do-first-encryption Ne pas effectuer le premier chiffrement (chiffrement par flux).
--dont-do-second-encryption Ne pas effectuer le second chiffrement (chiffrement par bloc).
--encrypt-only-decryptor Chiffre uniquement le stub de déchiffrement dans le second chiffrement.
« C'était une chose terrible, indescriptible, plus vaste que n'importe quel métro – un amas informe de bulles protoplasmiques, faiblement luminescentes, et avec des myriades d'yeux temporaires se formant et se déformant comme des pustules de lumière verdâtre sur tout le front remplissant le tunnel qui s'abattait sur nous, écrasant les pingouins frénétiques et glissant sur le sol luisant que lui et ses semblables avaient si méchamment balayé de tous les débris. » ~ H. P. Lovecraft, Les Montagnes hallucinées
Un Shoggoth est un monstre fictif dans le Mythe de Cthulhu. Les êtres ont été mentionnés en passant dans le cycle de sonnets de H. P. Lovecraft, Fungi from Yuggoth (1929–30), puis décrits en détail dans sa novella Les Montagnes hallucinées (1931). Ils sont capables de former tous les organes ou appendices dont ils ont besoin pour la tâche à accomplir, bien que leur état habituel soit une masse grouillante d'yeux, de bouches et de tentacules frétillants.
Puisque ces créatures sont comme une masse informe de chair gélatineuse auto-modelante et n'ont pas de forme fixe dans les descriptions de Lovecraft, j'ai voulu donner ce nom à un outil de chiffrement polymorphe. 🙂
Pour des tests de sécurité autorisés uniquement. Toute utilisation abusive de cet outil contre des systèmes sans autorisation explicite est illégale.