Windows on-disk forensics #

NTFS metadata

NTFS stores not just files but a parallel set of metadata files prefixed with $ that live in the volume root (hidden). An image gives you these for free and they survive deletion of individual user files for a surprisingly long time. In practice you'll pull the triage set, parse $MFT first to answer "did this file exist?", then $UsnJrnl / $LogFile for "what happened to it?", then $I30 to recover filenames out of directory listings whose MFT entries have been reused.

ArtifactWhat it provesHow it's generated / key factTimestampsParsers / tools
$MFTEvery file/dir that existed, incl. deleted entriesThe NTFS driver creates a 1 KB FILE record for every file and directory at creation, updates it on every metadata change, and on delete only marks it unused, so deleted entries survive until the record is reused. Each record holds $STANDARD_INFORMATION (SI), $FILE_NAME (FN) and $DATA (small files are stored inside the record itself).4 SI + 4 FN timestamps (MACB), 100-ns FILETIME UTC. SI changes with normal activity and all four values (incl. Changed) are settable from user mode (SetFileTime, SetFileInformationByHandle). FN is set by the kernel on create, rename and move - harder, but not impossible, to forge (SetMACE, move-rename trick).MFTECmd (Zimmerman), AnalyzeMFT (dkovar), mft2csv (jschicht), Autopsy, X-Ways, EnCase, Velociraptor Windows.NTFS.MFT
$LogFileTransaction journal (recent file ops)NTFS's own transaction log: the driver writes redo/undo records for every metadata change before committing it, so the volume can recover after a crash. Circular, about 64 MB by default - minutes to hours of history on a busy volume.Records are ordered by LSN, not stamped with their own wall-clock time; times come from the SI / FN values captured inside the redo and undo data. Sequence by LSN, date by the embedded attributes.LogFileParser (jschicht), ntfs-log-tracker (dkovar), Velociraptor
$UsnJrnl:$JChange journal - creates/renames/deletesThe Update Sequence Number journal. When enabled (default on system volumes) NTFS appends a record for each change to a file - create, overwrite, extend, rename, delete, security change, basic-info (timestamp) change, close - with the name, MFT and parent references and reason flags. Sparse, default max 32 MB, so days of history on active systems. Great for "what was staged then wiped".Per-record TimeStamp, FILETIME UTC, written by the kernel when the change is logged, not user-settable. A BASIC_INFO_CHANGE record on a file is the corroboration for timestomping.MFTECmd (-f $J), UsnJrnl2Csv (jschicht), fsutil usn readjournal
$I30 (INDX)Directory index - recovers deleted filenames in a folderEach directory's B+ tree index ($INDEX_ROOT / $INDEX_ALLOCATION) listing every child's name and a copy of its FN attribute. When entries are removed or nodes rebalance, old entries stay in slack space and can be carved, even after the MFT record is reused.Each entry holds the child's FN MACB as it was when indexed, a snapshot that can predate or outlive the current $MFT record.INDXParse (willi.ms), Velociraptor Windows.NTFS.Index
$Secure:$SDSSecurity descriptors (ACLs)Volume-wide store of unique security descriptors; each file's SI points to one by Security ID, so identical ACLs are stored once and a new ACL appends a new descriptor. Useful for post-breach permission changes.No timestamp per descriptor. Bound changes with the owning file's SI Changed time, $UsnJrnl SECURITY_CHANGE records and Security EID 4670 (if auditing is on).SDSParser, icacls (live), fsutil
Alternate Data StreamsHidden payloads bound to a fileExtra named $DATA streams on a file. Browsers, Outlook and other attachment-manager-aware apps write Zone.Identifier (Mark of the Web) when they save a download - ZoneId 3 = Internet, with ReferrerUrl / HostUrl on Win10+. Attackers strip MOTW, or stash scripts and payloads in streams.No timestamps of its own - streams share the host file's SI / FN. Zone.Identifier records URLs but no time; match it to browser download history.Streams.exe (Sysinternals), dir /r, Get-Item -Stream *, Autopsy
Trap: SI earlier than FN is an indicator of timestomping, not proof - copies across volumes, archive extraction, installers and sync clients all keep an old SI time legitimately, and FN can be forged too. Corroborate with a BASIC_INFO_CHANGE record in $UsnJrnl, $LogFile, zeroed sub-second values, and how the file arrived before you write "timestomped".

Execution evidence (what ran, when, by whom)

"Execution evidence" is the body of Windows features that happen to leave timestamped proof a program ran. None of them was designed as a forensic log - they exist for performance (Prefetch), compatibility (Amcache, ShimCache), battery usage reporting (SRUM/BAM), UI personalization (UserAssist), or activity sync (ActivitiesCache). Each has different fidelity, different enablement defaults, and different retention. Rank them, corroborate across several, and account for where each one is wrong before you call something executed.

