Leçon 5.4 · Windows pour analystes· 35 min
Mutex, événements et communication inter-processus
Mutex, événements, sections et pipes nommés comme preuves sur l’hôte : où ils vivent, comment les observer, les extraire et en tirer des détections.
Objectifs
- Nommer les types d’objets noyau que les malwares créent avec un nom et expliquer les espaces de noms Global\, Local\ et par session
- Expliquer pourquoi un mutex d’instance unique est un IOC solide, quand la vaccination par mutex fonctionne et quand elle échoue
- Observer les objets nommés avec System Informer, Process Explorer, WinObj et Sysmon, et savoir quels outils ne les voient pas
- Retrouver statiquement le nom d’un mutex à partir des chaînes UTF-16 et des arguments de l’appel à CreateMutex
- Transformer les objets nommés en entrées d’IOC, en chaînes YARA et en requêtes de chasse aux pipes nommés
Dans Processus, threads et DLL, vous avez lu la table des handles d’un processus et croisé au passage un type d’entrée : un Mutant doté d’un nom. De nombreux échantillons créent des objets noyau nommés par leur auteur — un mutex pour qu’une seule copie s’exécute, un événement qui indique à un thread injecté quand démarrer, un pipe par lequel un processus auxiliaire parle à son parent. Ces noms sont choisis par un humain, changent rarement d’un build à l’autre, et aucun programme légitime n’a de raison de choisir le même : ce sont parmi les IOC (indicateurs de compromission) de haute confiance les moins coûteux qu’un échantillon vous livre.
Objets noyau nommés
Tout objet noyau est atteint par un handle. Certains types d’objets peuvent aussi recevoir un nom à leur création, de sorte qu’un second processus puisse ouvrir le même objet par son nom au lieu d’hériter d’un handle ou de le dupliquer.
| Objet | Nom du type noyau | Créé avec | Usage par les malwares |
|---|---|---|---|
| Mutex | Mutant | CreateMutexA/W, CreateMutexExW | Marqueur d’instance unique ; sérialisation de l’accès à un fichier ou à un journal partagé |
| Événement | Event | CreateEventA/W | Signalisation entre composants : « la charge utile est mappée, démarre », « arrête-toi maintenant » |
| Sémaphore | Semaphore | CreateSemaphoreA/W | Limitation du nombre de workers simultanés ; parfois utilisé comme marqueur d’instance à la place d’un mutex |
| Section | Section | CreateFileMappingA/W | Mémoire partagée entre processus, y compris pour préparer du code à injecter |
| Pipe nommé | File (sur le pilote NPFS) | CreateNamedPipeA/W, ouvert avec CreateFileW | Canal bidirectionnel entre processus, en local ou via SMB |
| Mailslot | File (sur le pilote MSFS) | CreateMailslotA/W | Datagrammes unidirectionnels, en local ou en diffusion sur le domaine ; rare aujourd’hui |
Un mutex a au plus un thread propriétaire, et un thread qui demande un mutex
déjà détenu attend qu’il soit libéré. Pour la plupart des malwares (logiciels malveillants), la propriété
importe peu : ce qui compte, c’est que le nom existe. CreateMutexW renvoie un
handle, qu’il ait créé un nouvel objet ou ouvert un objet existant, et dans le
second cas GetLastError renvoie ERROR_ALREADY_EXISTS (183, 0xB7). Ce seul
bit d’information constitue toute la vérification d’instance unique.
L’espace de noms des objets
Les objets nommés vivent dans une arborescence gérée par le gestionnaire d’objets, à la manière d’un système de fichiers. Les répertoires qui nous intéressent ici :
\BaseNamedObjects global namespace ("Global\" prefix; session 0's local names)
\Sessions\1\BaseNamedObjects local namespace for interactive session 1 ("Local\" prefix)
\Sessions\1\AppContainerNamedObjects\<SID> objects created inside an AppContainer sandbox
\Device\NamedPipe\ named pipes, opened as \\.\pipe\<name>
\Device\Mailslot\ mailslots, opened as \\.\mailslot\<name>Le préfixe Win32 détermine où un nom aboutit :
Global\nameest créé dans\BaseNamedObjectset reste visible depuis toutes les sessions. Un échantillon qui veut une seule instance par machine, et non par utilisateur connecté, l’utilise. Créer un file mapping à cet endroit depuis une autre session que la 0 exigeSeCreateGlobalPrivilege; ce n’est pas le cas des mutex et des événements.Local\name, ou un nom sans préfixe, va dans le répertoire de la session de l’appelant. Deux utilisateurs connectés en même temps obtiennent chacun leur propre copie — un mutex par session n’empêche donc pas une seconde infection dans une autre session.- Les services s’exécutent dans la session 0, où l’espace de noms local
est
\BaseNamedObjects. Le même nomLocal\se résout donc vers un chemin complet différent selon que l’échantillon tourne en tant que service ou qu’un utilisateur double-clique dessus. Consignez le nom que le code transmet, et notez le chemin complet que vous avez observé.
Les pipes nommés et les mailslots échappent à ce schéma : ce sont des fichiers
sur des pilotes de système de fichiers dédiés, avec un espace de noms unique pour
toute la machine. Un nom de pipe est joignable depuis d’autres hôtes sous la
forme \\host\pipe\name via SMB, à travers le partage IPC$, ce qui rend les
pipes intéressants pour le mouvement latéral.
Pourquoi le nom du mutex est un si bon IOC
Un auteur choisit un nom de mutex une fois pour toutes et le réutilise, car le
changer laisserait deux versions tourner côte à côte et se disputer les mêmes
fichiers et les mêmes ports. Des noms comme Local\LabDemoMutex n’apparaissent
pas par hasard : l’indicateur combine donc forte spécificité et faible
renouvellement. Un hash de fichier meurt à la recompilation suivante ; un nom
de mutex survit souvent au repacking, au rechiffrement et à une nouvelle
infrastructure de C2, parce qu’il vit dans le code qui s’exécute après toutes
ces couches.
La même propriété permet la vaccination : créez vous-même le mutex sur les postes, avant l’arrivée de l’échantillon, et un échantillon qui le vérifie en conclura qu’il tourne déjà et se terminera. Cette méthode a servi lors d’incidents réels comme solution d’attente pendant le déploiement d’une vraie détection. Ses limites sont strictes :
- Elle ne fonctionne que pour le nom exact et l’espace de noms exact. Un
vaccin
Local\ne protège pas les autres sessions ; un échantillonGlobal\ignore un vaccin placé dans\Sessions\1\BaseNamedObjects. - Elle ne fonctionne que contre les échantillons qui se terminent (ou se
bloquent) sur
ERROR_ALREADY_EXISTS; certains ignorent le résultat. - Le vaccin doit être maintenu ouvert par un processus en cours d’exécution ; il disparaît au redémarrage jusqu’à ce que ce processus soit relancé.
- Elle ne peut rien contre les noms aléatoires ou dérivés de l’hôte.
Ce dernier point est la principale faiblesse de toute cette catégorie d’indicateurs. Les auteurs qui savent que les défenseurs collectent les mutex dérivent le nom à l’exécution : un hash du nom de l’ordinateur, du numéro de série du volume ou du SID de l’utilisateur, mis en forme comme un GUID ou une chaîne hexadécimale. Le résultat est stable sur une machine (la vérification d’instance unique fonctionne donc toujours) et différent sur toutes les autres. Pour ces familles, le nom littéral n’est un IOC d’hôte que pour cet incident ; l’indicateur durable, c’est l’algorithme — la chaîne de format, le hash, les entrées —, que vous retrouvez par rétro-ingénierie et pouvez reproduire dans un script de détection.
Astuce : Avant de signaler un nom de mutex comme IOC de famille, vérifiez-le sur deux exécutions dans des VM portant des noms différents. S’il change, signalez le motif (par exemple « 32 chiffres hexadécimaux dérivés du numéro de série du volume ») plutôt que la valeur.
Observer les objets nommés à l’exécution
Les mutex et les événements ne laissent ni fichier ni valeur de registre, si bien que les outils de Surveillance comportementale les voient de manière inégale.
| Outil | Mutex / événements / sections | Pipes nommés |
|---|---|---|
| System Informer — onglet Handles | Oui, tant que le handle est ouvert, avec le chemin complet de l’objet | Oui, sous forme de handles File sur \Device\NamedPipe\… |
Process Explorer — vue des handles (Ctrl+H), Find (Ctrl+F) | Oui ; Find Handle or DLL recherche un nom dans tous les processus | Oui |
| WinObj | Oui — parcourt l’espace de noms lui-même, indépendamment de tout processus | Pas la liste des pipes elle-même |
| Handle (CLI Sysinternals) | handle -a -p <pid>, ou handle -a <name> pour rechercher | Oui |
| Sysmon | Aucun événement pour la création de mutex ou d’événements | Event 17 (pipe créé), Event 18 (pipe connecté) |
| Process Monitor | Non enregistré | CreateFile, ReadFile, WriteFile sur le chemin du pipe |
| Sandboxes (bacs à sable ; CAPE et similaires) | Généralement listés dans le résumé comportemental, grâce aux hooks d’API | Généralement listés |
Deux conséquences en découlent. D’abord, les vues en direct ne montrent que ce
qui est encore ouvert : un échantillon qui constate que son mutex existe déjà et
se termine ne laisse rien à Process Explorer. Le traçage à base de hooks — un
rapport de sandbox, un moniteur d’API ou un point d’arrêt sur CreateMutexW dans
un débogueur — capte chaque tentative, y compris celles qui échouent. Ensuite,
la télémétrie de production contient rarement des mutex. Sysmon n’a pas
d’événement pour les mutex, et la plupart des EDR ne remontent pas la création
d’objets. Sur un hôte en production, on les chasse par énumération : une session
de réponse à incident exécutant handle.exe, un artefact Velociraptor qui parcourt
les répertoires d’objets, ou une image mémoire analysée après coup. Les pipes
nommés font exception, car Sysmon et la plupart des EDR les journalisent.
Trouver le nom statiquement
Un échantillon qui utilise un nom fixe doit le transporter quelque part dans le binaire. Où chercher :
- Les imports.
CreateMutexA/W,OpenMutexW,CreateEventW,CreateNamedPipeWouCreateFileMappingWdans la table des imports (voir Lire les capacités à partir des imports) indiquent qu’un objet nommé est probable. Associé à unGetLastErrorpeu après, il s’agit presque certainement d’une vérification d’instance. - Les chaînes larges. Les API
Wprennent des chaînes UTF-16LE, qu’une exécution par défaut destringsmanque complètement. Cherchez avecstrings -el(ou FLOSS, présenté dans Chaînes et chaînes obfusquées). - Le site d’appel. En x64, le nom est le troisième argument de
CreateMutexW(lpName) et arrive donc dansr8; pourOpenMutexW, c’est aussi le troisième ; pourCreateEventW, c’est le quatrième, dansr9. Trouvez l’appel via l’entrée de l’IAT, puis lisez leleaqui charge le registre d’argument (voir les conventions d’appel). - Les noms cachés. Quand aucune chaîne n’apparaît, le nom est construit à l’exécution — stack strings, blob chiffré par XOR, ou chaîne de format alimentée par des données de l’hôte. Le site d’appel vous donne quand même la réponse : posez un point d’arrêt sur l’API et lisez l’argument, une méthode que la leçon Déboguer un malware avec x64dbg couvre en détail.
Les instructions qui suivent immédiatement l’appel méritent aussi d’être lues.
Une comparaison du résultat de GetLastError avec 0xB7, suivie d’un saut vers
un chemin de sortie, est la vérification d’instance unique dans sa forme la plus
pure — et l’endroit exact qu’un analyste patche pour laisser tourner une seconde
copie sous un débogueur.
Les pipes nommés et les autres IPC comme indicateurs
Un échantillon qui crée un pipe vous dit généralement qu’il est plus qu’un seul processus : un loader et sa charge utile, un implant et une tâche de post-exploitation qu’il a lancée, ou un service et l’opérateur distant qui le pilote via SMB. Les pipes sont donc un indice structurel autant qu’un IOC.
Ce que les défenseurs journalisent et chassent couramment :
- Les Events Sysmon 17 et 18. L’Event 17 enregistre le processus qui a créé
un pipe ainsi que son nom ; l’Event 18 enregistre qui s’y est connecté. La
chasse commence par les noms de pipes qui correspondent aux valeurs par défaut
d’outils connus — outils d’administration à distance comme PsExec
(
\PSEXESVC) et motifs par défaut publiés des frameworks de red team courants —, puis passe aux pipes créés par des processus qui n’ont rien à faire à servir de l’IPC, commerundll32.exeou un binaire dans%TEMP%. - L’accès distant à
IPC$. L’événement de sécurité Windows 5145 (audit détaillé des partages de fichiers) montre un client distant ouvrant un nom de pipe viaIPC$, ce qui est la manière dont le mouvement latéral via SMB et les implants pair-à-pair apparaissent sur l’hôte qui les reçoit. - La forme plutôt que la valeur. Les valeurs par défaut des frameworks sont configurables, si bien que les chasses matures recherchent des motifs : noms d’apparence aléatoire sous un préfixe fixe, pipes qui n’existent que quelques secondes autour d’une création de processus, processus unique créant de nombreux pipes aux noms similaires.
Les sections et les événements sont moins visibles dans les journaux. Une section nommée est de la mémoire partagée, et une vue exécutable de celle-ci dans un autre processus est une primitive d’injection classique (voir section mapping injection et la future leçon Comprendre l’injection de processus). Un événement nommé qu’un processus attend explique pourquoi un composant injecté reste inactif.
Rapport et contenu de détection
Consignez chaque objet nommé comme une entrée d’IOC, avec assez de contexte pour que quelqu’un d’autre puisse l’utiliser correctement :
| Champ | Exemple |
|---|---|
| Type | Mutex |
| Valeur telle que transmise à l’API | Local\LabDemoMutex |
| Chemin complet observé | \Sessions\1\BaseNamedObjects\LabDemoMutex |
| Stabilité | Chaîne statique dans .rdata ; identique d’une exécution et d’un hôte à l’autre |
| Comportement en cas de collision | Se termine si ERROR_ALREADY_EXISTS |
| Encodage dans le fichier | UTF-16LE |
Les mêmes faits alimentent trois types de contenu de détection. Pour
YARA (voir
Écrire vos premières règles YARA), faites
correspondre le nom en wide — et aussi en ascii si vous n’êtes pas sûr de
l’API qu’utilise la famille :
rule LabDemo_Mutex_Name
{
meta:
description = "Lab sample: LabDemoMutex single-instance marker"
strings:
$mutex = "LabDemoMutex" wide ascii
condition:
uint16(0) == 0x5A4D and $mutex
}Laissez le préfixe Local\ ou Global\ hors de la chaîne : il ne fait pas partie
du nom de l’objet et certaines variantes le changent. Pour le contenu côté
endpoint, un pipe nommé devient une requête sur l’Event Sysmon 17 ; en voici une
ébauche en syntaxe de type KQL :
Sysmon
| where EventID in (17, 18)
| where PipeName has_any ("\\PSEXESVC", "\\LabDemoPipe")
or (PipeName matches regex @"^\\[0-9a-f]{8}$" and Image endswith @"\rundll32.exe")
| project TimeGenerated, Computer, EventID, PipeName, Image, ProcessGuidPour les mutex, fournissez au SOC une vérification en réponse à incident plutôt
qu’une règle de flux : un script qui tente OpenMutexW sur le nom, ou un balayage
avec handle.exe -a LabDemoMutex, et précisez-le dans le
rapport de triage.
Lab : un mutex d’instance unique, observé et extrait
Ce lab utilise un programme inoffensif que vous compilez vous-même. Il crée
Local\LabDemoMutex, indique si celui-ci existait déjà, le conserve dix secondes
puis se termine. Les étapes statiques fonctionnent sur toute machine disposant de
mingw-w64 et de Python ; les étapes d’exécution utilisent Wine si vous l’avez,
ainsi que votre VM d’analyse Windows issue de
Construire un laboratoire d’analyse sûr.
-
Compilez le programme.
c // mutexdemo.c — single-instance marker with a named mutex (harmless) #include <windows.h> #include <stdio.h> int main(void) { HANDLE m = CreateMutexW(NULL, FALSE, L"Local\\LabDemoMutex"); if (m == NULL) { printf("CreateMutexW failed: %lu\n", GetLastError()); return 1; } if (GetLastError() == ERROR_ALREADY_EXISTS) { printf("pid %lu: mutex already exists, another copy is running - exiting\n", GetCurrentProcessId()); CloseHandle(m); return 0; } printf("pid %lu: created Local\\LabDemoMutex, holding it for 10 seconds\n", GetCurrentProcessId()); Sleep(10000); CloseHandle(m); printf("pid %lu: released mutex, exiting\n", GetCurrentProcessId()); return 0; }bash x86_64-w64-mingw32-gcc -O1 -s -o mutexdemo.exe mutexdemo.c file mutexdemo.exe shasum -a 256 mutexdemo.exeSur la machine de build utilisée pour cette leçon (GCC 15.2 ; votre hash sera différent) :
text mutexdemo.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows ea6cec36447c9069c1c207f3dd1a204f1bc8bdac9acc871e011d3fd34a2510e0 mutexdemo.exe -
Montrez le comportement d’instance unique. Sous Wine, lancez une copie en arrière-plan et une seconde quelques secondes plus tard :
bash export WINEDEBUG=-all wine mutexdemo.exe > run1.txt 2>&1 & sleep 4; wine mutexdemo.exe > run2.txt 2>&1 sleep 9; cat run1.txt run2.txttext pid 32: created Local\LabDemoMutex, holding it for 10 seconds pid 32: released mutex, exiting pid 200: mutex already exists, another copy is running - exitingWine n’est pas Windows ; il montre la logique, et les étapes dans la VM montrent le véritable espace de noms.
-
Lisez les imports et les chaînes.
bash x86_64-w64-mingw32-objdump -p mutexdemo.exe | grep -iE 'Mutex|GetLastError|CloseHandle' strings -n 8 mutexdemo.exe | grep -i mutex x86_64-w64-mingw32-strings -el -n 6 mutexdemo.exetext 00008270 <none> 0097 CloseHandle 00008278 <none> 00ef CreateMutexW 00008298 <none> 0288 GetLastError pid %lu: created Local\LabDemoMutex, holding it for 10 seconds CreateMutexW Local\LabDemoMutexLa recherche ASCII ne trouve le nom qu’à l’intérieur d’une chaîne de format de
printf— un accident propre à ce programme. Le nom réellement transmis à l’API n’est trouvé que par la recherche UTF-16LE (-el). Dans un dump hexadécimal, il ressemble à ceci :text 00002200: 4c00 6f00 6300 6100 6c00 5c00 4c00 6100 L.o.c.a.l.\.L.a. 00002210: 6200 4400 6500 6d00 6f00 4d00 7500 7400 b.D.e.m.o.M.u.t. 00002220: 6500 7800 0000 4372 6561 7465 4d75 7465 e.x...CreateMute -
Localisez l’appel avec Capstone. Dans un environnement virtuel avec
pip install pefile capstone, enregistrez ce script sousfind_mutex.py:python # find_mutex.py — locate a UTF-16LE mutex name and the CreateMutexW call site import sys, pefile from capstone import Cs, CS_ARCH_X86, CS_MODE_64 pe = pefile.PE(sys.argv[1]) base = pe.OPTIONAL_HEADER.ImageBase data = pe.get_memory_mapped_image() name = "Local\\LabDemoMutex".encode("utf-16le") str_rva = data.find(name) print(f"UTF-16LE name at VA {base + str_rva:#x}") iat = {imp.name.decode(): imp.address for entry in pe.DIRECTORY_ENTRY_IMPORT for imp in entry.imports if imp.name} target = iat["CreateMutexW"] print(f"IAT slot for CreateMutexW at {target:#x}") text = next(s for s in pe.sections if s.Name.startswith(b".text")) md = Cs(CS_ARCH_X86, CS_MODE_64) insns = list(md.disasm(text.get_data(), base + text.VirtualAddress)) def rip_target(i): # resolve [rip + disp] operands to an absolute address if "rip" not in i.op_str: return None disp = int(i.op_str.split("rip")[1].strip(" +]-").split("]")[0], 16) sign = -1 if "rip -" in i.op_str else 1 return i.address + i.size + sign * disp # the call may go through a small "jmp [rip+x]" thunk; collect thunks first thunks = {i.address for i in insns if i.mnemonic == "jmp" and rip_target(i) == target} for idx, i in enumerate(insns): t = rip_target(i) hit_call = i.mnemonic == "call" and (t == target or (i.op_str.startswith("0x") and int(i.op_str, 16) in thunks)) if hit_call: for j in insns[max(0, idx - 6): idx + 7]: note = "" if rip_target(j) == base + str_rva: note = " ; -> L\"Local\\LabDemoMutex\"" if j is i: note = " ; CreateMutexW" print(f" {j.address:#x}: {j.mnemonic:6} {j.op_str}{note}")bash python find_mutex.py mutexdemo.exetext UTF-16LE name at VA 0x140004000 IAT slot for CreateMutexW at 0x140008278 0x140001491: push rbx 0x140001492: sub rsp, 0x28 0x140001496: call 0x140001620 0x14000149b: lea r8, [rip + 0x2b5e] ; -> L"Local\LabDemoMutex" 0x1400014a2: mov edx, 0 0x1400014a7: mov ecx, 0 0x1400014ac: call qword ptr [rip + 0x6dc6] ; CreateMutexW 0x1400014b2: mov rbx, rax 0x1400014b5: test rax, rax 0x1400014b8: je 0x14000150e 0x1400014ba: call qword ptr [rip + 0x6dd8] 0x1400014c0: cmp eax, 0xb7 0x1400014c5: je 0x140001529Lisez-le comme le dicte la convention d’appel :
ecx = 0correspond àlpMutexAttributes = NULL,edx = 0àbInitialOwner = FALSE, etr8pointe vers le nom. Le second appel indirect se résout en0x140008298, l’entrée deGetLastErrorvue à l’étape 3, etcmp eax, 0xb7est le test deERROR_ALREADY_EXISTS. Lejeà0x1400014c5est le branchement qu’un utilisateur de débogueur inverserait pour laisser tourner une seconde copie. -
Vérifiez votre chaîne YARA. Compilez la règle de la section précédente et exécutez-la sur
mutexdemo.exe(avecyaraouyara-python). Elle correspond deux fois : le nom UTF-16LE à l’offset de fichier0x220cet le texte ASCII à l’intérieur de la chaîne de format à0x229f. Décidez à laquelle des deux vous feriez confiance dans une règle visant une famille qui n’affiche pas le nom de son mutex. -
Observez-le sous Windows. Dans la VM d’analyse, lancez
mutexdemo.exedepuis une invite de commandes et, dans les dix secondes, ouvrez System Informer →mutexdemo.exe→ Handles. Trouvez le handle de type Mutant nommé\Sessions\<n>\BaseNamedObjects\LabDemoMutex, où<n>est votre numéro de session. Modifiez le source pour conserver le mutex plus longtemps s’il vous faut plus de temps. -
Cherchez depuis l’autre côté. Dans Process Explorer, appuyez sur
Ctrl+Fet recherchezLabDemoMutex; le résultat nomme le processus propriétaire. Depuis une invite élevée,handle.exe -a LabDemoMutexfait la même chose en ligne de commande. -
Parcourez l’espace de noms. Ouvrez WinObj en tant qu’administrateur et allez dans
\Sessions\<n>\BaseNamedObjects. TrouvezLabDemoMutexde typeMutant. Une fois le programme terminé, actualisez : l’objet a disparu, car son dernier handle a été fermé. -
Testez la frontière de l’espace de noms. Connectez un second utilisateur avec le changement rapide d’utilisateur pour que deux sessions existent. Avec le build
Local\, lancez une copie dans chaque session dans l’intervalle de dix secondes et constatez que les deux créent le mutex. Remplacez le nom parGlobal\LabDemoMutex, recompilez et recommencez. Si la seconde copie afficheCreateMutexW failed: 5, l’objet existe mais sa sécurité par défaut, définie par le jeton de l’autre utilisateur, refuse l’accès. Réfléchissez à ce que chaque résultat signifie pour un vaccin déployé par un seul compte.
Questions : Quelle recherche de chaînes a trouvé le nom qui compte, et
pourquoi la simple recherche ASCII vous a-t-elle induit en erreur ? Où l’objet
apparaîtrait-il dans WinObj si le programme s’exécutait en tant que service ? Si
le nom était construit à partir du nom de l’ordinateur avec wsprintfW, que
signaleriez-vous comme IOC et comment un SOC le vérifierait-il sur un hôte en
production ? Lesquels des outils de cette leçon n’auraient rien vu si la seconde
copie avait été la seule que vous observiez ?
À retenir
- Les mutex, événements, sémaphores et sections peuvent être nommés pour que des
processus sans lien retrouvent le même objet ; le préfixe (
Global\ouLocal\) et la session déterminent où le nom aboutit dans l’espace de noms des objets. - Un nom de mutex fixe est spécifique et durable, ce qui en fait un IOC solide et parfois un vaccin — mais seulement pour le nom, l’espace de noms et le comportement de sortie exacts, et jamais pour des noms aléatoires ou dérivés de l’hôte.
- Les vues des handles en direct et WinObj ne voient les objets que tant qu’un handle est ouvert ; Sysmon enregistre les pipes nommés (Events 17 et 18) mais pas les mutex, si bien que la chasse aux mutex repose sur les rapports de sandbox et l’énumération en direct.
- Statiquement, cherchez les chaînes larges et lisez le site d’appel de
CreateMutexW: le nom est dansr8, et uncmp eax, 0xb7aprèsGetLastErrorest la vérification d’instance unique. - Les pipes nommés signalent un outillage multi-processus et du mouvement latéral ; chassez sur les valeurs par défaut connues, les créateurs suspects et les motifs de noms plutôt que sur des valeurs isolées.