PowerShell Quick Guide: Essential One-Liners Every Threat Hunter Should Know

PowerShell threat hunting one-liners are the equivalent of a paramedic's pocket card — not where you do the bulk of the work, but exactly what you reach for when something looks wrong and you need an answer right now. The collection below is the one we paste from memory during the first five minutes of looking at a possibly-compromised Windows host. Everything here is read-only and intended for authorised triage on systems you administer.

Key Takeaways

  • One-liners are for quick orientation, not continuous monitoring. For that, use a SIEM or EDR product such as Microsoft Defender for Endpoint.
  • The most useful triage signals are processes (parent-child + command line), services running from unusual paths, autorun registry entries, and outbound network connections.
  • Get-CimInstance beats Get-Process for triage because it exposes ParentProcessId, CommandLine, and creation timestamps.
  • -ErrorAction SilentlyContinue is essential when walking the filesystem or registry as a non-elevated user; without it, the output is buried in access-denied errors.
  • Pipe anything interesting to Export-Csv -Encoding UTF8BOM to share results with another analyst.

Environment

  • Windows 10/11 or Windows Server 2019/2022.
  • Windows PowerShell 5.1 or PowerShell 7.4 — every snippet works on both unless flagged.
  • Local administrator rights. Several queries silently truncate output without elevation.
  • Authorised access to the host. These commands are read-only but should still only run with permission.

The One-Liners

Top CPU consumers right now

Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 ProcessName, Id, CPU, @{N='MB';E={[math]::Round($_.WorkingSet64/1MB,1)}}

Quick orientation. Anything sitting at 80–100% CPU that you do not recognise is your first lead — particularly common with coin miners and unpacked loaders.

Processes with their parent and command line

$p = Get-CimInstance Win32_Process; $p | Select-Object ProcessId,Name,CommandLine,@{N='Parent';E={($p|? ProcessId -eq $_.ParentProcessId).Name}} | Sort-Object Parent,Name

Living-off-the-land abuse hides in this view. Look for Office applications, outlook.exe, or browser processes spawning cmd.exe, powershell.exe, wscript.exe, mshta.exe, or regsvr32.exe.

PowerShell command lines with suspicious arguments

Get-CimInstance Win32_Process -Filter "Name='powershell.exe' OR Name='pwsh.exe'" | Where-Object { $_.CommandLine -match '(-enc|-encodedcommand|frombase64string|downloadstring|downloadfile|-w hidden|-windowstyle hidden)' } | Select-Object ProcessId,ParentProcessId,CommandLine

Catches the classic encoded-payload patterns. Expect false positives from internal deployment tooling; build a known-good list before alerting.

Established connections to non-RFC1918 destinations

Get-NetTCPConnection -State Established | Where-Object { $_.RemoteAddress -notmatch '^10\.|^172\.(1[6-9]|2[0-9]|3[01])\.|^192\.168\.|^127\.|^::1' } | Select-Object LocalPort,RemoteAddress,RemotePort,@{N='Process';E={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}}

Filters out RFC 1918 ranges and loopback. Remaining rows are processes talking out to the public internet — handy for spotting unusual C2-style traffic.

Services running from temporary or user-writable paths

Get-CimInstance Win32_Service | Where-Object { $_.PathName -match 'temp|appdata|programdata|users\\public' } | Select-Object Name,DisplayName,PathName,StartName,State

Legitimate services almost never live in user-writable paths. Anything matching here deserves a closer look at the binary signature.

Services set to auto-start but currently stopped

Get-Service | Where-Object { $_.StartType -eq 'Automatic' -and $_.Status -eq 'Stopped' } | Select-Object Name,DisplayName,Status,StartType

Sometimes attackers disable defensive services (Defender, Windows Update, BITS) without unsetting auto-start. Compare against a known-good baseline.

Autorun entries from the four classic Run keys

