Mini-guide: a PowerShell alert in ninety seconds, in the order that settles it fastest
Most PowerShell alerts are administration. Five questions, ordered so the cheapest one that can close the alert comes first, with the answer that means stop and the answer that means keep going.
- ATT&CK
- T1059.001
PowerShell runs thousands of times a day on a managed estate. The skill is not spotting that it ran, it is deciding quickly which of the thousand matters. Ask these in order and stop as soon as one of them settles it.
The example
10:26:03 Event ID 1 Process Create Computer: HR-WS-041
Image: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
CommandLine: powershell -nop -w hidden -ep bypass -e SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkA...
ParentImage: C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE
User: MARLOWEFENN\j.achterberg
1. What started it? (ten seconds)
The parent is the fastest discriminator there is. A management agent, a login script host or an administrator's terminal are ordinary. An Office application, a browser, a PDF reader or a mail client is not: it means a document or a page executed code.
Here the parent is Excel. In most estates that alone justifies isolating the host, and everything below is about scope.
If the parent is ordinary, keep going. Operators who already have a shell start PowerShell from cmd.exe like everybody else.
2. Who, and at what privilege? (ten seconds)
A named user at medium integrity who is not in IT, running hidden PowerShell, is unusual. SYSTEM running it from a scheduled task may be your patching tool. Match the account to the job the machine does.
3. What do the switches say about intent? (twenty seconds)
-nop skips the profile, -w hidden hides the window, -ep bypass sets the
execution policy aside for this process, and -e takes a base64 command. Each
has a legitimate use. Hidden plus encoded, started by something a user
opened, does not.
Remember that PowerShell accepts any unambiguous prefix of a parameter name, so
-e, -en, -enc and -EncodedCommand are one switch. A rule or a search that
looks for one spelling misses the rest.
4. What did it actually run? (thirty seconds)
Decode the base64 (it is UTF-16LE, which is why every other byte is A). The
analyst tools page does it in your browser without sending the
string anywhere. The fragment above begins IEX (New-Object Net.WebClient): a
download cradle.
Better, if script block logging is enabled, event 4104 in the PowerShell operational log holds the script after decoding and deobfuscation, as the engine ran it. If that log is empty, note it as a finding: you are relying on being able to decode whatever you are given.
5. Did it reach the network? (twenty seconds)
10:26:04 Event ID 22 DNSEvent Image: ...\powershell.exe QueryName: update-greyline.example
10:26:04 Event ID 3 NetworkConnect Image: ...\powershell.exe DestinationIp: 198.51.100.170 DestinationPort: 443
A connection in the same second, to a name nobody recognises, is the second
stage arriving. From here the question is no longer whether this alert is real.
It is what the second stage did, and that is answered by everything
powershell.exe started next, and by what else in the estate has resolved that
name.
What ninety seconds bought you
Observed: Excel started a hidden, encoded PowerShell as j.achterberg on HR-WS-041, which resolved update-greyline.example and connected to 198.51.100.170. Assessed, with high confidence: a malicious document ran a downloader. Unknown: what was downloaded, and whether it ran.
That is enough to isolate the host and start the endpoint execution playbook. The Sigma endpoint pack has the rule that matches every abbreviation of the encoded switch.
Sources
The scenario above is invented. These are what its real half rests on.
Discussion
GuidelinesSign in to comment. Corrections and additions are the point: this is a working document.