Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
external_c2_framework — API Python pour utilisation avec la spécification External C2 de Cobalt Strike. | Kitploit
Outils/GitHubGitHub/und3rf10w/external_c2_framework
Frameworks de Tests d'IntrusionFrameworks d'ExploitationPost-ExploitationCommandement et ContrôleRed TeamingDéveloppement de Charges Utiles
GitHubund3rf10w/external_c2_framework

external_c2_framework

API Python pour utilisation avec la spécification External C2 de Cobalt Strike.

Voir le dépôt
239965il y a 4 ansVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

external_c2 framework

Framework Python pour créer et utiliser des interfaces permettant de transférer des données entre frameworks, avec un accent particulier sur le rôle d’extension des frameworks de commande et de contrôle.

Actuellement, ce projet n’est conçu que comme une implémentation de la spécification External C2 de Cobalt Strike, telle que décrite dans ce document de spécification, mais il est susceptible d’évoluer à mesure que le projet mûrit.

Credits

Un immense crédit revient à xychix. Ce projet n’aurait pas été possible du tout sans leurs précieuses contributions. Pour l’essentiel, ce projet est une reconstruction et une extension du projet External C2 d’Outflank

Architecture

Ce projet se compose des parties principales suivantes :

  • Générateur
  • Squelettes
  • Frameworks
  • Transports
  • Encodeurs
  • Gestionnaire (pas encore implémenté)

Générateur

Le générateur lit un fichier de configuration et utilise les options configurées pour générer une build en remplaçant les markers dans les squelettes.

Le générateur peut être utilisé avec build_files.py. Un exemple de configuration du générateur est fourni sous la forme de sample_builder_config.config.sample.

Squelettes

skeletons sont les différents « squelettes » de code que le builder remplira dynamiquement pour générer une build complètement utilisable. skeletons contiennent des markers qui seront remplacés par des valeurs utilisables par le builder. Il existe trois « types » différents de squelettes :

Marqueurs de squelette

Un marqueur peut être placé dans n’importe quel fichier d’un skeleton; il sera remplacé par une valeur spécifiée dans la config du générateur. En pratique, les marqueurs ne doivent jamais être utilisés pour écrire directement des variables, mais uniquement pour définir des valeurs. Si la valeur d’un marqueur doit être réutilisée, il convient de stocker la valeur dans une variable et d’y faire référence de cette manière, plutôt que de réutiliser le même marqueur.

Le format d’un marqueur est : ```[var:::identifier_for_the_marker]```

Les chaînes seront écrites dans un squelette directement entourées de guillemets simples, et les nombres seront écrits tels quels.

Si une chaîne de la configuration est entourée de guillemets doubles, la chaîne sera écrite directement dans le fichier entourée de guillemets doubles, et les guillemets simples qui l’entourent seront supprimés.

Cette relation peut être démontrée comme suit :

root@kitploit:~
#################
# Skeleton Code #
#################

# Skeleton contains the following line of code:
foo = ```[var:::bar]```

##############
# End Result #
##############

# Stored in config as:
#   foo = bar
# Written as:
foo = 'bar'

# Stored in config as:
#   foo = "bar"
# Written as:
foo = "bar"

# Stored in config as:
#   foo = 2
# Written as:
foo = 2

# Stored in config as:
#  foo = "2"
# Written as:
foo = "2"

Frameworks

Les frameworks constituent l’application de base qui détermine quelles données sont utilisées par le transport et l’encoder, et comment ces données sont utilisées. Ce que fait réellement un framework spécifique importe peu, tant qu’il existe une logique pour importer et utiliser l’encoder et le transport. La plupart des parties essentielles d’un framework (principalement la logique client) seront stockées sous forme de skeleton, avec une interface pour interagir avec la partie serveur stockée en tant qu’objet framework de base.

Généralement, un framework contient un server et un client, et utilise des encoders et des transports pour relayer les données entre eux.

Il y a quelques principes fondamentaux à prendre en compte lors de la construction d’un framework :

  • Le framework est responsable de la mise à disposition de l’encoder pour que le transport puisse l’utiliser.
  • Si le framework utilise une relation client-serveur, les deux doivent être organisés en conséquence.
  • Comprenez que, dans la majorité des cas, l’utilisateur final n’interagira jamais directement avec le client d’un framework. Si vous voulez que des éléments soient reconfigurables sur le client, celui-ci doit être capable de le faire au runtime sans interaction directe.
  • Il y a peu de besoin de créer un skeleton de server, car l’utilisateur final va interagir directement avec le server d’un framework. Optez plutôt à la fois pour la lecture des options depuis une configuration et pour la possibilité donnée à l’utilisateur final de modifier les options (comme une temporisation de bloc ou la verbosité) au runtime.
  • Un skeleton de framework sera traité par le générateur, qui itérera sur chaque fichier qu’il contient ; ainsi, si un argument donné doit être configurable au moment de la génération, cela peut être fait facilement.
  • Un server de framework doit pouvoir être interfacé par un framework_manager commun.

Serveur de framework

