Mémoire et données volatiles · Leçon 3 sur 4
Connexions réseau, handles et code injecté
13 min de lecture
Une liste de processus vous indique ce qui était en cours d’exécution. Cette leçon répond aux questions suivantes : avec quoi chaque processus communiquait sur le réseau, quels fichiers, clés de registre et mutex il maintenait ouverts, et si du code s’exécutait en son sein sans qu’aucun fichier sur disque ne l’explique. Ces trois vues permettent à l’analyse mémoire de révéler des activités qu’une image disque ne peut pas montrer, comme un implant sans fichier au sein d’un processus légitime. Les noms des plugins de Volatility 3 servent d’exemples ; la leçon 5.2 a traité de l’exécution de Volatility 3 et des plugins de processus, ces éléments ne sont donc pas repris ici.
Artefacts réseau sous Windows
Windows conserve une structure noyau par point de terminaison TCP, socket d’écoute TCP et point de terminaison UDP, allouée par le pilote TCP/IP (tcpip.sys) dans la mémoire du pool noyau. Deux plugins les lisent de manières différentes :
- windows.netscan recherche ces structures en mémoire à partir de leurs signatures de pool (par exemple, la balise
TcpEpour les points de terminaison TCP). Comme il trouve les structures par reconnaissance de motifs plutôt qu’en parcourant des listes, il récupère également les connexions fermées dont les structures ont été libérées, mais pas encore écrasées. Ses colonnes sont Offset, Proto, LocalAddr, LocalPort, ForeignAddr, ForeignPort, State, PID, Owner et Created. - windows.netstat parcourt les listes de points de terminaison actifs du pilote, comme
netstat.exesur un système en cours de fonctionnement. Il ne montre que ce qui était actif et dépend des informations de symboles detcpip.sys; il peut donc échouer sur certaines versions de compilation.
Une entrée présente dans netscan mais absente de netstat correspond soit à une ancienne connexion fermée, soit à une structure retirée des listes pour la dissimuler. Déterminez lequel de ces cas s’applique à partir de l’état et de l’horodatage. Proto vaut TCPv4, TCPv6, UDPv4 ou UDPv6. UDP étant sans connexion, les lignes UDP n’ont pas d’état et généralement pas d’adresse distante. Created correspond à l’heure de création du socket, affichée en UTC. La recherche peut également renvoyer des fragments de mémoire libérée contenant des ports ou des PID impossibles ; ignorez les lignes incohérentes.
| État | Signification | Ce qu’il suggère |
|---|---|---|
| LISTENING | Socket en attente de connexions entrantes | Un service ou une porte dérobée acceptant des connexions sur LocalPort |
| SYN_SENT | Tentative de connexion sortante sans réponse à ce stade | Des tentatives de contact périodiques avec un serveur indisponible ou bloqué |
| ESTABLISHED | Connexion ouverte, les données peuvent circuler dans les deux sens | Une communication active au moment de la capture |
| CLOSE_WAIT | Le côté distant a fermé la connexion ; l’application locale ne l’a pas fait | Le correspondant a interrompu la session ; le processus conserve le socket |
| TIME_WAIT | Le côté local a fermé la connexion en premier ; le système conserve brièvement le tuple | Une connexion récente et terminée ; le propriétaire est souvent absent |
D’une connexion à une ligne de commande
La colonne PID relie un socket à un processus. Confirmez le PID dans windows.pslist ou windows.pstree et vérifiez que l’heure de création du processus est antérieure à la valeur Created du socket, car les PID sont réutilisés après la fin d’un processus. Exécutez ensuite windows.cmdline pour ce PID : la ligne de commande vous indique généralement pourquoi le processus communiquait sur le réseau, ou montre qu’il n’a aucune raison valable de le faire.
Sockets et fichiers ouverts sous Linux
Dans l’examen pratique CFX, les questions sur la mémoire utilisent une capture Linux. Sous Linux, linux.sockstat répertorie tous les sockets détenus par chaque processus, avec le PID, le descripteur de fichier, la famille (AF_INET, AF_INET6, AF_UNIX, AF_NETLINK), le protocole, les adresses et ports source et destination, ainsi que l’état TCP. Filtrez sur AF_INET et AF_INET6 pour supprimer les nombreux sockets de domaine UNIX et netlink. Volatility 3 ne possède pas de plugin linux.netstat ; linux.sockstat remplit ce rôle. linux.lsof répertorie les descripteurs de fichiers ouverts de chaque processus : les fichiers ordinaires avec leurs chemins, et les sockets sous la forme socket:[inode]. Ensemble, ils répondent à la question « quel processus détenait cette connexion et quels fichiers avait-il ouverts ? »
Handles et fichiers en cache
Un handle est une référence détenue par un processus vers un objet noyau. windows.handles, généralement exécuté avec --pid, répertorie les champs Type, GrantedAccess et Name de chaque handle. Les types utiles sont File (fichiers et périphériques ouverts), Key (clés de registre), Mutant (un mutex), Process et Thread (handles vers d’autres processus et threads, nécessaires à un injecteur), Event et Section (mémoire partagée). De nombreuses familles de logiciels malveillants créent un mutex nommé afin qu’une seule copie s’exécute, et ce nom constitue un indicateur publié. Un handle Key ouvert montre un accès à une clé, et non qu’une valeur y a été écrite.
windows.filescan recherche les structures FILE_OBJECT et répertorie leurs chemins, y compris ceux de fichiers qui ne sont plus ouverts. windows.dumpfiles récupère le contenu en cache d’un fichier depuis sa section de données (le cache de fichiers), sa section d’image (un exécutable mappé pour être exécuté) ou la structure shared cache map. Le résultat est souvent incomplet : les pages qui n’étaient pas résidentes sont absentes ou remplies de zéros. Un exécutable récupéré depuis sa section d’image présente la même disposition qu’en mémoire ; son empreinte ne correspondra donc pas à celle du fichier sur disque. Sous Linux, linux.lsof fournit la liste équivalente des fichiers ouverts.
Injection de code et arbre VAD
L’injection de code consiste à placer du code dans un autre processus et à l’y exécuter, afin qu’il hérite du nom, des privilèges et de la confiance accordée à ce processus. Trois formes courantes :
- Injection classique par thread distant : ouvrir le processus cible, y allouer de la mémoire (
VirtualAllocEx), écrire du code (WriteProcessMemory) et le lancer (CreateRemoteThread). - Process hollowing : démarrer un exécutable légitime à l’état suspendu, retirer le mappage de son image, écrire une image malveillante à sa place, rediriger l’adresse de démarrage du thread et reprendre son exécution.
- Chargement réflexif de DLL : une DLL se mappe et se reloge elle-même depuis la mémoire avec son propre chargeur ; le chargeur Windows ne l’enregistre donc jamais dans les listes de modules.
Le noyau décrit l’espace d’adressage de chaque processus à l’aide d’un arbre de descripteurs d’adresses virtuelles (VAD). Chaque nœud VAD couvre une plage et indique s’il s’agit de mémoire privée ou d’un fichier mappé (avec son nom), sa balise (VadS pour les allocations privées typiques), ainsi que la protection demandée lors de l’allocation de la plage. Les images exécutables et les DLL sont mappées depuis des fichiers avec PAGE_EXECUTE_WRITECOPY ; les tas et les piles sont des zones privées PAGE_READWRITE. windows.vadinfo répertorie tous les VAD d’un processus.
Détecter le code injecté avec malfind
windows.malfind signale les régions VAD dont la protection autorise à la fois l’écriture et l’exécution, principalement les régions privées (non adossées à un fichier) PAGE_EXECUTE_READWRITE, et ignore celles dont les pages sont vides ; il signale donc du contenu engagé. Pour chaque résultat, il affiche un vidage hexadécimal et un désassemblage du début de la région. Examinez les premiers octets :
4D 5A(« MZ ») signifie qu’un fichier PE se trouve en mémoire privée, ce que le chargeur Windows ne produit jamais. Désassemblé, un en-tête donne des instructions incohérentes telles quedec ebp; pop edx(32 bits) oupop r10(64 bits).- Des octets qui se désassemblent en code plausible, comme un prologue de fonction ou une séquence call/pop, suggèrent la présence de shellcode.
- Un en-tête mis à zéro masque le « MZ » ; recherchez plus loin
PE\0\0ou « This program cannot be run in DOS mode ».
Deux limites sont importantes. Premièrement, le VAD enregistre la protection d’origine ; du code alloué en RW puis passé en RX avec VirtualProtect n’apparaîtra pas comme RWX. Deuxièmement, des logiciels légitimes produisent des résultats : les compilateurs à la volée (JIT) de l’environnement d’exécution .NET et des moteurs JavaScript écrivent et exécutent du code en mémoire privée, et certains produits de sécurité injectent leur propre code. Confirmez un résultat en extrayant la région (--dump) et en l’analysant avec des règles YARA, soit avec windows.vadyarascan sur les VAD des processus (un PID ou tous), soit avec yarascan sur la mémoire noyau.
Indicateurs de process hollowing
Le process hollowing laisse une incohérence entre ce que le processus prétend être et ce qui est mappé. Le chemin d’image du PEB, affiché par cmdline et dlllist, désigne un exécutable légitime, mais le VAD à l’adresse de base de l’image n’est pas adossé à ce fichier. windows.ldrmodules compare les VAD mappés aux trois listes de modules du PEB (InLoad, InInit, InMem) ; une image principale retirée des listes, ou une région à l’adresse de base sans chemin de fichier mappé, est suspecte. L’exécutable affiche normalement False dans InInit ; cela ne constitue donc pas à lui seul un indicateur. Un résultat malfind à l’adresse de base de l’image complète le tableau.
Services, registre et vérifications de rootkits sous Linux
windows.svcscan lit les enregistrements de services dans la mémoire de services.exe, notamment le nom, l’état, le type de démarrage et le chemin du binaire, et peut révéler un service ajouté à des fins de persistance. windows.registry.hivelist répertorie les ruches chargées et windows.registry.printkey lit une clé en mémoire, telle qu’une clé Run, y compris les modifications qui n’ont pas encore été écrites sur disque. Sous Linux, linux.malfind signale les mappages mémoire accessibles en écriture et en exécution ou les mappages exécutables anonymes ; linux.lsmod répertorie les modules noyau chargés, linux.check_modules compare cette liste à sysfs pour trouver des modules cachés, et linux.check_syscall signale les entrées de la table des appels système qui pointent en dehors du noyau. Depuis 2025, Volatility 3 répertorie malfind, ldrmodules et les plugins de vérification Linux sous windows.malware. et linux.malware. (par exemple windows.malware.malfind) ; les noms courts utilisés ici sont des alias obsolètes.
Exemple détaillé : rundll32.exe sans arguments
Une image mémoire Windows est analysée. Sélection de colonnes de netscan :
| Proto | Adresse locale:Port | Adresse distante:Port | État | PID | Propriétaire | Création |
|---|---|---|---|---|---|---|
| TCPv4 | 0.0.0.0:135 | 0.0.0.0:0 | LISTENING | 1012 | svchost.exe | 2026-03-14T08:01:44Z |
| TCPv4 | 192.0.2.15:49823 | 203.0.113.50:443 | ESTABLISHED | 7344 | rundll32.exe | 2026-03-14T14:22:09Z |
| TCPv4 | 192.0.2.15:49790 | 198.51.100.24:443 | CLOSE_WAIT | 5128 | msedge.exe | 2026-03-14T14:05:31Z |
rundll32.exe sert à exécuter une fonction exportée par une DLL ; sa ligne de commande en désigne donc normalement une (rundll32.exe file.dll,Export). windows.cmdline pour le PID 7344 affiche uniquement C:\Windows\System32\rundll32.exe, sans arguments. Ce schéma est typique d’un processus sacrifié démarré par un framework de post-exploitation pour héberger du code injecté. windows.malfind --pid 7344 :
| VPN de début | VPN de fin | Balise | Protection | CommitCharge | PrivateMemory | Premiers octets |
|---|---|---|---|---|---|---|
| 0x1e0000 | 0x20afff | VadS | PAGE_EXECUTE_READWRITE | 43 | 1 | 4D 5A 90 00 |
Taille = Fin − Début + 1 = 0x20afff − 0x1e0000 + 1 = 0x2b000 = 176 128 octets = 176 128 / 4 096 = 43 pages, ce qui correspond à CommitCharge 43 ; la région entière est donc engagée. windows.handles --pid 7344 montre un Mutant nommé qz7k2m_upd_0451, qu’un rapport sur les menaces associe à une famille connue.
Conclusion prudente : les éléments sont compatibles avec une image PE injectée dans rundll32.exe PID 7344, qui détenait une connexion établie vers 203.0.113.50:443, créée à 2026-03-14T14:22:09Z. Ils ne montrent pas quelles données ont été envoyées ni comment le code est arrivé. Éléments à collecter ensuite : extrayez la région avec malfind --dump et consignez son empreinte SHA-256 (un PE présentant une disposition mémoire ne correspondra pas par son empreinte à un échantillon sur disque) ; analysez-la avec YARA ; vérifiez le parent dans windows.pstree ; recherchez d’autres processus communiquant avec 203.0.113.50 ; et examinez le disque pour rechercher la persistance et le mode d’introduction (clés Run, services, tâches planifiées, Prefetch et chronologie du système de fichiers du module 3).
Indicateurs et faux positifs associés
| Indicateur | Plugin | Pourquoi il est suspect | Faux positif courant |
|---|---|---|---|
Région privée RWX commençant par MZ | windows.malfind | PE non chargé par le chargeur Windows | Logiciels d’empaquetage et logiciels auto-décompactants |
| Région privée RWX contenant des octets ressemblant à du code | windows.malfind | Shellcode possible | Compilateurs JIT .NET et JavaScript |
| Connexion sortante depuis un processus qui utilise rarement le réseau | windows.netscan | Binaire système injecté ou détourné | Une DLL légitime hébergée par rundll32 |
| Socket LISTENING sur un port inhabituel | windows.netscan, linux.sockstat | Porte dérobée acceptant des connexions | Outils de développement, logiciels pair à pair |
| Nom de mutex connu | windows.handles | Marqueur d’infection propre à une famille | Noms courts et génériques identiques |
| Adresse de base de l’image non adossée à son fichier | windows.ldrmodules, windows.vadinfo | Process hollowing | InInit à False pour l’image principale est normal |
| Entrée d’appel système en dehors du noyau | linux.check_syscall | Détournement par un rootkit | Modules de sécurité ou de traçage |
Points clés pour l'examen : La partie A peut vous demander quel plugin récupère les connexions fermées (netscan, et non netstat), ce que signifie un état TCP, quel type de handle correspond à un mutex (Mutant), ou pourquoi malfind signale une région et dans quels cas ce signalement est un faux positif. Attendez-vous à calculer la taille d’une région à partir des VPN de début et de fin. Dans la partie B, la capture mémoire provient de Linux : préparez-vous donc à trouver un PID, une adresse distante ou un chemin de fichier ouvert avec linux.sockstat et linux.lsof, et à le rapporter exactement.
Points essentiels
- windows.netscan trouve les structures de points de terminaison par recherche en mémoire et inclut les connexions fermées ; windows.netstat parcourt uniquement les listes actives.
- Reliez un socket à son processus par le PID, comparez l’heure de création du processus à Created, puis lisez la ligne de commande.
- windows.handles montre les fichiers, clés et mutex ouverts ; un nom de mutex connu est un indicateur fort, et les fichiers extraits peuvent être incomplets.
- windows.malfind signale les régions VAD privées, engagées, exécutables et accessibles en écriture ; « MZ » au début est un signal d’alerte, et les compilateurs JIT sont le faux positif classique.
- Le process hollowing se manifeste par un chemin d’image qui ne correspond pas au VAD à l’adresse de base de l’image, une image principale retirée des listes dans ldrmodules et un résultat malfind à cette adresse de base.
- Sous Linux, utilisez linux.sockstat pour les connexions, linux.lsof pour les fichiers ouverts, et linux.lsmod, linux.check_modules et linux.check_syscall pour les vérifications de rootkits.