Présentation de Volatility 3 : analyser une image mémoire, de la couche de fichier aux connexions réseau
Catégorie : Volatility
Résumé
Volatility 3 lit une image de la mémoire d'une machine et en tire des objets : processus, connexions réseau, modules noyau, clés de registre, fichiers ouverts. Ce billet pose le vocabulaire : les couches, les symboles, l'automagic, les plugins ; d'où vient une image ; le format du fichier d'hibernation hiberfil.sys, section par section et set par set ; et les deux façons dont Volatility retrouve les connexions réseau, parce que c'est ce qui casse sur Windows 11. C'est la base pour lire le billet sur l'hibernation, celui sur netscan et la liste de ce que j'ai envoyé au projet.
1. Ce que fait Volatility
Volatility ne lance rien et n'a pas besoin de la machine. Il part d'une image mémoire et reconstruit ce que le système d'exploitation y avait : quels processus tournaient, qui était connecté à quoi, quel code était chargé, quelle commande a été lancée. Il travaille en trois étapes : trouver le noyau dans l'image et en déduire la traduction des adresses virtuelles en physiques ; charger la description des structures de ce build ; parcourir ces structures et afficher le résultat.
vol -f image.raw windows.info
vol -f image.raw windows.pslist
vol -f image.raw windows.netscan
windows.info est le premier plugin à lancer : il donne la version, la base du noyau et les symboles retenus. S'il échoue, le reste échouera aussi.
2. Les briques
Couches. Une image est lue à travers une pile de couches. Une couche de fichier lit les octets sur le disque ; une couche au-dessus peut décompresser (hibernation, crash dump) ; une couche de traduction (Intel 32 bits, PAE, 64 bits) convertit les adresses virtuelles en physiques. Chaque couche ne voit que celle du dessous. C'est ce qui permet d'ajouter un format d'image sans toucher aux plugins.
Symboles. Les ISF (Intermediate Symbol Format), en JSON, décrivent les structures du noyau pour un build donné : types, offsets des champs, adresses des symboles. Pour Windows, ils sont générés depuis le PDB de ntoskrnl.exe ; Volatility les télécharge tout seul quand il trouve le GUID dans l'image. Pour les pilotes, c'est à part : tcpip.sys n'a pas de symboles publics utilisables, et les structures réseau sont décrites dans des tables écrites à la main, une par build.
Automagic. Le code qui, au lancement, devine le type d'image, empile les couches, trouve le noyau (par son en-tête PE ou son KDBG) et choisit les symboles.
Plugins. Chacun répond à une question et produit un tableau. windows.pslist parcourt la liste chaînée des processus ; windows.psscan les cherche par signature dans toute la mémoire, y compris ceux qui ont été décrochés de la liste. Cette opposition, parcourir ou scanner, revient partout.
3. D'où vient une image
| Source | À retenir |
|---|---|
Capture en direct (WinPmem, un EDR, vmi-dump-memory sur une VM) |
image brute, la plus complète, mais il faut avoir eu la machine allumée |
| Dump de crash | partiel, selon le type choisi par Windows |
| Snapshot d'hyperviseur | image brute de la VM |
hiberfil.sys |
disponible sur un disque saisi, mais compressé et dans un format interne à Windows |
Dans une enquête sur disque, hiberfil.sys est souvent la seule trace de la mémoire. D'où l'importance de bien le lire.
4. Le fichier d'hibernation
À l'hibernation, Windows écrit la mémoire dans hiberfil.sys. Trois choses à savoir.
Fast Startup. Sur Windows 10 et 11, un arrêt « normal » est un arrêt hybride : la session utilisateur est fermée, mais la mémoire du noyau est écrite dans hiberfil.sys pour accélérer le démarrage suivant. Un disque saisi sur une machine « éteinte » contient donc de la mémoire noyau, sans pages utilisateur. On force ce comportement avec shutdown /s /hybrid, et l'hibernation complète (S4) avec shutdown /h.
Deux sections. Le fichier commence par un en-tête (PO_MEMORY_IMAGE), qui contient entre autres une structure de statistiques _PO_HIBER_PERF. Puis la section de boot (ce qu'il faut pour redémarrer le noyau), puis la section noyau (le reste de la mémoire). Des compteurs de pages dans l'en-tête bornent chaque section : FirstKernelRestorePage donne où commence la section noyau, KernelPagesProcessed combien de pages elle contient. L'offset de ce dernier dans _PO_HIBER_PERF n'est pas stable d'un build à l'autre, et c'est tout le sujet du billet sur 24H2.
Les sets de compression. Les pages sont compressées par paquets de 16 pages au plus. Chaque paquet commence par un en-tête de 4 octets : le nombre de pages, la taille compressée, et l'algorithme, LZ77 simple ou LZ77+Huffman (le format « Xpress » de Windows). Les sets se suivent en chaîne : la fin de l'un donne le début du suivant. Un set non compressé se reconnaît à sa taille égale à pages × 4096. Le format exact des bits de cet en-tête a changé sur Windows 11 24H2.
Dans Volatility 3, la couche d'hibernation (proposée dans la PR #1036, pas encore dans develop) lit l'en-tête, suit la chaîne des sets, décompresse chacun et reconstruit une image brute. Le plugin windows.hibernation.Dump écrit le résultat dans un fichier memory_layer.raw, qu'on analyse ensuite comme n'importe quelle image. windows.hibernation.Info affiche l'en-tête, dont le SystemTime du fichier.
5. Les connexions réseau : scanner ou parcourir
Deux plugins répondent à « qui était connecté à quoi », par deux chemins différents.
windows.netstat parcourt les structures de tcpip.sys depuis leur point d'entrée : la table de partition, puis les listes de listeners et d'endpoints. Il trouve ce qui est encore enregistré, et il a besoin de symboles pour tcpip.sys, qui viennent des tables faites main.
windows.netscan scanne la mémoire physique à la recherche des allocations de pool étiquetées TcpL (listener), TcpE (endpoint TCP) et UdpA (endpoint UDP). Il trouve aussi les connexions fermées dont la mémoire n'a pas été réutilisée, ce qui est précieux en forensique. Pour chaque allocation, il construit l'objet (_TCP_LISTENER, _TCP_ENDPOINT, _UDP_ENDPOINT) juste après l'en-tête de pool, et le valide : ports plausibles, pointeurs vers une famille d'adresses, propriétaire. Deux hypothèses : l'objet commence à un endroit fixe après l'en-tête, et sa disposition est celle de la table de symboles choisie pour ce build. Les deux sont fausses sur Windows 11 24H2 et plus, et c'est le billet sur netscan.
Même idée pour les plugins GUI (windows.desktops, windows.windows) : ils reposent sur des tables faites main pour win32k, dont la dernière date d'un build de Windows 10, et win32kbase.pdb n'est pas sur le serveur de symboles Microsoft pour les builds récents.
6. Quoi vérifier quand ça « marche »
Volatility échoue rarement bruyamment. Un plugin qui sort un tableau vide, ou Dump qui se termine sans erreur avec une image presque vide, ressemblent à des succès. Quelques réflexes : comparer la taille de l'image à la mémoire de la machine ; regarder si la liste des processus a l'air complète, pas seulement System ; confronter netscan et netstat ; et ne jamais supposer qu'un offset trouvé pour un build s'applique au suivant.
Sources
- Volatility 3 et sa documentation.
- La PR #1036 pour la couche d'hibernation.
- Les tables de symboles
netscan-win10-*.jsonetgui-win10-*.jsondansvolatility3/framework/symbols/windows/.