Mouvement latéral et Amcache : pivot par ProgramId entre hôtes
Lorsque vous confirmez la présence d'outils attaquants sur un hôte Windows, la question suivante est toujours : où d'autre ? Cadrer le mouvement latéral — identifier chaque autre hôte que l'attaquant a atteint — est l'une des étapes les plus difficiles d'une enquête, et Amcache est l'un des outils les plus utiles pour cela.
La raison : Amcache stocke deux pivots cross-hôtes que presque aucun autre artefact Windows ne stocke :
Hash— le SHA-1 des 31 premiers Mio de chaque PE que l'appraiser a vu.ProgramId— le hash d'identité applicative de 44 caractères, stable entre hôtes pour la même application.
Un seul Hash ou ProgramId suspect sur l'Hôte A devient une
requête que vous pouvez exécuter contre les CSVs Amcache analysés
de chaque autre hôte que vous avez collecté. Cette page est le
playbook complet.
Pour les prérequis, voir Référence complète Amcache, FileId Amcache expliqué, et ProgramId Amcache expliqué.
Le prérequis de collecte#
Le pattern ne fonctionne que si vous avez collecté Amcache depuis de nombreux hôtes d'une manière qui permet de joindre entre eux. Deux patterns pratiques de collecte :
Collecte par hôte basée sur KAPE#
Utilisez une seule racine de collecte avec des sous-répertoires par hôte :
\\fileshare\incident-042\
├── HOST01\
│ └── Windows\AppCompat\Programs\Amcache.hve (+ logs)
├── HOST02\
│ └── ...
├── HOST03\
│ ...
Analysez avec AmcacheParser pointé sur chaque répertoire par hôte :
Get-ChildItem '\\fileshare\incident-042' -Directory | ForEach-Object {
$host = $_.Name
AmcacheParser.exe `
-f "$($_.FullName)\Windows\AppCompat\Programs\Amcache.hve" `
--csv "\\fileshare\parsed\$host" `
--csvf "${host}_amcache.csv" `
--mp
}Vous vous retrouvez avec <host>_amcache_UnassociatedFileEntries.csv
par hôte, tous dans un seul répertoire.
Hunt sur parc Velociraptor#
L'artefact Windows.Forensics.Amcache, exécuté comme hunt, dépose
la sortie analysée par hôte dans le serveur Velociraptor. Les CSVs
sont nommés avec le hostname de l'hôte ; les mêmes requêtes
cross-hôtes ci-dessous s'appliquent.
Le pivot par hash#
Le pivot le plus simple et de plus haute précision. Vous avez un SHA-1 connu comme malveillant depuis l'Hôte A ; trouvez chaque autre hôte qui l'a.
$badHash = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.Hash -eq $badHash } |
Select-Object @{n='Host';e={$host}}, FullPath, KeyLastWriteTimestamp, Size
} |
Sort-Object KeyLastWriteTimestampLa sortie est une timeline par hôte de quand le binaire malveillant est apparu pour la première fois sur chaque hôte. L'horodatage le plus ancien est votre candidat patient-zero ; les horodatages suivants sont la propagation.
Quand les correspondances de hash sur-collent#
Le pivot par hash manque les recompilations du même outil. Les
attaquants qui recompilent leur loader avant chaque mouvement latéral
ont un hash différent sur chaque hôte. Pour ceux-là, repliez-vous
sur ProgramId.
Le pivot par ProgramId#
ProgramId est plus permissif que Hash — il attrape les
recompilations qui partagent nom/éditeur/version même quand le
contenu binaire diffère. Voir
ProgramId Amcache expliqué pour
comment l'identité est construite.
$badProgramId = '0006fa0b2a9f8a4eb9d7c81e8b1f3c5d3e2a0000ffff'
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.ProgramId -eq $badProgramId } |
Select-Object @{n='Host';e={$host}}, FullPath, Hash, KeyLastWriteTimestamp
} |
Sort-Object KeyLastWriteTimestampCela trouve chaque hôte qui a un binaire s'identifiant comme la
même application — même avec des hashes de contenu différents.
Couplez avec le pivot par hash : hash pour les correspondances de
haute précision, ProgramId pour les correspondances au niveau
famille.
Quand ProgramId sur-colle#
ProgramId attrape des faux positifs si l'attaquant se greffe sur
une identité applicative légitime (ex. recompiler du tooling nommé
PsExec.exe qui obtient le même ProgramId que le vrai PsExec).
Couplez avec Hash pour désambiguïser ; une ligne correspondant
au ProgramId mais avec un hash que personne d'autre dans votre
environnement n'a est hautement suspecte.
Le pivot par pattern de chemin#
Pour les patterns de chemin d'installation attaquants connus, regex
contre FullPath :
$pattern = '\\AppData\\Roaming\\[a-z0-9]{8}\\update\.exe$'
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.FullPath -match $pattern } |
Select-Object @{n='Host';e={$host}}, FullPath, Hash, ProgramId, KeyLastWriteTimestamp
}Utile quand :
- Vous connaissez la convention d'installation de l'intrusion set.
- L'attaquant fait tourner les hashes et métadonnées mais réutilise les patterns de chemin.
- Vous voulez trouver des variantes qui partagent un style de chemin.
Couplez les correspondances avec hash et ProgramId des résultats
par ligne pour construire une détection plus riche.
Vue en série temporelle de la propagation#
Pour chaque pivot, triez les résultats par KeyLastWriteTimestamp
pour voir la propagation dans le temps. Un pattern typique :
2026-04-01 14:23 HOST01 -- patient zero, attacker initial access
2026-04-03 09:11 HOST02 -- 2 days later
2026-04-03 11:34 HOST07
2026-04-03 14:55 HOST09
2026-04-04 02:08 HOST15 -- weekend; attacker working overnight
2026-04-04 02:33 HOST22
2026-04-04 02:51 HOST31
Deux lectures :
- La cadence (plusieurs hôtes en quelques heures les uns des autres) est caractéristique d'un outillage de mouvement latéral automatisé (basé sur PsExec / WMI / SMB).
- La rafale de nuit-pendant-la-nuit est le pattern attaquant typique : accès initial pendant les heures ouvrables, puis mouvement accéléré une fois qu'ils ont des credentials et du contrôle.
Utilisez ces patterns pour borner dans le temps le reste de votre
collecte de preuves. Tirez Sysmon / Security 4624 / 4688 pour
chaque hôte dans sa fenêtre KeyLastWriteTimestamp ± 1 h — vous
obtenez les lignes de commande réelles de l'attaquant et les
événements de credentials avec une haute précision.
Pivot croisé sur les preuves de pilotes et périphériques#
Le pattern cross-hôtes n'est pas limité à
*_UnassociatedFileEntries.csv. Pour des enquêtes plus
approfondies, exécutez les mêmes patterns de pivot contre :
*_DriverBinaries.csv#
Pour les enquêtes BYOVD — un pilote vulnérable que l'attaquant
a chargé sur un hôte est presque certainement chargé sur les autres
qu'il a atteints. Requête par Hash ou DriverName du pilote :
$badDriver = 'mhyprot2.sys'
Get-ChildItem -Recurse -Filter *_DriverBinaries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.DriverName -eq $badDriver } |
Select-Object @{n='Host';e={$host}}, DriverName, Service, DriverSigned, KeyLastWriteTimestamp
}*_DeviceContainers.csv#
Pour les enquêtes où l'attaquant a connecté du matériel (rare dans
les attaques à distance, central dans les cas de menace interne) —
requête par Manufacturer ou FriendlyName :
$suspiciousVendor = 'HakShop'
Get-ChildItem -Recurse -Filter *_DeviceContainers.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.Manufacturer -match $suspiciousVendor } |
Select-Object @{n='Host';e={$host}}, FriendlyName, Manufacturer, KeyLastWriteTimestamp
}Voir Historique USB et périphériques depuis Amcache pour les patterns côté périphérique en détail.
Combiner avec des sources non-Amcache#
Le pivot Amcache vous dit où le binaire a été inventorié. Pour confirmer l'exécution et identifier la méthode de mouvement, corrélez avec :
- 4624 (Logon) + 4625 (Failed logon) sur les hôtes destination — quand l'attaquant s'est-il authentifié, et en tant que qui ?
- 4648 (Explicit credential logon) — mouvement latéral avec credentials (PsExec, RDP avec credentials passés).
- Sysmon 1 / 4688 (Process create) avec processus parent — le
processus attaquant s'est-il lancé sous
services.exe(PsExec / service distant), souswmiprvse.exe(WMI), ou sousexplorer.exe(interactif) ? - Sysmon 3 (Network connect) + Sysmon 22 (DNS query) — C2 sortant.
- Arbres de processus Velociraptor / EDR — mêmes données, plus faciles à naviguer.
Un seul pivot Amcache cadrant la propagation, joint aux événements d'authentification et de processus par hôte sur les hôtes correspondants, vous donne une timeline défendable de : qui, quand, depuis où, via quel binaire, avec quel credential.
Quand le pivot manque#
Trois situations où le pivot cross-hôtes Amcache sous-performe :
L'appraiser n'a pas encore tourné sur les hôtes destination#
Si l'attaquant s'est déplacé latéralement dans les heures suivant votre collecte, les appraisers des hôtes destination peuvent ne pas avoir encore inventorié le binaire. Amcache les montre comme propres. Re-collectez 24-48 heures plus tard ; la propagation apparaîtra.
L'attaquant a nettoyé Amcache sur chaque hôte atteint#
Peu courant (surtout parce que c'est bruyant et que la plupart des attaquants ne s'en embêtent pas) mais possible. Utilisez le workflow de récupération via Volume Shadow Copy dans Où se trouve Amcache.hve sur disque sur chaque hôte où vous suspectez un nettoyage.
L'attaquant a utilisé des binaires différents par hôte#
Si l'attaquant a généré des implants par-hôte (vrais malwares
par-victime), les pivots par hash et ProgramId échouent par
construction. Les patterns de chemin et les détections
comportementales plus larges (4624 logon depuis la même IP
inhabituelle sur de nombreux hôtes) deviennent primaires.
Voir aussi#
- Référence complète Amcache — l'artefact en intégralité.
- FileId Amcache expliqué — le pivot par hash de contenu.
- ProgramId Amcache expliqué — le pivot par identité applicative.
- Amcache pour l'investigation de malware — triage mono-hôte qui produit les mauvais indicateurs avec lesquels vous pivoterez entre hôtes.
- Récupérer la preuve de binaires supprimés depuis Amcache — quand le binaire sur l'hôte destination a été effacé après le mouvement.
Pour explorer vos propres ruches collectées sans rien installer, déposez un fichier sur la page d'accueil de l'analyseur — il s'analyse entièrement dans votre navigateur.
Articles liés
- Volatility et Amcache : extraire la ruche depuis des images mémoire
Un guide pratique pour récupérer Amcache depuis une image mémoire Windows en utilisant Volatility — quand la récupération côté mémoire est la seule option, quels plugins utiliser, et comment passer le relais à AmcacheParser.
- Plugin amcache de RegRipper : ce qu'il fait et quand l'utiliser
Un guide pratique sur le plugin amcache de RegRipper — ce qu'il analyse, comment sa sortie texte diffère du CSV d'AmcacheParser, et quand l'utiliser à la place (ou en complément) de l'outil Zimmerman.
- Les colonnes de sortie d'AmcacheParser expliquées : chaque champ CSV décodé
Référence champ par champ pour la sortie CSV d'AmcacheParser — FileId, PathHash, ProgramId, LinkDate, BinFileVersion, IsPeFile et toutes les autres colonnes, avec les pivots qui comptent en DFIR.
- Guide de téléchargement d'AmcacheParser : sources officielles, miroirs et vérification
Tous les moyens de télécharger AmcacheParser d'Eric Zimmerman — Get-ZimmermanTools, téléchargement direct, KAPE, Velociraptor — avec vérification par somme de contrôle et schémas d'installation en environnement isolé.