
API Python pour une utilisation avec la spécification External C2 de Cobalt Strike
Framework Python pour une utilisation avec la spécification External C2 de Cobalt Strike, telle que décrite dans la spécification.
L'objectif de conception principal est de fournir une implémentation très modulaire de la spécification external c2, offrant suffisamment d'abstraction pour implémenter facilement des canaux C2 pour Cobalt Strike. Idéalement, tout ce qu'un utilisateur aurait à faire est de créer un module transport, un module encoder, et de remplir un fichier de configuration pour implémenter un nouveau canal.
Vous devrez effectuer plusieurs modifications de configuration avant de pouvoir commencer. Vous devrez :
builds/client/dbox/dbox_client.py, remplacez token par celui généré à l'étape 2.builds/server/utils/transports/transport_dbox.py, effectuez les mêmes modifications qu'à l'étape 3.cd builds/client/dbox && ./compile_dll.shstart_externalc2.cna depuis votre client CS.cd builds/server/ && ./dbox_server.pyLien vers la démo vidéo : https://www.youtube.com/watch?v=nTRHSh_uCcA
Ce projet se compose de trois parties principales :
Le builder construit dynamiquement les déploiements client et serveur en fonction de la configuration spécifiée. Idéalement, le client pourrait être distribué sous forme d'un fichier compilé unique tel qu'une DLL ou un EXE.
Le client est essentiellement la charge utile qui s'exécute sur le point de terminaison, désignée comme third-party client dans la spécification. La logique du client est principalement statique :
transporttransporttransport pour de nouvelles tâchestransportLes configurations nécessaires pour le transport et les mécanismes d'encodage sont copiées statiquement dans le client. La logique des fonctions de transport et d'encodage est également copiée statiquement depuis leurs modules respectifs.
La logique d'injection de processus est déterminée par le builder.
Le serveur est l'application qui sert d'intermédiaire pour la communication entre le client et le c2 server, désigné comme third-party Client Controller dans la spécification. La logique du serveur est principalement statique, mais prend en charge des sorties verbeuses et de débogage pour faciliter le développement :
encodertransporttransportencodertransporttransportencoderLe choix du module encoder et du module transport importés par le serveur est déterminé à partir des valeurs stockées dans config.py.
Aucun import des modules transport ou encoder non utilisés n'est effectué.
Les tableaux suivants décrivent les fonctions partagées entre les modules encoding et transport, et le client. Les fonctions partagées sont essentiellement exactement le même code.
UNE NOTE TRÈS IMPORTANTE : Les données envoyées aux fonctions sendData et recvData du client doivent être des données brutes, tandis que les données envoyées aux fonctions sendData et retrieveData du module de transport doivent déjà être encodées ou décodées selon les besoins.
| Fonction Transport | Fonction Client | Description |
|---|---|---|
| prepTransport |
| Fonction Encodeur | Fonction Client | Description |
|---|---|---|
| encode | encode | Définit les modifications apportées aux données brutes pour les préparer au transport |
| decode | decode | Définit les modifications apportées aux données brutes reçues du transport pour être relayées vers leur destination |
Tout d'abord, déterminez quel module de transport et d'encodage vous souhaitez utiliser. Nous utiliserons transport_gmail et encoder_b64url pour l'exemple suivant.
Ensuite, modifiez server/config.py selon vos besoins, en vous assurant que ENCODER_MODULE et TRANSPORT_MODULE sont correctement configurés et pointent vers vos modules souhaités :
EXTERNAL_C2_ADDR = "127.0.0.1"
EXTERNAL_C2_PORT = "2222"
C2_PIPE_NAME = "foobar"
C2_BLOCK_TIME = 100
C2_ARCH = "x86"
IDLE_TIME = 5
ENCODER_MODULE = "encoder_b64url"
TRANSPORT_MODULE = "transport_gmail"
verbose = False
debug = False
Ensuite, modifiez la section de configuration pour vos modules transport et encoder sélectionnés.
Assurez-vous que la section de configuration de client/mechanism/$mechanism_client.py correspond à toutes les configurations que vous avez définies jusqu'à présent.
Sur la machine exécutant le serveur, exécutez :
python server.py
Pour une sortie plus verbeuse, vous pouvez exécuter :
python server.py -v
Pour une sortie plus verbeuse et des sorties supplémentaires utiles pour le débogage, vous pouvez exécuter :
python server.py -d
Ensuite, exécutez le client sur le point de terminaison ciblé.
Si tout a fonctionné, un nouveau beacon sera enregistré dans la console Cobalt Strike, avec lequel vous pourrez interagir.
Pourquoi avoir écrit cela ? : Il n'y avait pas beaucoup d'implémentations publiées de la spécification, et parmi celles qui sont publiées, elles ne sont soit pas dans un langage que je connais, soit n'ont pas la modularité et l'abstraction que je recherchais.
Pourquoi Python 2 ? : Je suis paresseux et il est facile d'y implémenter de nouveaux canaux de transport et d'encodage.
Ton code est nul : Ce n'est pas une question.
Puis-je soumettre de nouveaux modules de transport et/ou d'encodage ? : Oui, s'il vous plaît ! Soumettez une pull request et je serais heureux de la revoir.
Une abstraction et une modularité similaires seront également implémentées dans le composant client, afin de prendre en charge différentes méthodes d'injection de processus pour la charge utile du beacon et d'autres fonctionnalités prévues à la feuille de route.
Actuellement, la fonctionnalité de builder manque, qui est prévue pour construire dynamiquement les déploiements client et serveur, mais elle est sur la feuille de route.
| prepTransport |
| Effectue toutes les préconfigurations requises pour utiliser le mécanisme de transport |
| sendData | sendData | Définit comment les données sont envoyées via le mécanisme de transport |
| retrieveData | recvData | Définit comment les données sont reçues via le mécanisme de transport |