FileId Amcache expliqué : le format de hash SHA-1 que Windows stocke
La valeur FileId dans Root\InventoryApplicationFile est l'un des
champs les plus utiles de toute la ruche Amcache — et l'un des plus
mal compris. C'est le hash de contenu du fichier, mais ce n'est pas
tout à fait un SHA-1 standard, et il ne pas tout à fait hashe le
fichier entier. Ce billet est la référence complète : ce qu'est la
valeur, comment l'utiliser, et les pièges qui attrapent les nouveaux
analystes.
Pour la référence Amcache plus large, voir la référence complète Amcache ; pour la structure de registre environnante, voir Structure du registre Amcache.
À quoi ressemble la valeur#
Un FileId typique issu d'une ruche réelle :
0000da39a3ee5e6b4b0d3255bfef95601890afd80709
41 caractères au total :
- Les 4 premiers caractères sont toujours
"0000"— une étiquette de type fixe. - Les 40 caractères restants sont le digest hex SHA-1 du fichier.
Le préfixe "0000" est un artefact historique : les premières
versions de l'appraiser anticipaient plusieurs algorithmes de hash
(avec chaque préfixe indiquant lequel) mais en pratique, seul SHA-1
a été utilisé. Aujourd'hui, le préfixe est constant.
Lorsque AmcacheParser expose ce champ dans son CSV, il le scinde en deux colonnes :
| Colonne | Valeur |
|---|---|
FileId |
La chaîne complète de 41 caractères, préfixe inclus. |
Hash |
Juste les 40 caractères hexadécimaux — le SHA-1 seul. |
Utilisez toujours Hash (ou retirez le préfixe vous-même) lors des
jointures avec des flux de hash externes. VirusTotal, vos flux TI
et les bases de hash-allowlist attendent un SHA-1 de 40 caractères —
ils ne trouveront aucune correspondance si vous incluez le préfixe
"0000".
Ce qu'il hashe réellement#
C'est le piège qui attrape presque tout nouvel analyste Amcache :
Le SHA-1 d'Amcache hashe les 31 premiers Mio du fichier, pas le fichier entier.
Pour les fichiers de moins de 31 Mio (c'est-à-dire presque tout — la plupart des EXEs et DLLs sont bien en dessous), le prefix hash égale le SHA-1 du fichier complet. Ils sont indistinguables l'un de l'autre.
Pour les fichiers plus grands que 31 Mio, le hash Amcache est un
prefix hash, pas un hash de contenu complet. Il reste suffisamment
distinctif pour identifier un build spécifique d'un binaire
spécifique, mais ce n'est pas la même valeur que vous obtiendriez de
sha1sum sur le fichier entier.
Pourquoi cela importe#
- Correspondances VirusTotal. Pour les fichiers de moins de 31 Mio, le SHA-1 Amcache correspond au SHA-1 indexé par VirusTotal. Pour des fichiers plus gros (installateurs, certains binaires de jeux, gros logiciels d'entreprise), il ne correspondra pas, et une réponse VirusTotal « no record » est dénuée de sens.
- Bases de hash personnalisées. Si vous maintenez une allowlist interne de hashes known-good, assurez-vous que vous stockez le même type de hash que celui contre lequel vous comparerez. Soit vous stockez des SHA-1 de contenu complet (et vous acceptez que les comparaisons sur gros binaires contre Amcache échouent), soit vous maintenez une colonne parallèle de prefix-hash.
- Recompiler pour vérification. Si vous avez le binaire original sous la main et que vous voulez vérifier qu'un hash Amcache correspond, ne hashez que les 31 premiers Mio :
import hashlib
PREFIX_BYTES = 31 * 1024 * 1024 # 31 MiB
def amcache_sha1(path: str) -> str:
h = hashlib.sha1()
with open(path, 'rb') as f:
h.update(f.read(PREFIX_BYTES))
return h.hexdigest()Pièges du monde réel#
Une poignée de pièges qui apparaissent sur des cas réels :
N'incluez pas le préfixe "0000" dans les recherches#
# Wrong
search_virustotal('0000da39a3ee5e6b4b0d3255bfef95601890afd80709')
# Right
search_virustotal('da39a3ee5e6b4b0d3255bfef95601890afd80709')L'API de VirusTotal attend spécifiquement le hash nu. Inclure le préfixe renvoie silencieusement un résultat vide — ce qui ressemble exactement à « ce fichier est inconnu » et est bien plus trompeur.
Les collisions de hash sont théoriques mais pas impossibles#
SHA-1 a des attaques de collision connues. Dans un contexte non adversarial, c'est sans importance — trouver une collision SHA-1 contre une entrée Amcache spécifique demande un effort largement disproportionné par rapport à ce qu'un attaquant gagne. Mais pour une correspondance à haute confiance dans une enquête à forts enjeux, ne traitez pas une correspondance SHA-1 comme une identité cryptographique. Couplez avec la taille du fichier, la date de link, et au moins un autre champ.
Ne faites pas confiance au FileId d'une ligne IsPeFile = False#
Amcache enregistre occasionnellement des valeurs FileId pour des
fichiers non-PE inventoriés par l'appraiser. Le hash est toujours
réel, mais le contexte est différent — il hashe ce qu'est le fichier
(un script, un fichier de config), et les outils en aval qui supposent
un contexte de fichier PE (les recherches PE-aware de VirusTotal, les
règles Yara contre des octets PE) renverront des résultats moins
utiles.
Plusieurs lignes, même hash#
Si vous trouvez la même valeur Hash à travers plusieurs lignes
*_UnassociatedFileEntries.csv sur le même hôte, c'est significatif.
Cela signifie que le même contenu binaire a été inventorié à plusieurs
chemins. Raisons courantes :
- L'attaquant a copié un outil à plusieurs emplacements pour tester lequel s'exécuterait.
- Un installateur légitime a déposé la même DLL dans plusieurs répertoires de produits.
- Un utilisateur a copié un fichier manuellement.
Regroupez par Hash, puis regardez l'ensemble des FullPath et
KeyLastWriteTimestamp pour chaque instance. Les horodatages vous
disent la séquence des copies ; les chemins vous disent l'intention.
Plusieurs hashes, même FullPath#
Le pattern inverse — le même chemin avec des valeurs Hash
différentes sur plusieurs lignes — signifie que le binaire à ce
chemin a changé entre les inventaires. C'est un signal fort de
remplacement de binaire :
- Légitime : une mise à jour logicielle a écrasé le fichier.
- Suspect : un attaquant a remplacé un binaire système ou un outil utilisateur exécuté régulièrement par une copie trojanisée.
Triez les lignes par KeyLastWriteTimestamp pour voir quand chaque
nouveau hash est apparu, puis corrélez avec des événements de patch
ou des événements Sysmon File Create autour de ces moments.
Pivots qui utilisent FileId / Hash#
Les pivots qui méritent leur peine sur des cas réels :
Chasse aux hashes cross-hôtes#
# Pivot a known-bad SHA-1 across every host's Amcache CSV
$badHash = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
ForEach-Object {
Import-Csv $_.FullName |
Where-Object { $_.Hash -eq $badHash } |
Select-Object @{n='Host';e={$_.PSChildName.Split('_')[0]}},
FullPath, KeyLastWriteTimestamp, Size
} |
Sort-Object HostC'est ainsi que vous passez de « nous avons trouvé ce hash sur un hôte » à « dites-moi chaque hôte de l'environnement qui a déjà eu ce binaire présent, et quand il est apparu ».
Enrichissement VirusTotal d'un CSV#
import csv, requests, time
API = 'https://www.virustotal.com/api/v3/files/'
HEADERS = {'x-apikey': '<your-key>'}
seen = set()
with open('HOST_amcache_UnassociatedFileEntries.csv', newline='') as f:
for row in csv.DictReader(f):
h = row['Hash']
if not h or h in seen:
continue
seen.add(h)
r = requests.get(API + h, headers=HEADERS)
if r.status_code == 200:
stats = r.json()['data']['attributes']['last_analysis_stats']
if stats.get('malicious', 0) > 0:
print(h, stats, row['FullPath'])
time.sleep(15) # VT public API rate limitMême une recherche à faible volume contre l'API publique donne une liste serrée de hashes confirmés malveillants sur un hôte typiquement infecté.
Corrélation avec les événements Sysmon Image Loaded#
L'event ID 7 (Image Loaded) de Sysmon enregistre le SHA-1 de chaque
DLL chargée par chaque processus. Joindre Hash Amcache au champ
Hashes de Sysmon 7 vous dit exactement quels processus ont chargé
une DLL attaquant donnée, et quand.
Voir aussi#
- Référence complète Amcache — la vue d'ensemble haut niveau.
- Structure du registre Amcache —
où se trouve
FileIddans la ruche. - ProgramId Amcache expliqué —
l'autre identifiant unique dans
InventoryApplicationFile. - Horodatages Amcache expliqués
— comment pivoter les correspondances
FileIddans le temps. - Les colonnes de sortie d'AmcacheParser expliquées — les colonnes CSV environnantes.
Vous voulez voir les valeurs FileId dans votre propre ruche sans
rien installer ? Déposez une ruche sur la
page d'accueil de l'analyseur — il 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.
- Qu'est-ce que le FileId Amcache ? (glossaire)
FileId est l'identifiant de 41 caractères qu'Amcache stocke pour chaque fichier — '0000' + le SHA-1 hex des 31 premiers Mio du fichier.
- 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.