Amcache ProgramId erklärt: die 44-Zeichen-Anwendungsidentität

Das ProgramId-Feld in Root\InventoryApplicationFile und Root\InventoryApplication ist Amcaches logische Anwendungsidentität. Es ist ein 44-Zeichen-Hex-String, der eine Anwendung eindeutig identifiziert — und entscheidend ist er deterministisch: Dieselbe Anwendung auf einem anderen Host erhält typischerweise dieselbe ProgramId. Das macht es zu einem der nützlichsten hostübergreifenden Pivots im gesamten Windows-DFIR-Werkzeugkasten.

Diese Seite ist die vollständige Referenz: was der Wert ist, wie Windows ihn konstruiert, wie man ihn in einer Einzelhost-Untersuchung verwendet und wie man ihn in einem Hunt über eine Umgebung pivotiert.

Für den breiteren Amcache-Kontext siehe die vollständige Amcache-Referenz; für die umliegende Registry-Struktur siehe Amcache-Registry-Struktur.


Wie der Wert aussieht#

Eine typische ProgramId aus einer echten Hive:

0006fa0b2a9f8a4eb9d7c81e8b1f3c5d3e2a0000ffff

44 Hex-Zeichen, kein Präfix, keine Trennzeichen. Jeder Eintrag in InventoryApplicationFile trägt einen; jeder Eintrag in InventoryApplication ist nach einem geschlüsselt. Die beiden verlinken über den gemeinsamen Wert: Die ProgramId einer Datei sagt Ihnen, zu welcher installierten Anwendung sie gehört.

Struktur der 44 Zeichen#

Der Wert ist kein einzelner einheitlicher Hash. Er kodiert mehrere Komponenten, in grober Form:

  • Ein Typ- / Versions-Tag (die führenden paar Zeichen).
  • Ein Hash der identifizierenden Attribute der Anwendung — primär Name, Publisher, Version und Sprache.
  • Ein abschließender Diskriminator (oft 0000ffff oder ähnlich), der von Windows für die interne Klassifizierung verwendet wird.

Die genaue Konstruktion hat sich über Windows-Builds verschoben und ist von Microsoft nicht vollständig dokumentiert. Für DFIR-Zwecke sind die praktischen Regeln:

  • Zwei Einträge mit derselben ProgramId betreffen dieselbe Anwendung.
  • Die ProgramId ist über Hosts hinweg stabil für dieselbe Anwendungs-Installation — Office 365 auf Host A und derselbe Office-365-Build auf Host B teilen eine ProgramId.
  • Die ProgramId ist nicht stabil über große Versions-Upgrades — ein Upgrade der Anwendung ändert in der Regel ihre ProgramId.

ProgramId auf einem einzelnen Host verwenden#

Die Hauptverwendung ist das Verknüpfen einer Datei mit ihrem Anwendungsdatensatz.

Datei → Anwendung#

Sie haben eine verdächtige Zeile in *_UnassociatedFileEntries.csv gefunden. Ihre ProgramId ist 0006fa0b2a9f8a4eb9d7c81e8b1f3c5d3e2a0000ffff.

Schlagen Sie dieselbe ProgramId in *_AssociatedFileEntries.csv und im übergeordneten Anwendungskatalog nach (dem Registry-Schlüssel Root\InventoryApplication\<ProgramId> oder der äquivalenten CSV, falls Ihr Parser eine ausgibt). Sie erhalten typischerweise:

  • Den Anzeigenamen und Publisher der Anwendung.
  • Das Installationsdatum.
  • Die Installationsquelle (manchmal eine Download-URL).
  • Die vollständige Liste der mit dieser Anwendung verknüpften Dateien.

Das ist unbezahlbar, wenn ein Angreifer ein Tool ablegt, das sich als legitime Anwendung tarnt. Der Dateiname und die Metadaten der Datei sagen möglicherweise „AdobeReaderUpdater.exe / Adobe Inc.", aber ihre ProgramId passt entweder zu keinem installierten Adobe-Produkt (verdächtig) oder passt zu einer anderen Anwendung, als ihr Name vermuten lässt (sehr verdächtig).