ArtifactProof of execution?How it's generated / key factTimestampsParsers / tools
Prefetch
C:\Windows\Prefetch\<EXE>-<hash>.pf
Yes (on client Win10/11)Written by the Windows prefetcher (SysMain) to speed up launches: the kernel traces the files and folders a process touches in its first ~10 seconds, then writes or updates <EXE>-<path-hash>.pf, so the same exe run from two folders makes two files. Lists loaded files and volumes. MAM-compressed on Win10+, up to 1,024 files on Win8+. Disabled by default on Windows Server; an SSD does not disable it on clients.Up to 8 last-run times (Win8+) and a run count, FILETIME UTC, inside the file. The .pf's own creation time ≈ first run (if it hasn't aged out), modification ≈ last run. The prefetcher traces the first ~10 s after launch, so the .pf's times (and the embedded run times) land about 10 seconds after the process actually started - subtract it when sequencing at second level.PECmd (Zimmerman), WinPrefetchView (NirSoft), Prefetch Parser (Volatility plugin), KAPE module, Velociraptor Windows.Forensics.Prefetch
Amcache.hve
C:\Windows\AppCompat\Programs\Amcache.hve (+ .LOG1 / .LOG2)
Key: Root\InventoryApplicationFile
Presence + metadata (strong indicator)Registry hive maintained by the compatibility appraiser (the Microsoft Compatibility Appraiser task, program installs and launches) that inventories executables, drivers, installed programs and shortcuts. Root\InventoryApplicationFile holds path, size, publisher, version, PE link date and a SHA-1 (FileId) of the first 30 MiB (31,457,280 bytes) only - larger files won't match a full-file hash. Files can be inventoried without ever running.Each InventoryApplicationFile key's LastWrite ≈ when Windows catalogued the file, often near first run, but scans add files too. LinkDate = PE compile time (attacker-controlled). No run count.AmcacheParser (Zimmerman), RegRipper amcache.pl, Registry Explorer
ShimCache / AppCompatCache
Hive: C:\Windows\System32\config\SYSTEM
Key: SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache, value AppCompatCache
No - only that App Compat checked the fileThe kernel shim engine keeps the cache in memory and adds an entry whenever a file's compatibility is checked - on execution, but also when Explorer browses or inspects an executable - then writes it to SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache at shutdown or reboot. Up to 1,024 entries (path + the file's modified time); no reliable execution flag on Win10+. Often misreported as proof of execution.The timestamp is the file's $SI Modified time when it was cached, not when it ran. Only flushed at shutdown, so recent entries exist only in memory on a live host. List order roughly approximates insertion order; absolute times don't.AppCompatCacheParser (Zimmerman), ShimCacheParser (Mandiant), RegRipper appcompatcache.pl
SRUM
C:\Windows\System32\sru\SRUDB.dat
Provider list: SOFTWARE\Microsoft\Windows NT\CurrentVersion\SRUM\Extensions
Yes - with network bytes per app per userThe System Resource Usage Monitor service samples per-app, per-user resource use - CPU time, bytes sent and received per interface, energy, notifications - and writes it to this ESE database about hourly and at shutdown (the SOFTWARE\…\SRUM\Extensions key lists the provider DLL and GUID behind each table - collect the SOFTWARE hive too, since parsers use it to name tables and map network interfaces). Apps and SIDs are stored as IDs - join SruDbIdMapTable. Typically 30-60 days.TimeStamp is an OLE Automation date (ESE DateTime) for the hourly write - the activity happened during the preceding interval. Some columns (e.g. ConnectStartTime) are FILETIME. Precision ceiling ≈ 1 hour: good for "did rclone run between 02:00 and 03:00?", useless for sub-hour sequencing.SrumECmd (Zimmerman), srum-dump (Mark Baggett), ESEDatabaseView (NirSoft)
BAM/DAM
Hive: C:\Windows\System32\config\SYSTEM
Key: SYSTEM\CurrentControlSet\Services\bam\State\UserSettings\<SID> (Win10 1809+; 1709-1803: …\Services\bam\UserSettings\<SID>); DAM under …\Services\dam\
Yes - background activity monitorThe Background Activity Moderator driver (bam.sys, Win10 1709+) throttles background apps and records, per user SID, the full path of each executable the last time it ran. Not every process type is recorded.Each value begins with an 8-byte FILETIME UTC = last run under that user. One value per binary, overwritten each run - most recent only, no history.RegRipper bam.pl, Registry Explorer, KAPE module, Velociraptor Windows.Forensics.Bam, Belkasoft X
UserAssist
Hive: C:\Users\<user>\NTUSER.DAT
Key: NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{GUID}\Count
Yes - GUI launches via ExplorerExplorer writes it per user when a program or shortcut is launched through the shell - Start menu, desktop, Explorer double-click. Value names are ROT13 of the path or a known-folder GUID path. Not updated for command-line or script launches.Each value's blob: LastExecuted FILETIME UTC, run count, focus count and focus time (ms in the foreground). Last run only.RegRipper userassist.pl, UserAssistView (NirSoft), Registry Explorer
MUICache
Hive: C:\Users\<user>\AppData\Local\Microsoft\Windows\UsrClass.dat
Key: UsrClass.dat\Local Settings\Software\Microsoft\Windows\Shell\MuiCache
Weak - binary was shown to shellWhen the shell runs an executable it caches the program's display name (the FileDescription from its version resource) under UsrClass.dat\…\Shell\MuiCache, keyed by path. Shows the shell handled that path for this user. Supplementary.No per-value timestamp - the key's LastWrite bounds the most recent addition.RegRipper muicache.pl, MUICacheView (NirSoft)
ActivitiesCache.db (Timeline)
C:\Users\<user>\AppData\Local\ConnectedDevicesPlatform\<id>\ActivitiesCache.db (+ -wal)
Yes - per-user activitiesThe Connected Devices Platform service (CDPSvc) records user activities - app launches, documents opened, some clipboard activity - in a per-user SQLite DB under %LocalAppData%\ConnectedDevicesPlatform\<id>\. The Timeline UI is gone in Windows 11 and cloud sync ended in 2021, but the DB may still hold local activity - check the image rather than assume.StartTime, EndTime, LastModifiedTime, ExpirationTime are Unix epoch seconds (not FILETIME, easy to mis-convert). Retention about 30 days.WxTCmd (Zimmerman), Autopsy, SQLite browsers
RecentFileCache.bcf
C:\Windows\AppCompat\Programs\RecentFileCache.bcf
Legacy - Win7 eraWin7 / Server 2008 R2: the compatibility scanner records recently run executables here. Superseded by Amcache from Windows 8.No per-entry time; the .bcf file's own timestamps bound the last update.RecentFileCacheParser (Zimmerman), KAPE module, Velociraptor (KAPE targets)
CIT / Syscache.hve
CIT (mostly pre-Windows 10): SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\CIT\System (hive C:\Windows\System32\config\SOFTWARE)
Syscache: C:\System Volume Information\Syscache.hve
Supporting telemetryCIT: compatibility-telemetry usage aggregates under SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\CIT. Syscache.hve (System Volume Information, Win7 / 2008 R2) lists files the compatibility engine touched, by MFT reference. Niche, but useful corroboration.CIT stores aggregation windows (roughly daily buckets) as FILETIME, low-resolution corroboration only.CITParser (ANSSI), Registry Explorer
Common misreads: ShimCache does not prove execution - it shows the compatibility engine saw the file; use Prefetch, Amcache, SRUM, BAM or UserAssist for execution. An SSD does not turn Prefetch off on Windows 10/11 clients; it is off by default on Windows Server.

Shell & user activity