'HKLM:\Software\Microsoft\Windows\CurrentVersion\Run','HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce','HKCU:\Software\Microsoft\Windows\CurrentVersion\Run','HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce' | ForEach-Object { Get-ItemProperty $_ -ErrorAction SilentlyContinue | Select-Object PSPath,* -ExcludeProperty PS* } 

The simplest persistence anchor. For broader coverage use Sysinternals Autoruns; this one-liner catches the most common locations.

Recently created executables outside Program Files

Get-ChildItem -Path C:\ -Include *.exe,*.dll,*.ps1,*.bat,*.cmd -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.CreationTime -gt (Get-Date).AddHours(-24) -and $_.FullName -notmatch 'Program Files|Windows\\(System32|SysWOW64|WinSxS|servicing|assembly)' } | Select-Object FullName,CreationTime,Length

Filesystem-level new-arrival check. Tune the time window and exclusion list to match what your environment legitimately drops.

Scheduled tasks created in the last seven days

Get-ScheduledTask | Get-ScheduledTaskInfo | Where-Object { $_.LastRunTime -gt (Get-Date).AddDays(-7) -or $_.NextRunTime -gt (Get-Date) } | Select-Object TaskName,LastRunTime,NextRunTime,LastTaskResult

Scheduled tasks are a top persistence mechanism. Cross-reference with the dedicated detection post linked below for deeper analysis.

Local admins (including nested group members)

Get-LocalGroupMember -Group 'Administrators' | Select-Object Name,PrincipalSource,ObjectClass

Anyone in Administrators who is not Administrator or your expected admin group is worth a question. Domain group nesting is resolved automatically.

Failed logons in the last hour, grouped by user and source IP

Get-WinEvent -FilterHashtable @{LogName='Security';Id=4625;StartTime=(Get-Date).AddHours(-1)} -ErrorAction SilentlyContinue | Select-Object @{N='User';E={$_.Properties[5].Value}},@{N='IP';E={$_.Properties[19].Value}} | Group-Object User,IP | Sort-Object Count -Descending | Select-Object Count,Name -First 20

The fastest way to confirm or rule out an active password attack. For a fleet-wide view, fan the same query out across all DCs with Invoke-Command.

Frequently Asked Questions

Are these one-liners safe to run on production systems?

All of them are read-only. The CPU impact is negligible on modern hardware. The only operational risk is the filesystem walk on C:\ — on a server with millions of files that can take minutes and produce a long list. Scope it tighter when in doubt.

Do I need to be a local administrator?

Some — yes. CommandLine on Win32_Process, the Security event log, and most registry hives under HKLM require elevation. Without it, the same one-liner silently returns fewer rows, which is misleading. Always run from an elevated shell.

Can I run these against remote machines?

Yes. Wrap any snippet in Invoke-Command -ComputerName $list -ScriptBlock { ... }. The returned objects are deserialised, so most downstream pipeline operators still work. See the remote management guide linked below.

Why not just use Defender for Endpoint or a SIEM?

You should — for ongoing monitoring. These one-liners are for the moment you do not have the tool, the agent has not yet been deployed, or you need to confirm something interactively before paging an analyst. They complement, not replace, proper telemetry.

How do I export the output for a colleague?

Append | Export-Csv -Path .\out.csv -NoTypeInformation -Encoding UTF8BOM to any of them. The CSV export guide linked below covers the encoding flags that keep Excel from mangling non-ASCII characters.

Conclusion

A useful one-liner is one you can type from memory at 2 a.m. when something is on fire. Pick the four or five from this list that map to the questions you most often ask, drop them in a profile module, and they become reflexes. They will not solve a real incident on their own — that is what your EDR, SIEM, and IR runbook are for — but they will get you to "is this actually a problem?" within minutes rather than hours.

Related Posts

Reference for the WMI/CIM provider that most of these snippets lean on: CIM Win32 Provider on Microsoft Learn.

0 comments:

Post a Comment