Anwendung → Dateien#

Der umgekehrte Pivot ist gleichermaßen nützlich. Sie haben einen verdächtigen Anwendungsdatensatz in InventoryApplication gefunden — vielleicht einen portablen Build von etwas mit Publisher "" und ungewöhnlicher Installationsquelle. Nehmen Sie seine ProgramId und listen Sie jede Datei auf, die sie teilt:

$pid = '0006fa0b2a9f8a4eb9d7c81e8b1f3c5d3e2a0000ffff'
 
Import-Csv .\HOST_amcache_UnassociatedFileEntries.csv |
  Where-Object { $_.ProgramId -eq $pid } |
  Select-Object FullPath, Hash, KeyLastWriteTimestamp
 
Import-Csv .\HOST_amcache_AssociatedFileEntries.csv |
  Where-Object { $_.ProgramId -eq $pid } |
  Select-Object FullPath, Hash, KeyLastWriteTimestamp

Sie erhalten den vollständigen Datei-Fußabdruck dieser Anwendung, wie der Appraiser sie sah — jede EXE, DLL und PE, die der Appraiser auf diese Anwendung zurückführte. Für Angreifer-Tooling ist das oft der schnellste Weg, das vollständige Set abgelegter Binärdateien aus einer einzelnen beobachteten Datei aufzuzählen.


Hostübergreifendes Pivotieren mit ProgramId#

Hier glänzt ProgramId als Hunt-Primitiv. Da die Identität über Hosts hinweg stabil ist für dieselbe Anwendung, wird eine einzelne verdächtige ProgramId auf einem Host zu einer Abfrage, die Sie gegen die Amcache jedes anderen Hosts ausführen können:

$pid = '0006fa0b2a9f8a4eb9d7c81e8b1f3c5d3e2a0000ffff'
 
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
  ForEach-Object {
    $rows = Import-Csv $_.FullName |
      Where-Object { $_.ProgramId -eq $pid }
    if ($rows) {
      $host = $_.PSChildName.Split('_')[0]
      foreach ($r in $rows) {
        [pscustomobject]@{
          Host = $host
          Path = $r.FullPath
          Hash = $r.Hash
          When = $r.KeyLastWriteTimestamp
        }
      }
    }
  } |
  Sort-Object When

Das ist der Lateral-Movement-Pivot. Wenn ein einzelner Host eine verdächtige ProgramId hat, sagt Ihnen diese Abfrage über Ihre gesammelten Amcache-CSVs hinweg jeden anderen Host, auf dem dieselbe Anwendung jemals erschienen ist, mit Pfaden und Zeiten — in der Regel ein engeres Signal als reine Hash-Pivots, weil die ProgramId kleine Variationen des Binärprogramms überlebt (erneutes Signieren, Neukompilierung mit demselben Namen/Publisher/Version).

Für das vollständige Lateral-Movement-Playbook siehe Lateral Movement und Amcache-ProgramId-Pivoting.


Wann ProgramId am nützlichsten ist#

Ein paar Ermittlungsmuster, in denen ProgramId der richtige Pivot ist:

Dieselbe Familie, mehrere Builds#

Ein Angreifer kompiliert sein Tool möglicherweise mehrfach mit denselben Namens-, Publisher- und Versions-Metadaten — nur das Binärprogramm ändert sich. Die Hashes unterscheiden sich. Die ProgramId ist dieselbe. Hashing allein verfehlt die Familie; ProgramId fängt sie ein.

Umbenannte Binärprogramme#

mimikatz.exesvchost64.exeupdate.exe. Der Dateiname ändert sich; die eingebetteten PE-Metadaten sind dieselben. Wenn der Angreifer sich nicht die Mühe gemacht hat, die Versionsinfo- Ressource zu säubern, bleibt die ProgramId dieselbe.

