Collect a Windows Endpoint First-Response Snapshot
When a Windows endpoint shows signs of compromise, collect a focused record of its current state before changing it where your incident plan permits. This snapshot includes host details, processes, network connections, Defender status, and recent system events.
Use an approved administrative session, follow the incident lead’s containment direction, and store the files in a restricted case location. Live response commands can affect the system and do not replace a forensic image or documented evidence-handling process.
Step 1: Create a Restricted Case Folder
Prepare an Evidence Collection Directory
Evidence HandlingOpen elevated PowerShell, create a uniquely named folder under ProgramData, and restrict inherited permissions so only Local System and local Administrators can read the collection. Keep the shell open for the remaining steps so the case path stays available.
$caseDir = Join-Path $env:ProgramData ('IR\' + (Get-Date -Format 'yyyyMMdd-HHmmss'))New-Item -ItemType Directory -Path $caseDir -Force | Out-Nullicacls $caseDir /inheritance:r /grant:r '*S-1-5-18:(OI)(CI)F' '*S-1-5-32-544:(OI)(CI)F'Get-Acl $caseDir | Format-List Owner, AccessToString@( "Collector: $env:USERDOMAIN\$env:USERNAME" "Started UTC: $([DateTime]::UtcNow.ToString('o'))") | Set-Content -Path (Join-Path $caseDir 'collection-notes.txt')❯ View Expected Console Output
processed file: C:\ProgramData\IR\20261004-101500Successfully processed 1 filesStep 2: Record Host, Process, and Network State
Capture the Current Endpoint State
System TriageSave basic system information, active processes, TCP connections, and local UDP endpoints with their owning process IDs. UDP is connectionless, so this records local endpoints rather than remote peer sessions. These queries do not terminate processes or change firewall rules, though collecting live state can update system metadata and may expose sensitive command lines or addresses.
Get-ComputerInfo | Select-Object CsName, WindowsProductName, WindowsVersion, OsBuildNumber, OsLastBootUpTime | Format-List | Out-File (Join-Path $caseDir 'host.txt')
Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, ExecutablePath, CreationDate, CommandLine | Export-Csv -NoTypeInformation (Join-Path $caseDir 'processes.csv')
Get-NetTCPConnection | Select-Object State, LocalAddress, LocalPort, RemoteAddress, RemotePort, OwningProcess | Export-Csv -NoTypeInformation (Join-Path $caseDir 'tcp-connections.csv')
Get-NetUDPEndpoint | Select-Object LocalAddress, LocalPort, OwningProcess | Export-Csv -NoTypeInformation (Join-Path $caseDir 'udp-endpoints.csv')❯ View Expected Console Output
host.txtprocesses.csvtcp-connections.csvudp-endpoints.csvStep 3: Save Defender Status and Recent System Events
Collect Security and Event-Log Context
Security TelemetryRecord Defender’s current status when the module is present and collect a bounded period of recent System events. Adjust the time window to the suspected activity timeline. Event timestamps are converted to UTC ISO 8601 in the export so they can be compared with the UTC collection note; note any event-log access errors.
if (Get-Command Get-MpComputerStatus -ErrorAction SilentlyContinue) { Get-MpComputerStatus | Select-Object AMServiceEnabled, AntivirusEnabled, RealTimeProtectionEnabled, AntivirusSignatureLastUpdated | Format-List | Out-File (Join-Path $caseDir 'defender-status.txt')} else { 'Get-MpComputerStatus is unavailable on this endpoint.' | Set-Content (Join-Path $caseDir 'defender-status.txt')}
$since = (Get-Date).AddHours(-2)Get-WinEvent -FilterHashtable @{ LogName = 'System' StartTime = $since} -MaxEvents 500 -ErrorAction Continue | Select-Object @{Name='TimeCreatedUtc'; Expression={ $_.TimeCreated.ToUniversalTime().ToString('o') }}, Id, ProviderName, LevelDisplayName, Message | Export-Csv -NoTypeInformation (Join-Path $caseDir 'recent-system-events.csv')❯ View Expected Console Output
defender-status.txtrecent-system-events.csvStep 4: Hash and Verify the Collected Files
Create a SHA-256 Manifest
Integrity CheckHash the collected files and immediately verify the manifest. If additional evidence is added later, create a new manifest and document the action in the case notes. A matching hash detects later changes to these files; it does not establish that collection was complete or that the live host was trustworthy.
$manifest = Join-Path $caseDir 'SHA256SUMS.csv'Get-ChildItem -Path $caseDir -File | Where-Object Name -ne 'SHA256SUMS.csv' | Get-FileHash -Algorithm SHA256 | Export-Csv -NoTypeInformation $manifest
Import-Csv $manifest | ForEach-Object { $actual = (Get-FileHash -LiteralPath $_.Path -Algorithm SHA256).Hash [pscustomobject]@{ File = Split-Path $_.Path -Leaf Verified = ($actual -eq $_.Hash) }}❯ View Expected Console Output
File Verified---- --------collection-notes.txt Truedefender-status.txt Truehost.txt Trueprocesses.csv Truerecent-system-events.csv Truetcp-connections.csv Trueudp-endpoints.csv True