Paalkia CTF

Hexagone CTF / Forensics / Panthère Silencieuse 2/4

Medium T1059.001 Opération Panthère Silencieuse

Panthère Silencieuse 2/4

PowerShell obfusqué

01Énoncé

Les journaux d'événements de FIN-WKS-07 ont été exportés après la compromission. Reconstitue ce qui s'est exécuté au lancement de l'intrusion et récupère le secret que la charge dissimule. Format du flag : RWX{...}

02Contexte

Toujours sur FIN-WKS-07, on passe à l'analyse de journaux d'événements Windows. Une pièce jointe piégée a lancé une chaîne d'exécution qui télécharge un second binaire. Le flag est caché dans le script, obfusqué en deux couches.

TTP de référence : pièce jointe malveillante, détournement de mshta, PowerShell obfusqué. Acteurs comparables : APT32, FIN7, MuddyWater.

03Artefact

  • PANTHERE-EVD-02.zip contenant un dossier evtx/
  • 190 canaux EVTX, dont Microsoft-Windows-Sysmon%4Operational.evtx et Security.evtx
  • Les journaux PowerShell/Operational et PSReadLine sont volontairement absents : le challenge se résout depuis Sysmon seul

04Difficulté

Le challenge ne repose pas sur un outil complexe mais sur le tri. 190 journaux EVTX, la plupart vides ou sans rapport avec l'intrusion, et aucun journal PowerShell pour lire les scripts en clair. Il faut savoir quel journal porte la preuve, et le connaître assez bien pour en extraire la chaîne d'exécution.

05Pourquoi Sysmon

Sysmon (Sysinternals, Microsoft) est un service et un driver qui journalise l'activité système de façon bien plus détaillée que les journaux Windows natifs. Il n'est pas installé par défaut : quand il est présent, c'est la première source à ouvrir.

Son Event ID 1 (création de processus) enregistre pour chaque processus :

  • la ligne de commande complète ;
  • le processus parent et sa ligne de commande ;
  • l'utilisateur, les hashes du binaire, un identifiant unique (ProcessGuid) qui permet de chaîner les processus.

L'équivalent natif, l'événement Security 4688, n'enregistre pas la ligne de commande par défaut (il faut l'activer par GPO) et ne donne ni hashes ni ligne de commande du parent.

Sysmon couvre aussi le reste de la chaîne d'attaque : connexions réseau (EID 3), création de fichiers (EID 11), modifications de registre (EID 13), requêtes DNS (EID 22). Une seule source pour suivre l'attaquant de l'exécution à la persistance.

06Résolution

Étape 1 : choisir le bon journal

Journaux EVTX triés par taille

On trie les 190 journaux par taille. La majorité pèse 68 Ko (journal vide, non visible ici). Deux sortent du lot : Security.evtx et Microsoft-Windows-Sysmon%4Operational.evtx. On commence par Sysmon pour les raisons ci-dessus.

Étape 2 : reconstituer la chaîne d'exécution

Méthode 1 : Event Viewer

Ouvrir eventvwr.msc > Action > Open Saved Log > le fichier Sysmon.

Filter Current Log > Event IDs : 1

Filtre sur l’Event ID 1 dans Event Viewer

On filtre sur l'Event ID 1 pour ne garder que les créations de processus.

Sans connaître le vecteur d'intrusion, on cherche une anomalie classique : une exécution depuis un répertoire utilisateur (Downloads, AppData, Temp).

Les logiciels légitimes s'exécutent depuis Program Files ou System32 ; une charge livrée par mail ou navigateur atterrit dans le profil utilisateur.

Action > Find > Downloads

Recherche de Downloads dans Event Viewer

On ouvre le journal Sysmon exporté (600 événements) et on filtre sur l'Event ID 1 : 292 créations de processus. On cherche ensuite Downloads (Action > Find).

Note : l'onglet General affiche « The description for Event ID 1 cannot be found » car Sysmon n'est pas installé sur la machine d'analyse. Les données sont intactes, on les lit dans l'onglet Details (Friendly View).

La recherche remonte 4 événements, présentés ici dans l'ordre chronologique.

Événement Sysmon : mshta.exe

09:14:25 : explorer.exe (PID 1484) lance C:\Windows\SysWOW64\mshta.exe (PID 2268) sur C:\Users\j.martin\Downloads\Facture_2026_impayee.hta.

L'utilisateur j.martin a ouvert une fausse facture au format HTA : c'est le point d'entrée. mshta est un binaire Windows légitime détourné pour exécuter du code (LOLBin).

Événement Sysmon : powershell.exe

09:14:26 : moins d'une seconde après, mshta (PID 2268) lance powershell.exe -nop -w hidden -enc <...> (PID 5664). Options : -nop (pas de profil), -w hidden (fenêtre cachée), -enc (commande encodée en base64).

