PowerShell Live Response & Incident Triage Scripts
Essential non-destructive PowerShell commands and modular functions for live-response investigation during active incident triage.
🌐 1. Active Network Connections with Process Attribution
Section titled “🌐 1. Active Network Connections with Process Attribution”- 🎯 What it looks for: Established and listening TCP/UDP network connections, mapping each socket’s local and remote IP:Port directly to the owning Process ID, Process Name, executable file path, and exact command-line arguments.
- 💡 Why it matters: Standard netstat output only shows Process IDs, requiring manual correlation. Attackers operating C2 beacons or reverse shells often name their binaries after benign tools (
svchost.exe,update.exe); mapping the socket directly to the binary path reveals whether the connection is spawned from abnormal paths likeC:\Users\Public\,C:\ProgramData\, orAppData.
# Get active TCP connections mapped to Process Name and Command LineGet-NetTCPConnection -State Established, Listen | ForEach-Object { $conn = $_ $proc = Get-CimInstance Win32_Process -Filter "ProcessId = $($conn.OwningProcess)" [PSCustomObject]@{ LocalAddress = "$($conn.LocalAddress):$($conn.LocalPort)" RemoteAddress = "$($conn.RemoteAddress):$($conn.RemotePort)" State = $conn.State PID = $conn.OwningProcess ProcessName = $proc.Name Executable = $proc.ExecutablePath CommandLine = $proc.CommandLine }} | Sort-Object RemoteAddress | Out-GridView -Title "Active Sockets vs Process"⚡ 2. Process Parentage & Suspicious Hierarchy Triage
Section titled “⚡ 2. Process Parentage & Suspicious Hierarchy Triage”- 🎯 What it looks for: Command-line interpreters (
powershell.exe,cmd.exe,mshta.exe,wscript.exe) spawned by anomalous parent processes such as web application worker pools (w3wp.exe), SQL servers (sqlservr.exe), the print spooler (spoolsv.exe), or desktop shell processes. - 💡 Why it matters: Adversaries exploiting vulnerabilities (e.g. Log4j, web shells, remote code execution bugs) inherit the context of the vulnerable parent service. A database server or print spooler spawning PowerShell is almost always an active exploit attempt or privilege escalation payload.
# Extract process tree with parent attribution$processes = Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, ExecutablePath, CommandLine$procLookup = @{}$processes | ForEach-Object { $procLookup[$_.ProcessId] = $_.Name }
$processes | ForEach-Object { [PSCustomObject]@{ PID = $_.ProcessId ProcessName = $_.Name ParentPID = $_.ParentProcessId ParentName = $procLookup[$_.ParentProcessId] CommandLine = $_.CommandLine Path = $_.ExecutablePath }} | Where-Object { $_.ProcessName -in 'powershell.exe','cmd.exe','cscript.exe','wscript.exe','mshta.exe' -and $_.ParentName -in 'w3wp.exe','sqlservr.exe','spoolsv.exe','explorer.exe'} | Format-Table -AutoSize🔍 3. Unsigned Running Binaries Inspection
Section titled “🔍 3. Unsigned Running Binaries Inspection”- 🎯 What it looks for: All unique executables currently running in system memory that lack a valid cryptographic Authenticode digital signature, have revoked certificates, or are self-signed.
- 💡 Why it matters: Enterprise workstations run Microsoft-signed and trusted vendor software. Custom adversary payloads, Cobalt Strike beacons, compiled loaders, and ransomware executables are frequently unsigned or signed with fake, invalid certificates that fail chain verification.
# Identify unsigned or invalid signature executables running in memoryGet-Process | Select-Object -ExpandProperty Path -Unique | Where-Object { $_ } | ForEach-Object { $sig = Get-AuthenticodeSignature -FilePath $_ if ($sig.Status -ne 'Valid') { [PSCustomObject]@{ Status = $sig.Status SignerCert = $sig.SignerCertificate.Subject Path = $_ } }} | Format-Table -AutoSize📌 4. Fast Endpoint Persistence Audit
Section titled “📌 4. Fast Endpoint Persistence Audit”- 🎯 What it looks for: Inspects common autostart registry hives (
Run,RunOnce) across bothHKLM(system-wide) andHKCU(current user), including 32-bitWOW6432Nodelocations. - 💡 Why it matters: Registry Run keys remain one of the most reliable and frequently abused persistence vectors. Malware places payloads in user directories (
%APPDATA%,%TEMP%) and creates a Run key to guarantee execution upon every user logon without requiring local administrator rights.
# Registry Run & RunOnce Keys (User + System)$runPaths = @( "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run", "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce", "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run", "HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce", "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Run")
$runItems = foreach ($path in $runPaths) { if (Test-Path $path) { Get-ItemProperty -Path $path | Get-Member -MemberType NoteProperty | ForEach-Object { [PSCustomObject]@{ Hive = $path Entry = $_.Name Value = (Get-ItemProperty -Path $path).($_.Name) } } }}$runItems | Where-Object { $_.Entry -notmatch '^PS' } | Format-Table -AutoSize🕒 5. Active Scheduled Tasks Executing Script Interpreters
Section titled “🕒 5. Active Scheduled Tasks Executing Script Interpreters”- 🎯 What it looks for: Scheduled Tasks configured to invoke script interpreters (
powershell.exe,cmd.exe,rundll32.exe,mshta.exe,cscript.exe) along with their configured arguments and trigger state. - 💡 Why it matters: Attackers use scheduled tasks to maintain persistent footholds that trigger periodically (e.g. every 30 minutes) or upon system idle. Auditing tasks running command interpreters highlights obfuscated scripts, remote downloads, or beacon resurrectors.
# Filter scheduled tasks invoking cmd, powershell, or wscriptGet-ScheduledTask | Where-Object { $_.Actions.Execute -match '(powershell|cmd|cscript|wscript|mshta|rundll32)'} | Select-Object TaskName, TaskPath, State, @{N='Command';E={$_.Actions.Execute}}, @{N='Arguments';E={$_.Actions.Arguments}} | Format-Table -AutoSize📡 6. Dump Local DNS Resolver Cache
Section titled “📡 6. Dump Local DNS Resolver Cache”- 🎯 What it looks for: Inspects the client-side Windows DNS cache (
DnsClientCache), revealing all external domain names and hostnames resolved by local processes, along with their remaining Time-To-Live (TTL). - 💡 Why it matters: If an attacker runs a C2 beacon or drops an infostealer that contacts external command infrastructure, the domain is cached locally prior to network transmission. Even if the network socket has closed, the DNS cache preserves volatile evidence of C2 domains, dynamic DNS hosts, and webhook exfiltration endpoints.
# Inspect recent DNS lookupsGet-DnsClientCache | Where-Object { $_.Data -ne $null } | Select-Object Entry, RecordName, RecordType, Status, Data, TimeToLive | Sort-Object TimeToLive | Out-GridView -Title "DNS Cache Audit"