https://github.com/therealunicornsecurity/tricard
→ Logiciel de sécurité : Je vais protéger votre système et défendre contre les activités malveillantes !
→ Malware : Je vais détecter et contourner vos défenses !
→ Logiciel de sécurité : Je vais alors détecter vos mécanismes de détection !
→ Malware : Je vais .. euh..
Origines et objectif
Tricard était à l'origine une simple fonction récursive pour interroger le registre. Lors des exercices de Red Team, il est assez courant d'essayer de comprendre à quoi servent les machines. L'un des usages les plus fréquents de ce programme était de trouver des configurations liées à PuTTY, afin d'identifier les postes de travail des administrateurs système. Après avoir été déployé de nombreuses fois pour la collecte d'informations, nous avons remarqué que notre serveur de collecte recevait des données surprenantes : il collectait involontairement des données provenant de sandboxes d'analyse de malware. Notre binaire était analysé par les outils déployés dans les réseaux de nos clients, et leurs sandboxes exécutaient également notre programme. C'est alors que nous avons découvert un autre usage potentiel pour cet outil d'audit simple.
Compilation et déploiement
Toutes les données sont concaténées dans un tableau JSON. Comme celui-ci peut devenir très volumineux très rapidement, les requêtes POST contenant le payload JSON sont compressées en Zlib. Le client et le serveur sont configurés pour communiquer via HTTPS.
Fonctions de collecte
Chaque fonction de collecte ajoute des données dans un buffer JSON passé en paramètre char*.
1. ListProcessesToJson
Liste les processus en cours d'exécution sur le système. Ajoute les informations de chaque processus à une chaîne au format JSON.
2. ListLoadedModulesToJson
Liste les modules chargés (DLLs) dans les processus en cours d'exécution. Ajoute les informations des modules à une chaîne au format JSON.
3. GetPSHistory
Récupère l'historique des commandes PowerShell. Encode l'historique en base64 et l'ajoute à la chaîne JSON.
4. GetSysinfo
Récupère diverses informations système (version de l'OS, architecture, informations utilisateur). Encode les informations en base64.
5. GetNetworkInterfacesJSON
Récupère les informations des interfaces réseau (adresses MAC, adresses IP).
6. GetBasicInfo
Récupère les informations système de base (nom de la machine, nom d'utilisateur, domaine). Initialise la structure de données JSON.
7. LoopFolders
Parcourt les dossiers spécifiés (dossier temporaire et bureau). Liste les fichiers incluant les détails comme le nom, le type, le magic number, la date de création et la date de modification.
8. SendGzipCompressedPOSTRequest
Envoie une requête POST vers un serveur avec des données compressées en Gzip. Utilise les fonctions WinHTTP pour ouvrir une session TLS, se connecter et envoyer la requête.
9. main()
Orchestre la collecte et la transmission des informations système. Initie une requête POST HTTP/TLS compressée en Gzip pour envoyer les données au serveur.
Structure JSON
La structure du fichier JSON respecte les fonctions de collecte décrites ci-dessus :
- Username (String) : Nom d'utilisateur associé aux données
- MalOne (UUID) : Identifiant unique associé à l'échantillon
- Computername (String) : Nom de la machine
- NetworkInterfaces (Liste) : Informations des interfaces réseau incluant le nom de l'adaptateur, la description, l'adresse IP et l'adresse MAC
- PSHistory (String) : Historique PowerShell encodé en base64
- Sysinfo (String) : Informations système encodées en base64
- Files (Dictionnaire) : Arborescence du système de fichiers avec les détails des répertoires et fichiers
- RunningProcesses (Liste) : Processus en cours d'exécution
- LoadedModules (Liste) : Modules chargés
- Regdump (Dictionnaire) : Dump du registre organisé par ruche (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, etc.)
Chaque fichier JSON reçu est nommé selon un pattern spécifique :
Binaires compilés
Chaque fichier source est modifié par le dispatcher via sed. Un UUID est placé à deux endroits : les cookies et le payload JSON. Ceci permet de détecter les systèmes qui passent par des proxies de terminaison TLS, ou utilisent des modules HTTP qui réécrivent les headers.
Les binaires sont compilés avec mingw pour Linux :
x86_64-w64-mingw32-g++ -w -static -Os -s tmpsrc/tricard.test.cpp \
-o tmpbuild/tricard.test.exe -lwinhttp -liphlpapi -lz -lcrypt32 -std=c++14
Le binaire original est relativement lourd (environ 1 Mo) mais peut être compressé avec UPX ou tout autre packer. Cependant, comme Tricard est déjà détecté par la plupart des solutions antivirus, le packer ne fait qu'empirer les choses.
Exemples
Voici quelques exemples flagrants de sandboxing :
Configuration du serveur
Enregistrement d'un nouvel échantillon Tricard
- Étape 1 : Compiler localement avec dispatcher.py
- Étape 2 : Envoyer les informations du binaire au serveur (UUID MalOne, permutation du charset base64). Chaque message est signé par HMAC pour empêcher la pollution des données
- Étape 3 : Envoyer l'échantillon aux sandboxes
- Étape 4 : Les données sont collectées depuis le serveur backend (srv.py)
- Étape 5 : Si l'UUID du binaire émetteur correspond à un UUID trouvé dans statham.json, il est tagué en conséquence. Sinon, il contient la chaîne
__unknowntarget__
Endpoints du serveur
POST /GetData
Reçoit des données compressées via une requête POST. Lit un fichier JSON (« statham.json ») contenant la base de données. Décompresse les données reçues et fait correspondre la clé MalOne avec la base. Si une correspondance est trouvée, les données sont mises à jour et sauvegardées. Sinon, un fichier unknowntarget est écrit.
POST /MalOne
Stocke les échantillons nouvellement enregistrés. Reçoit des données JSON contenant un message et un HMAC. Vérifie l'intégrité du message via le HMAC avec une clé secrète. Si la vérification réussit, met à jour « statham.json » avec les informations du nouvel échantillon (UUID et charset base64).
Base de données des échantillons
Chaque nouvel échantillon est enregistré avec les informations suivantes :
- Clé : nom de l'échantillon + date de compilation epoch
- Valeurs : UUID identifiant chaque échantillon, permutation du charset base64 (utilisée pour le décodage de l'historique PowerShell)
Analyse
La phase d'analyse est volontairement laissée de côté ici. En effet, Tricard continuera très probablement à être utilisé pour les audits et la collecte de données. Après tout, ce n'est qu'un outil de collecte agnostique. C'est l'analyse et ce qu'on en fait qui définit son objectif. C'est pour cette raison que le code a été publié, car nous aimerions le voir grandir.
Références
- MISP Warning Lists
- Collection d'outils malware
- Ressources d'analyse de malware
- Sandprint — Fingerprinting Malware Sandboxes (article de recherche qui a inspiré ce travail)
C'est tout pour cette fois ! Restez classe, amateurs de cybersécurité, et joyeuse journée des Licornes !
Décembre 2023
Besoin d'un audit de sécurité ou d'un accompagnement sur mesure ?
Découvrir nos services →