Le serveur est l’application qui sert d’intermédiaire entre le client et le c2 server. La logique du serveur est principalement statique. La logique du serveur pour le framework cobalt_strike, désigné comme third-party Client Controller dans la spécification, est présentée ci-dessous :

  1. Analyser la configuration
  2. Importer le module d’encodage spécifié
  3. Importer le module de transport spécifié
  4. Établir une connexion avec le serveur C2
  5. Demander un stager au serveur C2
  6. Encoder le stager avec le module encoder
  7. Transporter le stager avec le module transport
  8. Attendre une réponse de métadonnées du client reçue via le transport
  9. Décoder les métadonnées avec le module encoder
  10. Transmettre les métadonnées au serveur C2.
  11. Recevoir une nouvelle tâche du serveur C2.
  12. Encoder la nouvelle tâche
  13. Transmettre la nouvelle tâche au client via le transport
  14. Attendre une réponse du client reçue via le transport
  15. Décoder la réponse via le module encoder
  16. Transmettre la réponse au serveur C2.
  17. Répéter les étapes 11 à 16

Un server doit pouvoir gérer plusieurs clients (pas encore implémenté) et être interfacé par un framework_manager.

Client de framework

Le client est essentiellement la charge utile (payload) qui s’exécute sur le point de terminaison. La logique du client pour le framework cobalt_strike est principalement statique et présentée ci-dessous :

  1. Effectuer toutes les préparations nécessaires à l’utilisation du transport
  2. Recevoir le stager
  3. Injecter le stager et ouvrir le handle vers le beacon
  4. Obtenir les métadonnées du beacon
  5. Transmettre les métadonnées du beacon au serveur C2 via le transport
  6. Surveiller le transport pour de nouvelles tâches
  7. Transmettre les nouvelles tâches au beacon
  8. Transmettre les réponses du beacon via le transport
  9. Répéter les étapes 6 à 8.

Le client utilise l’encoder et le transport spécifiés pour relayer les données entre lui-même et son server respectif.

Encodeurs

Les encodeurs reçoivent des données, puis modifient ces données soit pour les préparer à être envoyées via le transport, soit pour décoder les données reçues via le transport et les ramener à leur forme brute afin qu’elles soient interprétées par le composant framework qui les utilise.

Les encodeurs doivent s’attendre à être interfacés directement par le transport et à traiter les données de manière indépendante du framework et du composant.

Transports

Les transports ont pour rôle d’envoyer et de recevoir des données via un canal de communication et d’interfacer l’encodeur afin de garantir que les données sont transformées dans le format nécessaire. Les transports doivent s’attendre à recevoir des données d’un composant de framework, ou via le canal de communication, et avoir la capacité de relayer les données à travers le canal de communication. Les transports sont responsables de l’appel à l’encoder pour encoder ou décoder les données si nécessaire.

Les transports doivent s’attendre à être interfacés directement par le composant framework et à traiter les données de manière indépendante du framework et du composant.

Comment utiliser ceci

  1. Tout d’abord, déterminez quel module de transport et d’encodage vous souhaitez utiliser. Nous utiliserons transport_imgur et encoder_lsbjpg pour l’exemple suivant.

  2. Ensuite, créez un builder_config.config adapté à vos besoins. Reportez-vous à l’exemple de configuration et au modèle fournis pour savoir comment procéder.

  3. Générez une build avec build_files.py. Par exemple, on peut générer une build dans le répertoire builds en utilisant encoder_lsbjpg et transport_imgur pour Cobalt Strike, en mode verbeux, avec la commande suivante :

root@kitploit:~
python build_files.py -b builds -f cobalt_strike -c sample_builder_config.config.sample -e encoder_lsbjpg -t transport_imgur -v
  1. Ensuite, lancez votre serveur généré et distribuez votre client.

Cobalt Strike

Sur la machine qui exécute 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 informations supplémentaires utiles au 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 et vous pourrez interagir avec lui.

FAQ

Pourquoi avoir écrit ceci ?: Il n’y avait pas beaucoup d’implémentations publiées de la spécification Cobalt Strike, et parmi celles publiées, elles ne sont soit pas dans un langage que je connais, soit elles ne possèdent pas la modularité et l’abstraction que je recherchais.

Pourquoi Python 2 ?: Parce que je suis paresseux et qu’il est facile d’y implémenter de nouveaux canaux de transport et d’encodage.

Votre code est nul: Ce n’est pas une question.

Puis-je soumettre de nouveaux modules de transport et/ou d’encodeur ?: Oui, je vous en prie ! Soumettez une pull request et je serai ravi de la revoir.

Comment compiler le client en un exécutable que je peux distribuer ?: J’ai testé cela avec succès sous Kali. Pour recréer mon environnement, assurez-vous simplement que veil-evasion est installé et que vous avez suivi sa procédure d’installation. Cela devrait avoir configuré un environnement wine avec Python installé, contenant toutes les dépendances dont vous avez besoin. Il se peut que vous deviez également installer le module pefile dans cet environnement.

Ensuite, vous pouvez vous rendre dans le répertoire du client pour lequel vous voulez générer un exécutable et exécuter :

root@kitploit:~
chmod +x compile_dll.sh
./compile_dll.sh
wine "C:\\Python27\\python.exe" /usr/share/veil/pyinstaller/pyinstaller.py -F -r c2file.dll -w --key "ayyyyyyylmao" client.py

Remplacez la valeur de key par celle que vous voulez. Vous devriez voir l’exécutable du client dans le répertoire dist/. Si vous voulez générer un exécutable qui fournit une console utilisable pour le débogage, compilez l’exécutable avec wine "C:\\Python27\\python.exe" /usr/share/veil/pyinstaller/pyinstaller.py -F -r c2file.dll -c client.py.

Télécharger l’outil