J'ai démonté le rançongiciel The Gentlemen sans jamais l'exécuter
Analyse statique d'un rançongiciel Go obscurci pour Windows : ce qu'il fait, comment je l'ai lu, et ce qui reste à prouver.
Un rançongiciel n'a pas besoin d'être lancé pour livrer ses secrets. J'ai analysé un échantillon de la famille The Gentlemen (SHA-256 3ab9575225e00a83a4ac2b534da5a710bdcf6eb72884944c437b5fbe5c5c9235) uniquement par analyse statique. Le binaire n'a jamais tourné.
Pour éviter de présenter des suppositions comme des faits, j'ai classé chaque affirmation selon quatre niveaux :
Observé : lu tel quel dans le fichier
Dérivé : issu de la décompilation
Inféré : déduction plausible
Non vérifié : reste à confirmer
En bref
Exécutable Windows x64 de 2,96 Mo, écrit en Go 1.24 ou plus récent, obscurci avec garble
Chiffrement X25519 + XChaCha20, avec une clé différente pour chaque fichier
Déchiffrement impossible sans la clé privée de l'attaquant
Propagation par SMB, WMI, tâches planifiées et services distants
Aucune communication sortante dans le code principal
Un détail qui compte pour les équipes en bac à sable : le binaire ne fait rien sans l'argument --password et sa valeur codée en dur. Sans cet argument, il affiche « bad args » et s'arrête. Une détonation automatique sans arguments ne montrera donc aucun comportement.
La méthode
Les outils : la plateforme REA pour l'inventaire et l'orchestration, Ghidra 12.1.4 en mode sans interface pour la décompilation, rabin2 et strings pour une première lecture, et YARA pour valider la détection.
Trois obstacles, et comment je les ai contournés :
1. Aucun nom de fonction. Ghidra n'exposait que entry. Garble avait modifié le magic de la pclntab (d10889d7 au lieu de fffffff1). Un parseur Python de 40 lignes a retrouvé les 2 675 fonctions.
2. Le coût de chaque appel. Chaque appel en ligne de commande réimportait le binaire, soit environ 95 secondes. Avec une session persistante, j'ai fait environ 930 décompilations par lots.
3. Les chaînes Go fusionnées. Go ne termine pas ses chaînes par un octet nul, donc Ghidra les colle les unes aux autres. J'ai relu chaque paire (pointeur, longueur) dans le fichier pour retrouver le texte exact.
Bonne surprise : les chaînes littérales ne sont pas chiffrées. Avec strings, j'ai obtenu en quelques secondes la note de rançon, l'aide de la ligne de commande et les commandes PowerShell.
Le déroulé d'une attaque
Vérification du mot de passe
Relance détachée du binaire (variable
LOCKER_BACKGROUND=1)Attente optionnelle, en minutes
Désactivation de Defender, suppression des copies shadow et des journaux d'événements
Arrêt d'environ 80 processus et d'environ 75 services : Veeam, Acronis, MSSQL, Exchange, Sophos…
Persistance : tâches
UpdateSystemetUpdateUser, clés RunGupdateSetGupdateUDécouverte des cibles : disques locaux, lecteurs mappés, partages UNC
Chiffrement en parallèle
Propagation latérale sur le domaine
Fond d'écran « YOUR NETWORK IS LOCKED BY THE GENTLEMEN », puis auto-suppression
Le chiffrement
Pour chaque fichier, le programme génère une clé X25519 éphémère et l'échange avec la clé publique de l'attaquant, embarquée dans le binaire. Le secret obtenu sert de clé XChaCha20. La clé publique éphémère est écrite en base64 dans le pied du fichier, et la clé privée n'est jamais écrite sur disque.
Fichiers jusqu'à 1 Mio : chiffrés entièrement
Fichiers plus gros : trois blocs seulement (début, milieu, fin). Les options
--fast,--superfastet--ultrafastréduisent encore la part chiffréeExtension ajoutée :
.axfsmg, et marqueurGENTLEMENen fin de fichier
Incohérence relevée : le texte d'aide annonce 9 %, 3 % et 1 %, mais les constantes du code valent 0,03, 0,01 et 0,003. Ce sont les constantes qui s'appliquent.
Récupération : je n'ai trouvé aucune faiblesse cryptographique. En revanche, les gros fichiers chiffrés partiellement gardent des zones en clair, ce qui peut aider à en récupérer certains formats.
La propagation latérale
Une fois le chiffrement local terminé, le binaire :
se copie dans
C:\Tempet crée un partageshare$ouvert à Everyone ;rend le SMB plus permissif (
NullSessionShares,EveryoneIncludesAnonymous = 1) ;liste les machines du domaine avec
NetServerEnum;essaie de se lancer sur chaque hôte de six façons :
wmic /node,schtasks /S,sc \\hôte create,Invoke-CommandetWin32_Process, après avoir coupé Defender à distance.
Je n'ai vu aucun vol d'identifiants : la propagation semble reposer sur les droits du compte courant.
Comment le détecter
Exclusions Defender sur
C:\ouC:\Temp, et arrêt de la protection en temps réelvssadmin delete shadowsouwevtutil cl, suivis d'arrêts massifs de services de sauvegardeCréation d'un partage
share$et modification deNullSessionSharesTâches ou services distants nommés
DefU,DefS,UpdateGU,DefSvcouUpdateSvcFichiers
README-GENTLEMEN.txtet%TEMP%\gentlemen.bmp
Correspondance MITRE ATT&CK : T1486, T1490, T1489, T1562.001, T1070, T1053.005, T1547.001, T1543.003, T1021.002, T1047, T1135, T1222.001, T1491.001, T1027.
J'ai aussi écrit une règle YARA et je l'ai validée sur l'échantillon. Je la partage sur demande.
Les limites
Tout vient de la décompilation. La clé et le nonce exacts de XChaCha20, ainsi que la part réellement chiffrée, restent à confirmer par exécution.
LogonUserWetNetUserAddapparaissent dans les chaînes, mais je n'ai pas tracé leur usage.net/httpest présent dans le binaire, mais le code principal ne l'appelle pas.
Pour une analyse statique, la discipline compte autant que les outils : dire ce que l'on a vu, ce que l'on en déduit, et ce que l'on ne sait pas encore.
#CyberSécurité #Ransomware #ReverseEngineering #MalwareAnalysis #Ghidra #ThreatIntel #DFIR