ArtifactWhat it provesHow it's generated / key factTimestampsParsers / tools
ShellBags
UsrClass.dat\Local Settings\Software\Microsoft\Windows\Shell\BagMRU + \Bags (Win7+; some in NTUSER.DAT\Software\Microsoft\Windows\Shell)
A user opened a folder - local, USB, network share, ZIP, Control Panel. Survives deletion of the folder.Explorer (and the common Open / Save dialog) saves per-folder view settings - size, position, sort, icon mode - the first time a user browses a folder, so the window reopens the same way. The folder's identity is stored as a chain of shell items in BagMRU, which mirrors the folder tree; settings go under Bags\<n>. Only folders opened through the shell get one - cd in a terminal doesn't.Shell items embed the folder's own MAC times as DOS date/time (2-second resolution) as they stood when the item was created, not the navigation time. Navigation time comes from the BagMRU key's LastWrite (FILETIME UTC) for the most recently opened child, ordered by MRUListEx.ShellBags Explorer / SBECmd (Zimmerman), RegRipper shellbags.pl, Velociraptor Windows.Forensics.Shellbags
Jump Lists
%AppData%\Microsoft\Windows\Recent\AutomaticDestinations\, …\CustomDestinations\
Files and folders a user opened with a specific app, plus pinned items, including from removable and network drives.Windows keeps an <AppID>.automaticDestinations-ms file per application (AppID = hash of the app's identity, so the filename tells you which app). Each time the app opens an item through the shell, an LNK-format stream for that item is added or updated inside the OLE compound file and the DestList stream is updated. customDestinations-ms files are written by the apps themselves (tasks, pinned items).Each DestList entry has a last-access FILETIME UTC and (Win10+) an access count. Each embedded LNK stream carries the target's own MAC times. The .automaticDestinations-ms file's own times bound first and last use of that app's list.JLECmd (Zimmerman), JumpListExplorer, Velociraptor (KAPE targets)
LNK files
%AppData%\Microsoft\Windows\Recent\, Office …\Office\Recent\, Desktop / Start Menu
A file or folder was opened by this user, and where it lived (volume serial and type, network share, machine name and MAC address).When a user opens a file through the shell, Explorer creates (or overwrites) a shortcut named after the target in Recent; one LNK per target name, updated on each re-open. The LNK records the target's path, size and MAC times, the volume's serial, type and label, and a tracker block with the originating NetBIOS name and MAC address. Deleted LNKs can often be carved from unallocated space, useful for USB tracking.Two sets: the target's MAC times as of the last update (FILETIME UTC, inside the LNK), and the LNK file's own times - created ≈ first opened, modified ≈ last opened.LECmd (Zimmerman), lnk-parser, Velociraptor Windows.Forensics.Lnk
Office TrustRecords
NTUSER.DAT\Software\Microsoft\Office\<ver>\<app>\Security\Trusted Documents\TrustRecords
The user trusted a document - and whether they enabled macros / active content or only editing.Office writes a value named after the document path when the user clicks Enable Editing (leaving Protected View) or Enable Content (macros / active content). Check the final DWORD of the value: FF FF FF 7F = Enable Content (macros allowed); 00 00 00 00 = Enable Editing only. Behaviour depends on Trust Center settings.The first 8 bytes are a FILETIME UTC = when the trust decision was recorded.RegRipper trustrecords.pl, Registry Explorer, dissect trusteddocs
OneDrive
%LocalAppData%\Microsoft\OneDrive\logs\, …\OneDrive\settings\<Personal|Business1>\
Files synced, uploaded, downloaded or deleted through OneDrive, including exfiltration to a personal account.The sync client writes obfuscated binary .odl logs as it works, and keeps a SQLite SyncEngineDatabase.db per account listing synced files and folders. Each signed-in account (personal or business) gets its own settings folder, so a personal account on a corporate laptop shows up as its own folder.ODL entries carry per-event timestamps (parsed to UTC by the tools); the database stores item metadata with its own time fields. Log files roll over, so collect early.OneDriveExplorer (Brian Maloney), odl.py (Yogesh Khatri), sqlite3
WER / LocalDumps
%ProgramData%\Microsoft\Windows\WER\ReportArchive\ and \ReportQueue\; LocalDumps folder from HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps
A process crashed or hung - often malware, an exploit, or a tool injected into the wrong process. Dumps can hold cleartext secrets and payloads.Windows Error Reporting (WerFault.exe, WerSvc) writes a Report.wer text file - faulting app path, module, exception code, loaded modules - and sometimes a minidump when a process crashes or hangs. If LocalDumps is configured, full dumps go to that folder too. The same crash is logged as Application EID 1000 / 1001.Report.wer has EventTime and UploadTime (FILETIME); the .dmp's own file times = when it was written; Application EID 1000 / 1001 give the same moment from the event log.Text editor, WinDbg, Volatility / MemProcFS for dumps

AI agent artifacts

AI coding agents and assistants run commands, read files and edit code as the user, so their transcripts are often the best execution log on the host - the prompt, every command, and the output the agent saw. The same files collect any secrets the agent read. Paths below are for Windows; ~ = %USERPROFILE%.

Trap: agent commands run through a non-interactive shell (powershell -Command / cmd /c), so they usually don't appear in PSReadLine history (ConsoleHost_history.txt). If EDR shows shells spawned by node.exe, claude.exe, codex.exe, Cursor.exe or Code.exe, the agent transcript is where the command lines and their output are recorded.
AgentWhereWhat it provesFormat, retention, notes
Terminal agents
Claude Code
(Anthropic)
%USERPROFILE%\.claude\projects\<encoded-cwd>\<session-uuid>.jsonl - full transcripts
%USERPROFILE%\.claude\history.jsonl - every prompt typed, with project path
%USERPROFILE%\.claude\file-history\ - pre-edit copies of files it changed
%USERPROFILE%\.claude\shell-snapshots\
%USERPROFILE%\.claude\debug\
%USERPROFILE%\.claude.json - per-project MCP servers, trusted folders, account
%USERPROFILE%\.claude\settings.json - permission allow-lists, hooks; also <repo>/.claude/settings*.json
Prompts, model replies, every tool call (shell command lines, file reads and writes, web fetches) and the tool output, with working directory and git branch. File-history lets you diff what it changed.JSONL, one event per line, ISO-8601 UTC timestamp on each. <encoded-cwd> is the project path with separators and dots turned into -. Transcripts older than cleanupPeriodDays (default 30) are deleted at startup - collect early. Optional OpenTelemetry export (CLAUDE_CODE_ENABLE_TELEMETRY) can mean a central copy in the SIEM. Enterprise policy: C:\ProgramData\ClaudeCode\managed-settings.json or C:\Program Files\ClaudeCode\ (varies by version).
Codex CLI
(OpenAI)
%USERPROFILE%\.codex\sessions\YYYY\MM\DD\rollout-*.jsonl - session transcripts
%USERPROFILE%\.codex\history.jsonl - prompt history
%USERPROFILE%\.codex\log\ - TUI / debug log
%USERPROFILE%\.codex\config.toml - approval mode, sandbox, MCP servers
Prompts, model output, shell commands and results, patches applied, token use.JSONL with timestamp / type / payload per line; the date folders bound session days. Newer builds add a SQLite index and may compress old rollouts (.jsonl.zst). approval_policy = "never", --yolo or --dangerously-bypass-approvals-and-sandbox = commands ran unreviewed.
Gemini CLI
(Google)
%USERPROFILE%\.gemini\tmp\<project-hash>\chats\ - auto-saved sessions
%USERPROFILE%\.gemini\tmp\<project-hash>\logs\ - plus checkpoints/ and /chat save tags
%USERPROFILE%\.gemini\history\<project-hash>\ - shadow git repo (checkpointing, off by default)
%USERPROFILE%\.gemini\settings.json - and GEMINI.md context files
Conversation and tool calls per project; the shadow repo holds file states before edits.JSON. The hash comes from the absolute project path - open every folder rather than computing it. --yolo / approvalMode = tool calls ran unprompted.
GitHub Copilot CLI%USERPROFILE%\.copilot\session-state\<session>\events.jsonl - plus workspace.yaml, plan.md, checkpoints/
%USERPROFILE%\.copilot\session-store.db - SQLite index (newer builds)
%USERPROFILE%\.copilot\logs\process-<ms-epoch>-<pid>.log
%USERPROFILE%\.copilot\config.json
Full session event history, plans and file checkpoints; one debug log per process.Older builds used history-session-state/. Log names carry a millisecond epoch and PID, a ready-made process start time to line up with EDR. COPILOT_HOME can relocate the folder.
Amazon Q Developer / Kiro CLI%TEMP%\qlog\ - logs
%USERPROFILE%\.aws\amazonq\, %USERPROFILE%\.kiro\ - config
chat.log covers startup, SDK calls and networking; AWS warns it can hold file paths, code, command output and account IDs.Temp-dir logs don't survive reboots or temp cleanup. Full prompt logging is an admin setting that writes to S3 - ask whether it's on. --trust-all-tools = no approval prompts.
AiderIn each repo: .aider.chat.history.md, .aider.input.history
%USERPROFILE%\.aider.conf.yml
Full chat as Markdown plus input history; aider also commits its own edits to git.Lives in the project, not the home dir - sweep for it, and check git log for aider: commits.
IDE agents
GitHub Copilot Chat / agent mode
(VS Code)
%APPDATA%\Code\User\workspaceStorage\<hash>\chatSessions\ - chat sessions
%APPDATA%\Code\User\workspaceStorage\<hash>\chatEditingSessions\ - files it changed
%APPDATA%\Code\User\globalStorage\github.copilot-chat\
%APPDATA%\Code\logs\<YYYYMMDDTHHMMSS>\window<n>\exthost\GitHub.copilot-chat\
Per-workspace chats including agent-mode tool calls and terminal commands; editing sessions show what it changed.JSON (newer builds JSONL). Map <hash> to a project with the workspace.json next to it; renaming or moving a project orphans the old folder, which stays on disk. Log folder names are editor launch times (local time).
Cursor%APPDATA%\Cursor\User\globalStorage\state.vscdb - table cursorDiskKV: composerData:<id> (session), bubbleId:<id>:<msg> (messages, tool calls, diffs)
%APPDATA%\Cursor\User\workspaceStorage\<hash>\state.vscdb - per-workspace chat list (ItemTable)
%USERPROFILE%\.cursor\mcp.json - and <repo>/.cursor/ rules and project MCP
%APPDATA%\Cursor\logs\
Agent conversations, the terminal commands it ran, the diffs it applied.SQLite with JSON values. Composer IDs are UUIDs, not time-ordered - sort on the timestamps inside the JSON. The schema changes between versions, so list keys first (SELECT key FROM cursorDiskKV). The DB can be gigabytes.
Windsurf
(Cascade)
%USERPROFILE%\.codeium\windsurf\ - mcp_config.json, memories/, Cascade conversation data
%APPDATA%\Windsurf\User\
%APPDATA%\Windsurf\logs\
Configured MCP servers, auto-generated memories about the user's projects, Cascade activity logs.Conversation files are a proprietary binary format (reported as encoded protobuf) - expect to work from logs, memories and file timestamps. Verify against the build.
Cline / Roo Code
(VS Code extensions)
%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\tasks\<task-id>\ - Cline
%APPDATA%\Code\User\globalStorage\rooveterinaryinc.roo-cline\tasks\<task-id>\ - Roo; same extensions also appear under the Cursor / Windsurf profiles
api_conversation_history.json = exactly what went to and from the model; ui_messages.json = what the user saw, incl. command approvals; task_metadata.json = files touched.Task IDs are millisecond epochs - the folder name is the task start time. checkpoints/ is a shadow git repo of the workspace.
Continue%USERPROFILE%\.continue\sessions\ - chat sessions (JSON)
%USERPROFILE%\.continue\config.yaml
%USERPROFILE%\.continue\dev_data\
Chat sessions and (if on) local usage data.Config shows which model endpoints, including self-hosted ones, it talked to.
Desktop assistants and local models
Claude Desktop%APPDATA%\Claude\logs\ - logs
%APPDATA%\Claude\claude_desktop_config.json - MCP servers
main.log, mcp.log (MCP connections), mcp-server-<name>.log (each server's stderr); the config lists every local MCP server's command line and env vars.Chat content is server side, not on disk. The MCP config often holds API keys in plaintext env vars - treat them as exposed if the host is compromised.
ChatGPT desktop%LOCALAPPDATA%\Packages\OpenAI.ChatGPT-Desktop_*\ (Store app - verify on the build)Cached conversations and app state.Content of record is server side (Enterprise Compliance API).
Ollama
(local models)
%LOCALAPPDATA%\Ollama\server*.log - server log
%USERPROFILE%\.ollama\history - ollama run prompts
%USERPROFILE%\.ollama\models\
API requests with client IP, model pulls (where models came from), interactive prompts.Listens on 11434; if bound to 0.0.0.0, the server log shows who else on the network used it.
LM Studio%USERPROFILE%\.lmstudio\conversations\ - saved chats (JSON)
%USERPROFILE%\.lmstudio\ - models, local server settings
Saved chats; local API server configuration.Like Ollama, an exposed local server is an abuse and data-exfil surface.
Server-side copies: enterprise plans keep their own record, often with longer retention than the endpoint - Claude Enterprise / Team audit logs and Compliance API, ChatGPT Enterprise Compliance API, GitHub org audit log (Copilot policy and seat events, not prompts), Google Workspace admin audit for Gemini, Purview for Microsoft 365 Copilot (CopilotInteraction audit records, prompt copies via eDiscovery), and S3 prompt logs for Amazon Q / Kiro. Ask for these in the first data request.

What to look for in the transcripts:

  • Commands it ran - timeline every shell tool call next to EDR process events.
  • Secrets it read - .env, cloud credential files, SSH keys, kube configs, browser profiles. What was read is in the transcript, so the transcript is now a copy of the secret.
  • Where data went - web fetches, curl, git push to unfamiliar remotes, new MCP servers pointing at external URLs.
  • Safety switches off - --dangerously-skip-permissions, --yolo, --trust-all-tools, broad allow rules, auto-approve. Check the settings file's mtime against the incident window.
  • Instructions the user didn't write - prompt injection arrives in tool output (a web page, issue, README or MCP response). Read the tool results just before an odd action.
  • Persistence - a planted CLAUDE.md, AGENTS.md, GEMINI.md, .cursor/rules, hook or MCP server re-runs the attacker's instructions every session.
  • Agents driven by malware - the August 2025 Nx "s1ngularity" npm compromise ran claude, gemini and q with permission checks off to hunt for secrets. The parent is a package script, not a terminal, and there's no matching user prompt. Record agent and extension versions too: a poisoned Amazon Q VS Code release (1.84.0, July 2025) shipped a wipe prompt.

Inventory (then copy; take SQLite files with their -wal / -shm files, or close the app first - recent rows often live only in the WAL. Check that your KAPE / Velociraptor / UAC targets actually cover these folders):

$targets = '.claude','.claude.json','.codex','.gemini','.copilot','.continue','.cursor','.codeium','.kiro','.aws\amazonq','.ollama','.lmstudio',
  'AppData\Roaming\Claude','AppData\Roaming\Code\User','AppData\Roaming\Code\logs','AppData\Roaming\Cursor\User','AppData\Roaming\Cursor\logs',
  'AppData\Roaming\Windsurf\User','AppData\Roaming\Windsurf\logs','AppData\Local\Ollama','AppData\Local\Temp\qlog'
Get-ChildItem C:\Users -Directory -Force | ForEach-Object {
  foreach ($t in $targets) {
    $p = Join-Path $_.FullName $t
    if (Test-Path -LiteralPath $p) { Get-Item -LiteralPath $p -Force | Select-Object FullName, LastWriteTimeUtc }
  }
}
Get-ChildItem C:\ -Recurse -Force -Filter .aider.chat.history.md -ErrorAction SilentlyContinue | Select-Object FullName, LastWriteTimeUtc
Timestamps: JSONL transcripts (Claude Code, Codex, Copilot CLI) carry an ISO-8601 UTC timestamp on every line. Cline task folders and Copilot CLI log names are millisecond Unix epochs. VS Code-family log folders are local-time YYYYMMDDTHHMMSS. SQLite stores (Cursor, state.vscdb) keep epoch-millisecond values inside JSON blobs - convert them and don't trust row order. Paths in this category change often: verify against the tool version on the host.

Registry hives & where they live

Registry timestamps 101: every key has a LastWrite timestamp (FILETIME UTC, 100-ns precision) = last time that key or any of its values was modified. Values do not have their own timestamps - if you need per-value time, you must infer from LastWrite or from an external log. Hive files on disk have their own $SI MACB (first create, last reg write back to disk). Transaction logs (.LOG1, .LOG2) hold recent changes not yet written into the hive - always parse the main hive with its logs or you'll miss recent writes.

HivePathWhat it holds
SYSTEMC:\Windows\System32\config\SYSTEMServices and drivers, ShimCache (AppCompatCache), BAM/DAM, MountedDevices, USB history (Enum\USBSTOR, Enum\USB), time zone, computer name, network interfaces, the boot key that protects SAM and SECURITY
SOFTWAREC:\Windows\System32\config\SOFTWAREInstalled programs (Uninstall), HKLM Run keys, Winlogon, NetworkList (networks and SSIDs joined), Windows version and install date, SRUM pending data
SAMC:\Windows\System32\config\SAMLocal accounts and groups, NT hashes (encrypted with the SYSTEM boot key), per-user last logon, password-set and failed-logon times
SECURITYC:\Windows\System32\config\SECURITYLSA secrets (Policy\Secrets: service account passwords, machine account key), cached domain logons as NL$1…NL$10 values under SECURITY\Cache (decryptable with the SYSTEM boot key)
DEFAULTC:\Windows\System32\config\DEFAULTHKU\.DEFAULT - settings used before anyone logs on and by the LocalSystem account (HKU\S-1-5-18)
NTUSER.DATC:\Users\<user>\NTUSER.DAT
Service accounts: C:\Windows\ServiceProfiles\LocalService\NTUSER.DAT, …\NetworkService\NTUSER.DAT
Per-user HKCU: Run keys, UserAssist, RecentDocs, RunMRU, TypedPaths, Explorer MRUs, TypedURLs
UsrClass.datC:\Users\<user>\AppData\Local\Microsoft\Windows\UsrClass.datPer-user HKCU\Software\Classes: ShellBags (Win7+), MUICache, per-user COM registrations and file associations
Amcache.hveC:\Windows\AppCompat\Programs\Amcache.hveProgram / file inventory written by the compatibility appraiser (see execution evidence). A separate hive, not mounted under HKLM, easy to forget to collect

Collect the logs with the hive: every hive has .LOG1 / .LOG2 transaction logs beside it (e.g. SYSTEM.LOG1) holding recent writes not yet flushed - parse hive + logs together. C:\Windows\System32\config\RegBack\ held automatic backups until Windows 10 1803; since then the files are still there but 0 KB unless EnablePeriodicBackup=1 was set under HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager. Older copies of hives may also sit in Volume Shadow Copies.

Registry parsers: Registry Explorer / RECmd (Zimmerman, GUI + CLI with bookmarks), RegRipper (Harlan Carvey, hundreds of plugins), YARP (python library), python-registry (Willi Ballenthin), hivex (libguestfs), Volatility 3 windows.registry.hivelist/userassist/printkey, MemProcFS virtual registry.

Event logs - high-value IDs

EVTX timestamps: every record has System/TimeCreated/@SystemTime in ISO-8601 UTC (100-ns FILETIME precision in the binary, serialized as ISO text in XML). The EventRecordID is a monotonically-increasing serial you should pair with the timestamp when sequencing events across a cleared/rotated log. Logs rotate when the file hits the max size set in the channel properties, default 20 MB for Security on Win10+. Record log size + oldest timestamp per channel at collection; a 20 MB Security log with only 2 days of events on a busy DC may mean the real evidence has already rolled.

IDChannelMeaning / use
4624SecuritySuccessful logon - LogonType is everything (see below)
4625SecurityFailed logon - spray/brute
4648SecurityLogon w/ explicit creds (RunAs, net use /u:) - lateral movement bellwether
4672SecuritySpecial privs assigned (admin logon)
4688SecurityProcess creation (enable cmdline logging policy)
4697SecurityService installed (Sysinternals PsExec = PSEXESVC; Impacket uses random names). Needs Audit Security System Extension - 7045 in System is always written
4698SecurityScheduled task created
4720/4722/4724/4728/4732/4738/4756SecurityUser created / enabled / pw reset / group adds / changes
4769Security (DC)TGS requested - RC4 (etype 0x17) + unusual service = Kerberoasting
4662Security (DC)Directory object access. DCSync = replication rights used by a non-DC account: {1131f6ad-9c07-11d1-f79f-00c04fc2dcd2} (DS-Replication-Get-Changes-All) or {89e95b76-444d-4c62-991a-0facbeda640c} (Get-Changes-In-Filtered-Set). {1131f6aa-…} (Get-Changes) alone is routine. Needs Directory Service Access auditing plus a SACL on the domain object.
5140 / 5145SecurityNetwork share accessed / detailed file-share access (which file, which share) - lateral SMB. Needs File Share auditing; 5145 is very noisy
7045SystemService installed - classic PsExec/Impacket random name
1102 / 104Security / SystemSecurity log cleared (1102) / any other log cleared (104) - hallmark of cover-up
4103 / 4104PowerShell/OperationalModule logging / Script block logging
400 / 403 / 600 / 800Windows PowerShellEngine start/stop, provider, pipeline
1116 / 1117DefenderMalware detected / action taken
Sysmon 1-29Microsoft-Windows-Sysmon/OperationalProcess, network, file, registry, WMI and DNS activity - see Sysmon event IDs below
EVTX parsers / detection: EvtxECmd (Zimmerman, w/ maps), Chainsaw (WithSecure, Sigma + hunt rules), Hayabusa (Yamato Security, Sigma w/ scoring), Zircolite (Sigma over EVTX via SQLite), EvtxHussar, DeepBlueCLI (Eric Conrad), APT-Hunter, python-evtx, Log Parser 2.2 (Microsoft), Timeline Explorer (Zimmerman) for review. Live triage: wevtutil, Get-WinEvent, Event Log Explorer.

Logon types (4624)

TypeMeaning
2Interactive (console/keyboard)
3Network (SMB, IIS, etc.)
4Batch (scheduled task)
5Service
7Unlock
8NetworkCleartext (basic auth, IIS)
9NewCredentials (runas /netonly) - worth checking; also produced by legitimate admin tools
10RemoteInteractive (RDP / Terminal)
11CachedInteractive (cached domain creds)
RDP is more than type 10: a fresh RDP logon is type 10, but reconnecting to a session can show type 7 (unlock), Network Level Authentication produces a type 3 first, and reconnect/disconnect fire 4778/4779. Correlate with TerminalServices / RemoteConnectionManager logs before counting RDP sessions.

Sysmon event IDs

Sysmon (Sysinternals System Monitor) is a driver and service that writes detailed process, file, registry, network and WMI activity to Microsoft-Windows-Sysmon/Operational (%SystemRoot%\System32\winevt\Logs\Microsoft-Windows-Sysmon%4Operational.evtx). It only exists if the client installed it, and it only logs what its XML config includes - with no config it records little beyond process creation, so check the config (sysmon -c) before you read an absence as "didn't happen". Every event carries UtcTime (when the activity happened, UTC) as well as the record's TimeCreated.

IDEventWhat it recordsInvestigative use
1Process creationImage, full command line, parent image and command line, user, integrity level, hashes, ProcessGuid / ParentProcessGuidThe backbone of a host timeline - process trees, LOLBin use, encoded PowerShell. Join other events on ProcessGuid (unique per process, unlike PIDs, which are reused).
2File creation time changedA process changed a file's creation time - old and new valueDirect timestomping evidence, with the process that did it. Expect noise from installers and sync clients.
3Network connectionTCP/UDP connections with process, user, source and destination IP / port, hostname if resolvedC2 and lateral movement from a specific process; off or heavily filtered in most configs because of volume.
4Sysmon service state changedSysmon started or stoppedGaps in coverage; a stop during the incident window can mean tampering.
5Process terminatedProcess end time and ProcessGuidGives process lifetime when paired with EID 1 - short-lived tools stand out.
6Driver loadedDriver path, hashes, signature and signature statusVulnerable or malicious drivers (BYOVD used to kill EDR); unsigned or unusual signers.
7Image loadedDLLs loaded by a process, with hashes and signatureDLL sideloading and unusual modules in trusted processes; very noisy, usually filtered to specific images.
8CreateRemoteThreadA process created a thread in another processClassic code-injection indicator; legitimate sources (e.g. some AV, debuggers) need baselining.
9RawAccessReadA process read a volume directly (\\.\ device access)Raw reads used to copy locked files such as NTDS.dit, hives or $MFT - legitimate backup and forensic tools do it too.
10Process accessA process opened another process, with the GrantedAccess mask and call traceCredential-dumping detection when the target is lsass.exe; check the source image and access mask against your baseline.
11File createdFile created or overwritten, with creating processDropped payloads, staging archives, files written to Startup or temp folders.
12Registry object created / deletedRegistry key or value created or deletedPersistence keys being added and cleanup afterwards.
13Registry value setRegistry value written, with the data (truncated if long)Run keys, service ImagePath, IFEO and other autostart changes with the writing process.
14Registry key / value renamedKey or value renamedRename-based evasion of registry monitoring.
15FileCreateStreamHashAlternate data stream created, with hash (and content for small streams)Zone.Identifier (Mark of the Web) on downloads - records the URL - and payloads hidden in streams.
16Sysmon config changedSysmon configuration state changedSomeone changed what Sysmon logs - check who, and compare old and new config.
17Pipe createdNamed pipe created, with processPipe names used by remote-execution and C2 frameworks; baseline normal pipes first.
18Pipe connectedClient connected to a named pipePairs with 17 to show which process talked over the pipe.
19WMI event filterWMI __EventFilter registeredWMI event-subscription persistence (with 20 and 21).
20WMI event consumerWMI consumer registered, with its command or scriptShows what the WMI subscription runs.
21WMI consumer-to-filter bindingFilter bound to consumerCompletes the subscription - all three together mean active WMI persistence.
22DNS queryDNS query and results, with the querying process (Win8.1+)Which process resolved a C2 or exfil domain - fills the gap when you only have network DNS logs.
23File delete (archived)File deleted, with a copy saved to the archive folderRecovers deleted payloads and scripts; needs ArchiveDirectory in the config and disk space.
24Clipboard changeClipboard contents changed (text archived)Rarely enabled; captures sensitive data, so use deliberately.
25Process tamperingProcess image changed in memory (hollowing, herpaderping)In-memory image replacement in a running process.
26File delete detectedFile deleted - logged only, no archive copyCleanup and anti-forensics timeline without the storage cost of 23.
27File block executableSysmon blocked creation of an executable (config-driven)Shows an attempt to drop an executable in a protected location.
28File block shreddingSysmon blocked a file-shredding attemptAnti-forensics attempt (e.g. secure-delete tools).
29File executable detectedAn executable file was created (logged, not blocked)New executables written to disk, with hashes - good for spotting dropped tools.
255ErrorSysmon internal errorCoverage gaps - check before concluding something didn't happen.
Configs to know: SwiftOnSecurity sysmon-config (baseline) and Olaf Hartong sysmon-modular (per-technique modules). Sysmon for Linux uses the same IDs for the events it supports and logs to syslog / the journal.

Persistence - the long tail

Windows exposes dozens of "ASEPs" (Autostart Extensibility Points): mechanisms Windows checks at boot, logon, or specific process start that an attacker can hijack to re-run their code. The sophistication curve runs from Run keys (any user, any malware, instantly spotted) up through signed-code validation hijacks (nation-state tier, hard to see without integrity scanning). Your job is to enumerate every ASEP, then compare each entry's binary and signer against what should be there. Sysinternals Autoruns and PersistenceSniper (Federico Lagrasta) are the standard sweeps; KAPE's RegistryHives + ASEP module + SharpUp cover the collected-image case; on live hosts at scale, Velociraptor's Windows.Sys.StartupItems and Windows.Persistence.PermanentWMIEvents do the same sweep.

Classic autoruns (loud, easy, still common)

  • Run / RunOnce keys - The simplest autostart. Any value under HKLM\Software\Microsoft\Windows\CurrentVersion\Run (system-wide, requires admin) or HKCU\…\Run (per-user, no privs needed) is launched by Explorer at logon; the data is the command line. RunOnce is deleted after it executes once; RunOnceEx processes its sections in order, synchronously. Also check the WOW6432Node variants on 64-bit systems. Trivial for commodity malware to drop - infostealers (Lumma, RedLine) love it. Hunt: every unknown binary; verify Authenticode signatures.
  • Startup folder - Any .lnk, .exe, or script dropped in %AppData%\Microsoft\Windows\Start Menu\Programs\Startup (per-user) or %ProgramData%\…\Startup (all-users) is executed at user logon. Often overlooked because it's "not registry." Parse LNK targets with LECmd.
  • Scheduled tasks - The Task Scheduler stores each task as an XML in C:\Windows\System32\Tasks\ (mirror in registry under Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree). Tasks can trigger on boot, logon, idle, event ID, or interval, and run as SYSTEM / NETWORK SERVICE / any user whose creds the task was created with. Attackers like them for durability (survive reboot) and masquerade (name a task MicrosoftEdgeUpdate). Watch for tasks with no author, hidden flag, UNC-path actions, or BASE64-encoded PowerShell. Audit via schtasks /query /fo list /v, Get-ScheduledTask, EID 4698 (created), 4702 (updated), 106/140 in Microsoft-Windows-TaskScheduler/Operational.
  • Services - Each entry under HKLM\SYSTEM\CurrentControlSet\Services\<svc> has ImagePath (exe), Start (0=boot driver, 1=system, 2=auto, 3=manual, 4=disabled), Type (kernel vs user), and optionally ServiceDll (for shared-process svchost services, under Parameters). Attackers either install a new service (classic Impacket/PsExec: random 4-letter service name, random 8-char binary, Type=0x10, Start=3) or hijack an existing one (overwrite ServiceDll of an unused service). Event IDs 7045 (install) and 4697 are your tells. Compare live service list to a known-good baseline.

Logon / UI-shell hijacks (DLL-level, higher stealth)

  • Winlogon Shell / Userinit - HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell defaults to explorer.exe; appending another binary (comma-separated) runs that too at logon. Userinit defaults to userinit.exe, and is called by Winlogon before Shell - same pattern. GinaDLL is legacy (pre-Vista) but still occasionally seen on old images.
  • AppInit DLLs - HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs. Any DLL listed here is loaded into every process that links user32.dll (nearly all GUI processes). Must be enabled via LoadAppInit_DLLs=1 and (post-Vista) signed. Ignored entirely when Secure Boot is on (Windows 8+), so it matters mainly on legacy-BIOS or Secure-Boot-off hosts.
  • AppCertDLLs - HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDlls. Loaded into any process that calls CreateProcess*. Broader reach than AppInit; even sneakier because it's not in the usual "Autoruns" chase list.
  • LSA Security / Notification Packages / Authentication Packages - Values under HKLM\SYSTEM\CurrentControlSet\Control\Lsa (Security Packages, Notification Packages, Authentication Packages). The LSA loads these DLLs in the LSASS process at boot. Perfect for credential harvesting (classic Mimikatz "SSP" trick registering mimilib.dll). An unknown SSP is a very high-signal detection.
  • Netsh helper DLLs - Under HKLM\SOFTWARE\Microsoft\Netsh. Loaded whenever netsh.exe runs, which happens frequently (scripts, GPOs, update processes). Attackers register a malicious helper so their code runs whenever a netsh is spawned.
  • Explorer shell extensions / ShellIconOverlayIdentifiers / context-menu handlers - DLLs registered under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers and various COM-handler keys get loaded into Explorer at logon. Rare but used by advanced actors to live inside a trusted process.

Image hijacks (make a legitimate binary load your code)

  • Image File Execution Options (IFEO) debugger hijack - HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<target.exe>\Debugger. Set to a path and Windows will launch that instead of the target, passing the target's command line as an argument. Originally a legit debugging feature. Classic abuse: hijack sethc.exe (sticky keys) with cmd.exe for an unauth SYSTEM shell at the lock screen; hijack a scheduled binary your victim's AV calls daily. Also abused via GlobalFlag=0x200 under this key, which turns on SilentProcessExit monitoring (configured under its own key - see below).
  • SilentProcessExit - HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\<target.exe> with ReportingMode (0x1 = launch MonitorProcess, 0x2 = write a dump, 0x4 = notify), MonitorProcess=<attacker.exe> and DumpType=2 (full memory), plus GlobalFlag=0x200 under the target's IFEO key. When the target is terminated, Windows launches the monitor and / or writes the dump (default folder %TEMP%\Silent Process Exit, or LocalDumpFolder) and logs it in the Application log with source Process Exit Monitor. Classic use: set target=lsass.exe, have the monitor collect the dump, SYSTEM-level credential harvesting with no third-party driver. Often seen in post-exploitation playbooks.
  • COM hijacking - Every COM class is identified by a GUID; the implementing DLL is registered under HKLM\Software\Classes\CLSID\{GUID}\InprocServer32 (system) or HKCU\Software\Classes\CLSID\{GUID}\InprocServer32 (per-user, takes precedence over HKLM for that user). Attackers point the per-user key at a malicious DLL; whenever any process in that user's context instantiates that CLSID, the malicious DLL loads. TreatAs adds another indirection - class A is "treated as" class B - letting the attacker intercept otherwise-protected system CLSIDs. Scheduled tasks that invoke COM, Explorer, Office - all are triggers. Use OleViewDotNet, or Autoruns to enumerate.
  • DLL search-order hijacking / sideloading / phantom DLL - Windows looks for a DLL in a specific search order: the loading .exe's directory first, then System32, PATH, etc. Drop a malicious DLL named like a dependency next to a signed binary (sideloading), or in a dir earlier in PATH, and the signed binary loads your code. Phantom DLL is when the binary tries to load a DLL that doesn't normally exist on disk - the attacker provides it. Lots of threat actors rely on this (e.g., signed vendor utilities and outdated Microsoft binaries shipped alongside a malicious DLL). Procmon on the CreateFile Not Found operations is the classic hunt.
  • Print Processors / Port Monitors - DLLs registered under HKLM\SYSTEM\CurrentControlSet\Control\Print\Environments\…\Print Processors and …\Monitors are loaded by the Print Spooler (spoolsv.exe, runs as SYSTEM). This is the PrintNightmare lineage (CVE-2021-34527) and seen in the wild with Winnti's PipeMon and Gelsemium (MITRE T1547.012) as stealthy SYSTEM persistence.
  • AppPaths - HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\<name.exe> maps a short name to a full path; start name or ShellExecute name dereferences through here. Overwrite an entry to redirect a common invocation.

Fileless / event-driven (hardest to see)

  • WMI event subscriptions - Three WMI classes form the trigger: __EventFilter (a WQL query that fires on an event - a timer, a logon, a process start), __EventConsumer (what to do: CommandLineEventConsumer runs a cmd, ActiveScriptEventConsumer runs a script, LogFileEventConsumer writes to a file), and __FilterToConsumerBinding (wires them together). All stored in C:\Windows\System32\wbem\Repository\OBJECTS.DATA. No file in Run, no scheduled task, no service - the trigger lives inside WMI. Classic APT tradecraft (APT29, Turla, FIN7). Hunt via Get-WmiObject -Namespace root\subscription -Class __EventFilter/__EventConsumer/__FilterToConsumerBinding, EID 5861 (consumer-to-filter binding activity), Autoruns -WMI, WMI-Monitor, PyWMIPersistenceFinder.
  • Office test persistence - HKCU\Software\Microsoft\Office test\Special\Perf - any DLL path under this undocumented key is loaded into every Office process (Word, Excel, Outlook) on launch. No prompt, no macro, no document. Pure registry trigger. If a user opens Outlook once a day, the DLL runs once a day. Patched by Microsoft's attention eventually, but still works on many fleets.
  • SIP / Trust Provider hijacking - Windows validates signed binaries by looking up a "Subject Interface Package" DLL (one per signature format: PE, Cabinet, MSI, Catalog). Entries live under HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptSIPDllGetSignedDataMsg\<OID> and …\CryptSIPDllVerifyIndirectData\<OID>, plus Trust Provider entries under …\Providers\Trust\FinalPolicy. Replace a SIP DLL with a wrapper that always returns "signature valid" and every signed-code check on the system (incl. sigcheck, Defender signature verifications) lies to you. Full write-up by Matt Graeber ("Subverting Trust in Windows"). Advanced-actor persistence that doubles as defense evasion.
  • Boot execution (BootExecute) - HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\BootExecute is a REG_MULTI_SZ of native-mode programs run during boot before Win32 subsystem starts (default: autocheck autochk *). Prepending a malicious native-mode binary gives earliest-possible-execution persistence. Rare but used.
  • BITS jobs - Background Intelligent Transfer Service (bitsadmin.exe / Start-BitsTransfer) can schedule a download that executes a command on completion (SetNotifyCmdLine). The job can be set to retry indefinitely across reboots. Jobs live in %ALLUSERSPROFILE%\Microsoft\Network\Downloader\qmgr*.dat or (newer) qmgr.db. Hunt: bitsadmin /list /allusers /verbose, BitsParser (FireEye), Microsoft-Windows-Bits-Client/Operational EID 59/60.

User-level / GPO / less-common but seen

  • Group Policy preferences (GPP) - SYSVOL-stored XML containing scheduled tasks, startup scripts, services, logon scripts. If an attacker has write access to \\<dc>\SYSVOL, they can push persistence to every joined machine. Watch for recent writes to Policies\{GUID}\Machine\Preferences\ScheduledTasks\ScheduledTasks.xml and friends.
  • Logon / startup scripts - HKLM\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts (and …\Group Policy\State\…\Scripts), local Group Policy script references under %SystemRoot%\System32\GroupPolicy\{User,Machine}\Scripts\{Startup,Logon,Shutdown,Logoff}.
  • Explorer DelegateExecute / Protocol handlers / URL handlers - Registering a protocol handler (HKCR\<scheme>\shell\open\command) runs your binary when a user clicks a scheme://… URL. Also hijacked for drive-by execution.
  • Screensaver - HKCU\Control Panel\Desktop\SCRNSAVE.EXE - the .scr is just a renamed PE. Idle-time execution. Niche but real.
  • Accessibility backdoor - Replace sethc.exe, utilman.exe, osk.exe, magnify.exe, narrator.exe or hijack them with IFEO. All are reachable from the pre-logon screen; abuse yields SYSTEM shell without authentication. Classic physical-access / stolen-image technique.
Persistence sweep tools: Autoruns / Autorunsc (Sysinternals, baseline), PersistenceSniper (Federico Lagrasta, PowerShell, 50+ techniques), SharpUp (GhostPack, privesc/persistence enum), Seatbelt (GhostPack, host survey), WinPEAS (ref), CimSweep (Matt Graeber, WMI across fleet), Kansa (Dave Hull), Velociraptor Windows.Persistence.* artifacts, Falcon RTR runscript + custom PowerShell.

Credential theft - artifacts and detection

Modern Windows stores credentials in a half-dozen locations. On a domain controller, the master store is NTDS.dit (an ESE database holding every object in Active Directory, including password hashes). On a workstation, the LSASS process holds whatever creds have been used since boot - NT hashes, Kerberos TGTs, cleartext passwords (for logon types that need them), and DPAPI master keys. On disk you'll find the SAM hive (local account hashes) and the SECURITY hive (LSA secrets, cached domain creds). The attacker's goal is almost always to get hashes they can crack or pass, or TGTs they can replay. Your job as DFIR is to answer "did they get it, and if so, what did they do with it after?"

  • LSASS dumping - categorize techniques, not just tools: comsvcs.dll MiniDump via rundll32, procdump -ma, Dumpert (direct syscall), nanodump, Taskmgr right-click, MiniDumpWriteDump through PPL bypass. Detect via Sysmon EID 10 to lsass with suspicious GrantedAccess masks (0x1010, 0x1410, 0x1438).
  • LSA Protection (PPL) and Credential Guard raise the bar; bypasses exist for PPL (e.g. vulnerable or signed drivers). Credential Guard moves secrets into the isolated LsaIso.exe process, so LSASS dumps on those hosts won't contain NT hashes or TGTs for protected accounts.
  • SAM/SECURITY offline - grab via reg save, VSS, raw NTFS read.
  • NTDS.dit - DC extraction via ntdsutil ifm, VSS, DCSync.
  • DCSync - detect via 4662 w/ replication GUID above; monitor replication rights (DS-Replication-Get-Changes-All).
  • Kerberos abuse - Kerberoasting (TGS-REP RC4), AS-REP Roasting (accounts with pre-auth disabled), Golden/Silver tickets, S4U2Self/S4U2Proxy (constrained/RBCD).
  • Shadow Credentials - attacker writes msDS-KeyCredentialLink to request PKINIT auth.
  • Zerologon (CVE-2020-1472), PetitPotam, PrinterBug → NTLM relay to AD CS → AD CS abuse (ESC1-ESC16 as catalogued since Certified Pre-Owned).
  • DPAPI - %AppData%\Microsoft\Protect\<SID>\<MasterKey>; chromium cookie DPAPI v10/v20 wrapped w/ app-bound key; infostealer workflow.

Lateral movement - what each pivot leaves behind

Every lateral-movement vector produces traces on both hosts - a client-side artifact on the source (what the attacker used to pivot) and a server-side artifact on the target (the authentication, the service install, the file created). Always correlate both sides: a 4624 Type 3 on the target with no matching outbound logon on the putative source means the real source is somewhere else and you haven't fully scoped yet.

VectorSource host artifactsTarget host artifacts
RDPmstsc Jump List, bitmap cache %LocalAppData%\Microsoft\Terminal Server Client\Cache, default.rdp, 1024/1102 TerminalServices-RDPClient4624 type 10, 4778/4779 session reconnect/disconnect, RemoteConnectionManager EID 1149
SMB (admin$)- (depends on tool)5140/5145, 4624 type 3
PsExec / Impacket psexecExec'd psexec.exe (Sysmon 1)7045 service install (random name on Impacket), 4697, PSEXESVC in Services, named pipe
WMI (wmiexec.py)If the source is Windows: process creation of wmic / PowerShell WMI cmdlets; outbound 135 + dynamic RPCWMI-Activity/Operational 5857-5861; child processes under WmiPrvSE.exe; 4624 type 3; __EventFilter / __EventConsumer if persistent
WinRMHTTP 5985/5986 outbound4624 type 3, wsmprovhost.exe hosting the remote session, Microsoft-Windows-WinRM/Operational, PowerShell 4103/4104
SSH (OpenSSH Server)ssh.exe process creation; %USERPROFILE%\.ssh\known_hostsOpenSSH/Operational and OpenSSH/Admin event logs (or %ProgramData%\ssh\logs\sshd.log if SyslogFacility LOCAL0 is set)

Anti-forensics & cover-up

  • wevtutil cl, Clear-EventLog → Security EID 1102 (Security log) / System EID 104 (any other log)
  • Volume Shadow Copy deletion (vssadmin delete shadows, wmic shadowcopy delete, vssadmin resize shadowstorage), ransomware signature; detect on the command line (4688 / Sysmon 1). VSS EID 8224 is only the service's idle shutdown, not a deletion indicator
  • Timestomping (SI vs FN divergence)
  • cipher /w, fsutil usn deletejournal, sdelete
  • Clearing MRU keys, UserAssist deletion
  • Disabling Defender / tamper protection (Defender Operational EID 5001 real-time protection disabled, 5007 configuration changed)
Lateral & credential tooling (defender & reference-of-attacker): BloodHound/SharpHound + BloodHound CE for AD attack-path graphs, PingCastle and Purple Knight for AD hygiene, ADRecon, Impacket suite (attacker-ref: secretsdump, wmiexec, psexec, GetUserSPNs), Rubeus (ref), mimikatz (ref), pypykatz (defensive LSASS parse), DSInternals for NTDS/SAM offline, BMC-Tools (ANSSI) for RDP bitmap cache, Volatility 3 windows.registry.lsadump / windows.registry.hashdump / windows.registry.cachedump.