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 Host

C'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 limit

Mê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#

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

Retour à tous les articles