La ligne de commande appelle System32\...\powershell.exe mais l'image réelle est dans SysWOW64 : mshta étant en 32 bits, Windows redirige l'appel vers la version 32 bits de PowerShell.

Événement Sysmon : FacturePro_Update.exe

09:14:28 : PowerShell (PID 5664) lance C:\Users\j.martin\Downloads\FacturePro_Update.exe (PID 7796).

Le binaire n'a ni description, ni éditeur, ni version, contrairement aux binaires légitimes vus plus haut. Le champ ParentCommandLine contient la commande PowerShell encodée complète : c'est là qu'on la récupère pour l'étape de décodage.

Événement Sysmon : cmd.exe copie le binaire

09:17:21 : trois minutes plus tard, un processus de PID 7796, celui de FacturePro_Update.exe, lance cmd /c copy pour dupliquer le binaire dans C:\Users\j.martin\AppData\Roaming\Microsoft\Windows\, un dossier au nom légitime. Signe probable de préparation d'une persistance.

Chaîne complète :

Chaîne d’exécution
explorer.exe → mshta.exe (HTA) → powershell.exe -enc → FacturePro_Update.exe → cmd.exe (copie dans AppData)

Méthode 2 : Chainsaw

Chainsaw est un outil open source de WithSecure, conçu pour le triage rapide d'artefacts Windows (journaux EVTX, MFT). Deux modes :

  • search : recherche une chaîne ou une expression régulière dans tous les journaux ;
  • hunt : applique des règles de détection Sigma et ses propres règles à l'ensemble des journaux.

Ce qu'il apporte : pas besoin de savoir quel journal ouvrir ni quoi chercher, les règles signalent l'activité suspecte. Les 190 journaux sont analysés en 7 secondes, avec une sortie en tableau, CSV ou JSON.

PowerShell
.\chainsaw.exe hunt "C:\Users\paalkia\Documents\Hexagone_CTF\PANTHERE-EVD-02\evtx\" -s sigma\ --mapping mappings\sigma-event-logs-all.yml

Le fichier de mapping fait la correspondance entre les champs des règles Sigma et ceux des journaux Windows.

Chainsaw charge 3732 règles et remonte 314 détections, dont 240 de bruit (installations de paquets AppX légitimes). Les détections pertinentes, dans l'ordre chronologique (05/11/2026) :

HeureEvent IDActivitéRègles déclenchées
09:14:261mshta.exe lance powershell.exe -nop -w hidden -encSuspicious MSHTA Child Process, Suspicious PowerShell Parent Process, Suspicious Encoded PowerShell Command Line, Suspicious Execution of Powershell with Base64, PowerShell Base64 Encoded FromBase64String Cmdlet
09:14:2711PowerShell écrit FacturePro_Update.exe dans DownloadsPotential Binary Or Script Dropper Via PowerShell
09:14:551whoami lancé par FacturePro_Update.exeWhoami Utility Execution, Local Accounts Discovery
09:15:11 → 09:16:061net user, net localgroup, net localgroup administratorsLocal Accounts Discovery, Suspicious Group And Account Reconnaissance Activity Using Net.EXE
09:15:381ipconfigSuspicious Network Command
09:15:491systeminfoSuspicious Execution of Systeminfo
09:16:181tasklistSuspicious Tasklist Discovery Command
09:17:2211cmd.exe copie le binaire dans AppData\Roaming\Microsoft\Windows\Creation of an Executable by an Executable
09:17:311 / 13reg.exe crée la clé HKCU\...\CurrentVersion\Run\FactureUpdatePotential Persistence Attempt Via Run Keys Using Reg.EXE, New RUN Key Pointing to Suspicious Folder

Un seul événement (09:14:26) déclenche à lui seul cinq règles : c'est le point d'entrée. La suite retrace l'intrusion complète : dépôt de la charge, découverte du poste, puis persistance par clé Run.

Sortie de chainsaw hunt sur l’événement 09:14:26
PowerShell
.\chainsaw.exe search -e "Downloads" -i -t "Event.System.EventID: =1" "C:\Users\paalkia\Documents\Hexagone_CTF\PANTHERE-EVD-02\evtx\Microsoft-Windows-Sysmon%4Operational.evtx"
Sortie de chainsaw search
Found 17 hits

Une recherche brute de Downloads sur les 190 journaux renvoie 578 résultats.

