Tricard —Profilage de sandboxes malware

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..

Mème Spider-Man qui se pointe du doigt

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

Structure de données JSON de Tricard
Structure JSON correspondant aux fonctions de collecte

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 :

Pattern de nommage des fichiers Tricard
Pattern de nommage : IP source _ nom de l'échantillon _ date de compilation epoch _ timestamp de réception.json

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 :

Bash
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 :

Noms de fabricant aléatoires dans une sandbox
Noms de fabricant générés aléatoirement — un indicateur courant de sandbox
Fichiers temporaires aléatoires dans une sandbox
Fichiers temporaires suspects générés par l'environnement sandbox
Processus aléatoires dans une sandbox
Noms de processus inhabituels révélant un environnement sandboxé

Configuration du serveur

Enregistrement d'un nouvel échantillon Tricard

Flux de correspondance UUID
Workflow d'enregistrement et de correspondance des UUID
  1. Étape 1 : Compiler localement avec dispatcher.py
  2. É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
  3. Étape 3 : Envoyer l'échantillon aux sandboxes
  4. Étape 4 : Les données sont collectées depuis le serveur backend (srv.py)
  5. É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

Structure de la base de données JSON Statham
Base des échantillons : chaque entrée contient l'UUID et la permutation du charset base64

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

C'est tout pour cette fois ! Restez classe, amateurs de cybersécurité, et joyeuse journée des Licornes !


Décembre 2023


← Retour aux articles

Besoin d'un audit de sécurité ou d'un accompagnement sur mesure ?

Découvrir nos services →