Persistence Hunter¶
Persistenz ermöglicht es einem Programm, nach einem Neustart, einer Anmeldung, einem geplanten Auslöser oder einem anderen Ereignis erneut ausgeführt zu werden. Ein Angreifer kann dafür die normale Windows-Konfiguration nutzen. Viele legitime Programme verwenden genau dieselben Mechanismen; ein gefundener Persistenzeintrag ist daher ein Ausgangspunkt für die Analyse.
juntei persistence-hunter ist eine native Rust-Portierung von
PyrsistenceSniper von Hexastrike mit 131 Prüfungen: dem
Katalog von PyrsistenceSniper mit 130 Prüfungen plus einer nativen Prüfung für Startmenü-COM.
Eine Erläuterung jedes Mechanismus, seiner Beweisorte und der Untersuchung eines Befunds finden Sie im Persistenzleitfaden mit 131 Prüfungen. Die Danksagungen zur Persistenz beschreiben die Python- und PowerShell-Projekte hinter dem Katalog.
Verwendung¶
Version: 1.1.0 (CODE BLUE Release)
Yamato Security (https://github.com/Yamato-Security/juntei - @SecurityYamato)
Usage:
juntei persistence-hunter -d <EVIDENCE> [OPTIONS]
Input:
-d, --directory <DIR> Evidence directory (a mounted Windows volume or a collection of hosts)
-f, --file <FILE> One registry hive (filesystem checks need a directory)
--no-logs Read dirty hives without replaying transaction logs
Filtering:
--profile <FILE> Replace the bundled allow/block profile with a YAML profile
--min-severity <MIN_SEVERITY> Minimum classification to include: info, low, medium, high [default: medium] [possible values: info, low, medium, high]
--check <ID> Run only these check or ATT&CK IDs (comma separated; repeatable) [alias: --technique]
General Options:
-h, --help Show the help menu
--list-checks Show every available check and its ATT&CK technique
Analysis:
--no-timeline Skip MFT and event-log timestamp correlation
--mft <FILE> MFT to use for timestamp correlation (one host only)
Performance:
-T, --threads <N> Worker threads (default: logical CPU count)
Output:
-o, --output <FILE> Save findings to a file
-t, --output-type <OUTPUT_TYPE> Output type: csv (default), json, jsonl; without -o, write data to stdout [possible values: csv, json, jsonl]
--coverage <FILE> Save per-check coverage and errors to CSV
-C, --clobber Overwrite output files
Display Settings:
-K, --no-color Disable color output
-q, --quiet Quiet mode: do not display the launch banner
Erster Scan¶
Die Beweise können ein eingebundenes Windows-Volume, eine Velociraptor-Sammlung oder ein Verzeichnis mit
mehreren gesicherten Computern sein. Computer werden während der Analyse getrennt gehalten, und jedes Ergebnis enthält
Comp. Die Maskierung von Dateinamen in Sammlungen wird beim Auflösen von Windows-Pfaden dekodiert.
Für einen einzelnen Hive:
Ein einzelner Hive kann keine Prüfungen bedienen, die einen anderen Hive oder Dateisystembelege benötigen. Lesen Sie den Abdeckungs- bericht, bevor Sie ein leeres Ergebnis als aussagekräftig behandeln.
Die Check-IDs und ihre ATT&CK-Zuordnungen auflisten:
juntei persistence-hunter --list-checks
juntei persistence-hunter -d evidence/ --check run_keys,windows_service_image_path -o focused.csv
Verwenden Sie die von --list-checks ausgegebenen Check-IDs oder eine ATT&CK-ID wie T1547.001.
Eine übergeordnete ID wie T1547 wählt ihre Untertechniken aus. --technique ist ein Alias für --check.
Jede Prüfung enthält in den Befunden ihre Technik, Beschreibung und Referenzlinks.
Parallele Scans¶
Der Befehl verwendet einen gemeinsamen Worker-Pool, standardmäßig mit der Anzahl der logischen CPUs. Setzen Sie
-T, --threads <N>, um die Anzahl der Worker zu wählen, oder -T 1 für einen Scan mit einem Thread:
Beweiserkennung, unabhängige Prüfungen, Payload-Metadaten sowie MFT-/EVTX-Zeitleistenquellen laufen parallel. Die geladenen Registry-Hives eines Hosts werden schreibgeschützt geteilt, und zwischengespeicherte Metadaten derselben Payload werden einmal initialisiert. Hosts werden nacheinander geladen, um den Hive-Speicher nicht über die gesamte Sammlung zu vervielfachen. Befunde, Abdeckung, Zeitstempelauswahl und Reihenfolge der Warnungen bleiben bei unterschiedlichen Thread-Anzahlen gleich.
auto-parse führt Parser-Prozesse bereits parallel aus und gibt daher jedem persistence-hunter-Kindprozess
einen Worker. Seine eigene Option -T steuert die Anzahl gleichzeitiger Parser-Prozesse.
Zu sichernde Beweise¶
| Quelle | Beispiele für Prüfungen |
|---|---|
SYSTEM und zugehörige Transaktionsprotokolle |
Dienste, Wiederherstellungsbefehle von Diensten, LSA-Pakete, Booteinstellungen, Authentifizierungsanbieter |
SOFTWARE und zugehörige Transaktionsprotokolle |
Run-Schlüssel, Winlogon, IFEO, COM-Registrierungen, TaskCache, Office-Einstellungen |
NTUSER.DAT und UsrClass.dat jedes Benutzers |
Benutzer-Autostarts, Umgebungsvariablen, COM-Überschreibungen, Office-Einstellungen |
SAM und SOFTWARE |
RID-Anomalien, verborgene Konten, ungewöhnliche Mitgliedschaft in der lokalen Gruppe Administratoren |
Windows/System32/Tasks |
Befehle und COM-Handler geplanter Aufgaben; Vergleich mit TaskCache |
.library-ms-Dateien und nach CLSIDs benannte Ordner im Startmenü jedes Benutzers |
Kandidaten für COM-Aktivierungsauslöser, verknüpft mit passenden Klassenregistrierungen von Benutzer/Computer |
| Autostartordner, PowerShell-Profile, Office-Vorlagen, Terminal-Einstellungen | Dateien und Befehle, die durch Benutzer- oder Systemauslöser ausgeführt werden |
WMI OBJECTS.DATA |
Instanzen von Ereigniskonsumenten und Bindungen von Filtern an Konsumenten |
BITS qmgr.db oder qmgr*.dat |
Wiederhergestellte Benachrichtigungsbefehle und Besitzer-SIDs |
$MFT und relevante EVTX-Dateien |
Unabhängige Zeitstempelkorrelation |
| Referenzierte ausführbare Dateien, DLLs und Katalogdateien | SHA256-Hashes und beschreibende PE-/Zertifikatsmetadaten |
Registry-Transaktionsprotokolle werden eingespielt, sofern vorhanden. --no-logs liest die Hives so, wie sie gesichert wurden;
ein nicht wiedergegebener „dirty“ Hive kann jüngste Änderungen auslassen und wird in der Abdeckung gemeldet. Für Prüfungen des aktiven Systems
wird das aktuelle Control Set verwendet. Die Prüfung auf eine DSRM-Hintertür untersucht zusätzlich
ControlSet001, ControlSet002 und CurrentControlSet, sofern vorhanden; gleichen Sie den gemeldeten Pfad
mit SYSTEM\\Select ab, bevor Sie diese Einstellung als aktiv beschreiben. Andere historische Control Sets
lassen sich mit den einzelnen Registry-Parserbefehlen untersuchen.
Hive-Lesevorgänge teilen sich ein Eingabebudget von 1 GiB pro Computer. Computer-Hives werden vor Benutzer-Hives versucht;
Eingaben oder Transaktionsprotokolle, die nicht hineinpassen, werden in der teilweisen Abdeckung genannt. Andere lesbare Hives und
dateibasierte Prüfungen laufen weiter. Nur kanonische Hive-Speicherorte oder explizit übergebene Exporte begründen die
Identität eines Hives; eine Kopie im temporären Verzeichnis eines Benutzers kann den echten Hive dieses Benutzers nicht ersetzen.
Das in SOFTWARE aufgezeichnete ursprüngliche Systemlaufwerk wird dem gesicherten Systemvolume zugeordnet; wird ein ursprüngliches
C:-Volume unter einem anderen Laufwerksbuchstaben der Beweise eingebunden, gehen daher keine Payload-Metadaten verloren.
auto-parse führt den Hunter ebenfalls aus und speichert persistence/PersistenceHunter.csv (oder .json/.jsonl)
im Verzeichnis jedes Computers, mit PersistenceHunter-logs.txt daneben. Seine Befunde fließen zudem in
die optionale SIEM-Zeitleiste -j <FILE> ein. Die automatische Analyse verwendet --min-severity info, um das
vollständige Konfigurationsinventar zu bewahren, einschließlich der Einträge, auf die Zulassungsregeln zutreffen.
COM-Registrierungen und Aktivierungsauslöser¶
Die Prüfung scheduled_task_files wählt den Prinzipal jeder Aktion anhand von
Actions Context und passender Principal id im Aufgaben-XML aus. Ein Gruppenprinzipal wird als Gruppe beibehalten;
er kann nicht festlegen, welche Klassenregistrierungen welches einzelnen Benutzers verwendet würden.
Kandidaten für COM-Handler werden getrennt in der nativen und der 32-Bit-Klassenansicht aufgelöst. Berücksichtigt werden nur die
gesicherte UsrClass.dat/NTUSER.DAT des passenden Benutzers und das SOFTWARE des Computers.
SID-Prinzipale werden über gesicherte ProfileList-Pfade verknüpft. Kontonamen, einschließlich
HOST\user und DOMAIN\user, bevorzugen ein passendes user.DOMAIN-Profil gegenüber einem einfachen
user-Profil. Lokale Host-Aliase und .\user verwenden gesicherte Hostnamen für den Abgleich von Suffixen;
ein exaktes Suffix hat Vorrang vor anderen Host-Aliasen. Das einfache Profil wird nur berücksichtigt,
wenn kein qualifiziertes Profil passt. Jede solche Übereinstimmung wird in Description ausdrücklich als
Heuristik anhand des Ordnernamens gekennzeichnet; sie beweist weder den Besitz des Kontos noch eine Domänenmitgliedschaft. Mehrdeutige Übereinstimmungen
bleiben ungelöst und werden sowohl in der Beschreibung des Befunds als auch in der Abdeckung gemeldet; Mehrdeutigkeit
zwischen qualifizierten Profilen löst keinen Rückgriff auf das einfache Profil aus. Dies hängt nicht
von Volatile Environment ab, das normalerweise nur im Arbeitsspeicher existiert und nicht mit Registry-Hives gespeichert wird. Eine doppelte Benutzer-CLSID
überdeckt die untergeordneten Elemente der Computer-CLSID. Gruppenprinzipale verwenden COM-Kandidaten des Computers und behalten
diese Einschränkung in der Beschreibung des Befunds bei; ein normaler Gruppenprinzipal macht die
Abdeckung für sich genommen weder unvollständig noch verbraucht er die Einträge der Fehlerzusammenfassung.
Der Resolver folgt InprocServer32 und LocalServer32, verwendet verwaltete CodeBase-Pfade
(einschließlich Versionsunterschlüsseln) und verknüpft AppID-LocalService mit dem ImagePath des gesicherten SYSTEM-
Dienstes. AppID-Zuordnungen zu Namen ausführbarer Dateien bleiben erhalten, doch ein Basisname legt nicht den
vollständigen Pfad einer ausführbaren Datei fest. Lokale file:-CodeBase-URLs werden dekodiert; entfernte URLs werden aufgezeichnet,
ohne sie aufzurufen. Fehlende Registrierungen behalten die CLSID mit
ResolutionStatus: unresolved_com_class, leeren Pfad-/Hash-Feldern und unbekanntem Exists.
Die Prüfung start_menu_com liest XML-URLs aus .library-ms-Dateien im Startmenü jedes Benutzers und erfasst
nach CLSIDs benannte Ordner, einschließlich leerer Verzeichnisse. Sie meldet Auslöserpfad, CLSID, Kandidaten-
server und Registry-Herkunft. Eine reine Dateisicherung kann kein leeres Verzeichnis bewahren,
und fehlende Benutzer-Hives verhindern eine vollständige Suche nach Registrierungen pro Benutzer. Symbolischen Links wird
nicht gefolgt. Es handelt sich um Konfigurationskandidaten: Architektur, Rechteerhöhung, UAC, Richtlinien und
Aktivierungskontext können beeinflussen, ob eine Registrierung tatsächlich verwendet wird. Untermauern Sie eine Ausführung
mit Prozess-, Modullade- oder anderen unabhängigen Belegen.
Klassifizierung und Profile¶
Die standardmäßige Mindestklassifizierung ist medium. Um das vollständige Inventar zu prüfen, einschließlich
der Einträge, auf die die mitgelieferte Zulassungsliste zutrifft:
Verwenden Sie alle Schweregrade bei der Prüfung unvollständiger Sammlungen
Eine weit gefasste Zulassungsregel kann teilweise auf den Befehl eines Angreifers zutreffen, selbst wenn dessen Signierer fehlt
oder abweicht. Upstream klassifiziert teilweise Übereinstimmungen als LOW, was der Standardschwellenwert
medium des manuellen Befehls ausblendet. Dies kann bösartige geplante Aufgaben unter Windows-Verzeichnissen betreffen.
Verwenden Sie --min-severity info für eine vollständige Untersuchung und prüfen Sie PolicyReason, SignerStatus,
den Befehl und die Quellbelege gemeinsam. auto-parse behält diese Einträge bereits bei.
| Klassifizierung | Bedeutung |
|---|---|
HIGH |
Eine konfigurierte Sperrregel traf vollständig zu |
MEDIUM |
Keine Zulassungs- oder Sperrregel traf zu |
LOW |
Die harten Bedingungen einer Zulassungsregel trafen zu, aber die Signierer-Metadaten passten nicht oder waren nicht verfügbar |
INFO |
Eine Zulassungsregel traf vollständig zu |
Dies sind Richtlinienklassifizierungen, keine gemessenen Wahrscheinlichkeiten einer Kompromittierung. Ein standardmäßiger MEDIUM-
Eintrag ist kein Beweis für Malware. INFO belegt weder, dass eine Datei eine gültige Signatur hat, noch dass
ein Angreifer sie nicht missbraucht hat. Eine teilweise Übereinstimmung mit einer Zulassungsregel liegt unter dem Standardschwellenwert; verwenden Sie daher
--min-severity low oder info, wenn Sie spärliche Sammlungen prüfen oder die Zulassungsliste abstimmen.
Übergeben Sie ein YAML-Profil mit --profile profile.yaml. Es ersetzt das mitgelieferte Profil. Globale
und prüfungsspezifische Regeln innerhalb der ausgewählten Datei werden kombiniert; jede vollständig zutreffende Sperrregel hat Vorrang.
Zum Beispiel:
allow: []
block:
- reason: Example known-bad command fragment
value_matches: 'example-malicious-loader\.exe'
checks:
windows_service_image_path:
enabled: true
allow:
- reason: Organization's expected service path
value_matches: '^C:\\Program Files\\ExampleCorp\\Agent\\agent\.exe$'
signer: ExampleCorp
Unterstützte Regelbedingungen sind path_matches, value_matches, hash (64 hexadezimale SHA256-
Ziffern), not_lolbin und signer (Teilzeichenfolge ohne Beachtung der Groß-/Kleinschreibung). Alle angegebenen harten Bedingungen müssen
zutreffen. Signierer-Metadaten sind die oben beschriebene weiche Bedingung. Reguläre Ausdrücke verwenden die Syntax regulärer Ausdrücke von Rust:
Lookarounds und Rückverweise werden nicht unterstützt. Unbekannte Check-IDs, ungültige Ausdrücke
und unbekannte Profilfelder führen zu einem Fehler, statt die Richtlinie stillschweigend abzuschwächen.
Ausgabefelder¶
CSV ist das Standarddateiformat. Verwenden Sie -t json für lesbare JSON-Objekte oder -t jsonl für kompakte
Ausgabe mit einem Objekt pro Zeile. Ohne -o schreibt ein explizites -t nur Daten nach stdout; Abdeckungs-
warnungen gehen nach stderr. Ohne beide Optionen gibt Juntei eine Zusammenfassung und bis zu 30 Kandidaten aus.
| Felder | Wie sie zu interpretieren sind |
|---|---|
Comp, CheckID, Technique, MitreID |
Welchen Computer und welchen Persistenzmechanismus die Zeile beschreibt |
Path, Value |
Der Registry-Ort, die Datei, die Aufgabe oder der wiederhergestellte Datensatz und dessen konfigurierter Inhalt |
Description, References |
Warum der Mechanismus wichtig ist und wo Sie mehr dazu lesen können |
AccessGained |
Der übliche Geltungsbereich des Mechanismus (USER oder SYSTEM; BITS kann auch LOCAL_SERVICE/NETWORK_SERVICE angeben); kein Beweis, dass ein bestimmter Befehl diese Berechtigung erlangt hat |
Severity, PolicyReason |
Klassifizierung durch das Profil, Erläuterung der zutreffenden Richtlinie und etwaige Einschränkung wegen teilweiser Übereinstimmung oder nicht verifiziertem Signierer |
SourceFile, RecordStatus |
Exakte gesicherte Quelle, deren Pfad mit der Eingabe wie übergeben beginnt (./HOST/... bei auto-parse), sowie Kontext zu Zuordnung/Wiedergabe/Wiederherstellung; verfolgen Sie dies bis zum ursprünglichen Beweis zurück |
KeyLastWrite |
Der Zeitstempel des Registry-Schlüssels. Er datiert keinen einzelnen Wert |
LastChange, ChangeSource, ChangeEvidence |
Unabhängig korrelierter Änderungszeitpunkt, Quellnachweis und ob die Korrelation gelungen ist |
ResolvedPath, ResolutionStatus, Exists |
Payload-Pfad und Ergebnis der Offline-Auflösung; nicht gesicherte Beweise sind unbekannt, nicht false |
SHA256 |
SHA256 der gesicherten Payload-Bytes, sofern lesbar |
Signer, SignerStatus |
Beschreibende eingebettete Zertifikats-/Katalogmetadaten und deren Verfügbarkeit; Vertrauenswürdigkeit des Zertifikats und Gültigkeit der Signatur werden nicht geprüft |
IsLolbin, Launcher |
Ob das konfigurierte Startprogramm oder die Payload in der mitgelieferten LOLBAS-Liste steht, und das für eine vermittelte Payload verwendete Startprogramm |
IsBuiltin, IsInOS-Directory |
Kontext für gängige Windows-Befehle und Systemverzeichnisse; keines der Felder belegt Legitimität |
Ein rundll32.exe-Befehl kann eine DLL-Payload benennen. Juntei bewahrt das Startprogramm, während es die Payload auflöst und
hasht. Ein Verweis außerhalb des gesicherten Computers, ein fehlendes Laufwerk, eine mehrdeutige
Übereinstimmung ohne Beachtung der Groß-/Kleinschreibung oder eine nicht aufgelöste Umgebungsvariable wird nicht durch eine Datei
vom Rechner der Analystin oder des Analysten ersetzt.
Zeitstempel und Einschränkungen¶
Der Hunter verwendet die Änderungszeiten kopierter Dateien auf der Analyse-VM nicht als Angriffszeitstempel.
Sofern verfügbar, korreliert er Registry-Schreibvorgänge mit Sysmon-Ereignis 13, Aufgabeninstallationen mit
Security 4698 oder Task Scheduler 106, Dienstinstallationen mit System 7045 und dateibasierte
Konfigurationen mit den ursprünglichen $MFT-Zeitstempeln. Die Herkunft erscheint in ChangeSource.
Ein Ereignis kann eine Konfigurationsänderung datieren, ohne zu beweisen, dass die konfigurierte Payload ausgeführt wurde.
Ereignis 6011 im lokalen System-Protokoll kann einen früheren Computernamen belegen. Der Hunter folgt verifizierten Umbenennungs-
ketten, die am gesicherten Computer verankert sind, behält dessen aktuellen Comp-Wert bei und zeichnet den
ursprünglichen Ereigniscomputer und den Nachweis des Umbenennungsdatensatzes in ChangeSource auf. Nicht belegte fremde Namen,
archivierte Protokolle, weitergeleitete Protokolle und eine andere Windows-Installation werden über diese Regel nicht akzeptiert.
Gesicherte Werte für ComputerName/ActiveComputerName, TCP/IP Hostname/NV Hostname sowie Hostname/FQDN aus Client-Informationen liefern Host-Aliase und decken DNS-/NetBIOS-Unterschiede sowie ausstehende Umbenennungen ab. Ohne gesicherte Identität kann ein einzelner Name in den primären Protokollen eine Datierung stützen, mit ausdrücklich als nicht verifiziert gekennzeichneter Identitätsherkunft und einer Abdeckungswarnung. Mehrere nicht verifizierte Namen werden dem Host nicht zugeordnet. Abgelehnte Computer- namen werden als Einschränkung der Korrelationsabdeckung gemeldet; ihre Kanäle werden dennoch als gesichert markiert.
Verwenden Sie --mft <FILE>, um für einen einzelnen Computer eine extern gesicherte MFT auszuwählen. Verwenden Sie --no-timeline,
um die Zeitstempelkorrelation zu überspringen. NOT_RUN, NOT_APPLICABLE, NO_ARTIFACT, NO_MATCH und REJECTED
erklären ein leeres LastChange; ein leeres Feld ist kein Beleg dafür, dass der Eintrag harmlos ist.
Die Wiederherstellung von WMI und BITS ist begrenztes Carving und kein vollständiger Parser für Datenbanktransaktionen. Wiederhergestellte Zeichenfolgen oder Bindungen können alte/gelöschte Daten enthalten; diese Datensätze müssen untermauert werden. WMI-Klassenschemata allein werden nicht als Abonnements gezählt. Ein TaskCache-Eintrag ohne gesicherte Aufgaben-XML-Datei ist eine zu prüfende Unstimmigkeit; eine Triage-Sammlung hat diese Datei möglicherweise einfach ausgelassen. Katalog- und PE-Metadaten sind nicht verifiziert und können in einer Sammlung fehlen. Prüfungen auf das Ersetzen von Dateien der Bedienungshilfen hängen von geeigneten Referenz-Signaturmetadaten ab; fehlende Katalogbelege dürfen nicht dazu führen, dass jede ausführbare Datei der Bedienungshilfen markiert wird.
Die Abdeckung wird für jede Prüfung aufgezeichnet, auch für Prüfungen ohne Befunde. complete bedeutet, dass die
zutreffende gesicherte Quelle gelesen wurde; es beweist nicht, dass die Sammlung vollständig ist oder dass
der Computer keine andere Persistenz aufweist. partial, not_collected, failed und disabled erklären
die Grenzen. Bewahren Sie --coverage Coverage.csv und das Parserprotokoll zusammen mit Ihren Befunden auf.
Die Portierung verwendet die CSV-/JSON-/JSONL-Formate von Juntei. Sie ruft weder das Upstream-Python-Programm auf, noch fragt sie Online-Anreicherungsdienste ab, noch bildet sie die HTML-/XLSX-Oberfläche von Upstream nach.