On restreint au journal Sysmon (-e : chaîne recherchée, -i : insensible à la casse, -t : filtre sur l'Event ID 1). Il reste 17 événements, tous liés à l'intrusion : chaque processus lancé par la charge hérite de son répertoire courant, Downloads.

HeureProcessusLigne de commande
09:14:25mshta.exemshta.exe "C:\Users\j.martin\Downloads\Facture_2026_impayee.hta"
09:14:26powershell.exepowershell.exe -nop -w hidden -enc JABFAHIA...
09:14:28FacturePro_Update.exeexécuté depuis Downloads
09:14:55whoami.exewhoami /all
09:15:11net.exenet user
09:15:20net.exenet localgroup
09:15:29net.exenet ipconfig /all (commande invalide)
09:15:38ipconfig.exeipconfig /all
09:15:49systeminfo.exesysteminfo
09:16:06net.exenet localgroup administrators
09:16:18tasklist.exetasklist /v
09:17:21cmd.execopy ...\Downloads\FacturePro_Update.exe ...\AppData\Roaming\Microsoft\Windows\
09:17:31reg.exereg add HKCU\...\CurrentVersion\Run /v FactureUpdate ... \AppData\Roaming\Microsoft\Windows\FacturePro_Update.exe

Les 4 événements net1.exe restants sont les sous-processus lancés automatiquement par net.exe.

La chaîne se lit en trois temps : accès initial (HTA → PowerShell → charge), découverte du poste (utilisateurs, groupes, réseau, système, processus), puis persistance (copie du binaire dans AppData et clé Run FactureUpdate). La commande invalide net ipconfig /all, corrigée 9 secondes plus tard, trahit un opérateur humain aux commandes.

ParentCommandLine de FacturePro_Update.exe dans chainsaw

Étape 3 : décoder la commande PowerShell

From Base64 puis Decode text UTF-16LE dans CyberChef

L'option -enc de PowerShell attend un script encodé en base64, mais pas à partir d'UTF-8 : à partir d'UTF-16LE, l'encodage interne de Windows (2 octets par caractère). Un simple From Base64 donne un texte entrecoupé d'octets nuls ($.E.r.r.o.r...). Il faut ajouter Decode text en UTF-16LE pour obtenir le script lisible.

  • $ErrorActionPreference='SilentlyContinue' : masque les erreurs, rien ne s'affiche à l'utilisateur ;
  • $cid=... : décode un bloc base64 et le stocke, sans jamais l'utiliser ensuite ;
  • $w=New-Object Net.WebClient puis DownloadFile(...) : télécharge FacturePro_Update.exe depuis le serveur de l'attaquant (10.10.10.100:8080) dans le dossier Téléchargements ;
  • Start-Process $p : exécute la charge.

Le script est un stager : son seul rôle est de télécharger et lancer la vraie charge. La variable $cid, chargée mais jamais utilisée, n'a aucune utilité pour l'attaque : c'est la donnée dissimulée que l'énoncé demande de récupérer.

Étape 4 : déchiffrer $cid

Bloc $cid décodé en base64

Le bloc base64 décodé donne 35 octets illisibles : la donnée est protégée par une seconde couche. L'opération la plus courante dans un stager est le XOR avec une clé courte, une technique simple, rapide et suffisante pour échapper à une recherche de chaîne.

XOR Brute Force dans CyberChef avec le crib RWX

Le format de flag RWX{...} est connu, on l'utilise comme clair connu (crib). XOR Brute Force teste les 256 clés possibles d'un octet et n'affiche que celles dont le résultat contient RWX{. Une seule clé ressort : 0x2a.

Le principe : avec un XOR, chiffré XOR clé = clair, donc chiffré XOR clair = clé. Le premier octet chiffré est 0x78, le premier caractère attendu est R (0x52) : 0x78 XOR 0x52 = 0x2a. Connaître un seul octet du clair suffit à retrouver une clé d'un octet.

07Flag

RWX{d30bfusc4t3d_p0wersh3ll_st4g3r}

08Pistes de détection

  • mshta.exe qui s'exécute, surtout sur un fichier .hta ouvert depuis Downloads ou une pièce jointe.
  • PowerShell lancé en fenêtre cachée avec une commande encodée.
  • Un exécutable sans éditeur ni signature lancé depuis le profil utilisateur.
  • Une rafale de commandes de reconnaissance (whoami, net, systeminfo, tasklist) en quelques minutes sur un poste bureautique.
  • Une nouvelle clé Run qui pointe vers AppData.
  • MITRE ATT&CK : T1566.001, T1218.005, T1059.001.

09Note du concepteur

Objectif pédagogique

Reconstituer une chaîne d'exécution à partir des seuls journaux Sysmon, sans les journaux PowerShell qui donneraient le script en clair. Il faut d'abord trouver le bon journal parmi 190, puis suivre la filiation des processus, de la pièce jointe jusqu'à la persistance. Le challenge se termine par une désobfuscation en deux couches : base64 en UTF-16LE, puis XOR à clé d'un octet retrouvée par clair connu.

Anti-triche

Le flag n'est jamais en clair (base64 puis XOR), donc non greppable.