Über eine Umgebung neu bereitgestellte Tools#

Der Angreifer legt dasselbe Tool auf 20 Hosts ab, während er seitlich vorrückt. Hashes können übereinstimmen, Pfade in der Regel nicht. Die ProgramId ist der konsistenteste Identifikator über alle 20 Hosts.


Wann ProgramId der falsche Pivot ist#

Ein paar Fälle, in denen ProgramId unterperformt:

Tools mit rotierenden Metadaten#

Wenn der Angreifer mit jedem Mal mit anderen Namens-/Publisher-/Versions-Werten neu kompiliert, erhält jeder Build eine andere ProgramId. Für diese ist der Datei-Inhalts-Hash (der SHA-1 in Hash) der bessere hostübergreifende Pivot, weil mindestens eine Komponente des Builds identisch ist.

Living-off-the-land-Binärprogramme#

net.exe, psexec.exe, certutil.exe — missbrauchte legitime Tools. Jeder Host, der irgendeines davon ausgeführt hat, hat dieselbe ProgramId dafür. ProgramId-Treffer sind hier praktisch bedeutungslos. Pivotieren Sie stattdessen auf Kommandozeile (4688 / Sysmon 1) oder auf den Pfad, von dem das LOLBIN ausgeführt wurde.

Wirklich neuartige Binärprogramme#

Eine Datei, die zum allerersten Mal irgendwo auftaucht, hat eine ProgramId, die kein anderer Host teilt. Ohne ein Korpus zum Vergleich leistet ProgramId nichts; Hash plus Publisher = '' and IsPeFile = True and FullPath unter \Users\ ist der funktionierende Triage-Filter.


Häufige Verwechslungen#

Zwei Dinge, die ProgramId nicht ist:

Kein Hash des Binärprogramms#

Hash (oder FileId) ist der Inhalts-Hash. ProgramId ist ein Anwendungsidentitäts-Hash, berechnet aus Metadaten, nicht aus den Bytes des Binärprogramms. Zwei völlig verschiedene Binärprogramme mit identischen Metadaten erhalten dieselbe ProgramId; dasselbe Binärprogramm, neu kompiliert mit anderen Metadaten, erhält eine andere ProgramId.

Kein Identifikator pro Host#

Ein häufiger Fehler ist anzunehmen, dass ProgramId eine spezifische Installation identifiziert. Tut es nicht. Wenn ein Benutzer Notepad++ auf fünf Hosts installiert, teilen diese fünf Hosts eine ProgramId für Notepad++. Um Installationen zu unterscheiden, benötigen Sie Installationsdaten, -quellen oder -pfade zusätzlich zur ProgramId.


Wo ProgramId in der Ausgabe von AmcacheParser lebt#

AmcacheParser stellt ProgramId in jeder Kategorie-CSV bereit, die es hat:

CSV Verwendung von ProgramId
*_UnassociatedFileEntries.csv Die Anwendung, zu der eine Datei sich zugehörig erklärt (auch wenn der übergeordnete Anwendungsdatensatz fehlt).
*_AssociatedFileEntries.csv Die Anwendung, mit der die Datei wirklich assoziiert ist.
*_ProgramEntries.csv Die eigene Identität der Anwendung (Legacy-Schema).
*_ShortcutEntries.csv Die Anwendung, auf die die Verknüpfung zeigt.

Für Pivots ist das Standardmuster: Identifizieren Sie eine verdächtige Zeile in UnassociatedFileEntries, nehmen Sie ihre ProgramId und führen Sie die obigen Abfragemuster aus.


Siehe auch#

Um ProgramId-Werte in Ihrer eigenen Hive zu erkunden, ohne etwas zu installieren, legen Sie eine Datei auf der Startseite des Parsers ab — sie verlässt nie Ihren Browser.

Verwandte Beiträge

Zurück zu allen Beiträgen