Attackers Love PowerShell. Here’s How to Catch Them.
Adversary Lab Notes
PowerShell is the most abused tool in Windows environments. Attackers use it because it’s already there, it’s trusted, and it can do almost anything.
In this note we’ll look at how to hunt for suspicious PowerShell execution using Sysmon logs in Log Analytics.
The Query
Event
| where Source == "Microsoft-Windows-Sysmon"
| where EventID == 1
| where TimeGenerated > ago(24h)
| where EventData has "powershell"
| where EventData has_any ("-enc", "-e ", "-ep bypass", "-nop", "hidden", "downloadstring", "frombase64")
| extend CommandLine = extract(@'CommandLine">([^<]+)', 1, EventData)
| extend User = extract(@'User">([^<]+)', 1, EventData)
| extend ParentProcess = extract(@'ParentCommandLine">([^<]+)', 1, EventData)
| project TimeGenerated, Computer, User, CommandLine, ParentProcessWhat You’re Hunting
-enc / -e — Encoded command, hiding the payload
-ep bypass — Execution policy bypass, ignoring restrictions
-nop — No profile, avoiding logged startup scripts
hidden — Hidden window, user can’t see it running
downloadstring — Fetching code from the internet
frombase64 — Decoding obfuscated payloads
That encoded string? It decodes to Write-Host "hello world". Harmless in this case. But the pattern, encoded command spawned from another shell, is exactly what attackers do.
Why Parent Process Matters
The ParentProcess column tells you what launched PowerShell.
Typically Normal Activities:
explorer.exe (user clicked something),
pwsh.exe or cmd.exe (admin working)
Suspicious Activities:
winword.exe or excel.exe (macro execution),
wmiprvse.exe (WMI lateral movement),
mshta.exe (HTA dropper)
🚨Note 🚨: "normal" processes can still be abused, so the key differentiator is often the command-line arguments and child processes spawned rather than the parent alone.
🔑 Key Insight: The command line tells you what ran. The parent process tells you why it ran. Both matter for investigation.
No Defender for Endpoint?
This query uses Sysmon Event ID 1 (process creation) flowing to Log Analytics via Azure Monitor Agent. You don’t need MDE to hunt PowerShell — you just need the right logs.
If you have MDE, the same hunt is cleaner:
DeviceProcessEvents
| where FileName == "powershell.exe"
| where ProcessCommandLine has_any ("-enc", "-ep bypass", "-nop", "hidden", "downloadstring")
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessCommandLineSame logic but easier to parse with prettier fields.
📝 Next Note: Scope Any Incident to a Time Window
Want to Practice in Your Own Azure Lab?
If you don’t have an Azure tenant to test in, or you want to ask questions when you get stuck, the Adversary Lab Community is where that happens.
Weekly discussions on Azure security and detection engineering
Q&A when your queries don’t work
Early access to exclusive content
👉 Join Adversary Lab Community
See you next time! 👋


