Try in Splunk Security Cloud

Description

The following Hunting analytic assists with identifying suspicious PowerShell execution using Script Block Logging, or EventCode 4104. This analytic is not meant to be ran hourly, but occasionally to identify malicious or suspicious PowerShell. This analytic is a combination of work completed by Alex Teixeira and Splunk Threat Research Team.

  • Type: Hunting
  • Product: Splunk Enterprise, Splunk Enterprise Security, Splunk Cloud

  • Last Updated: 2023-12-27
  • Author: Michael Haag, Splunk
  • ID: d6f2b006-0041-11ec-8885-acde48001122

Annotations

ATT&CK

ATT&CK

ID Technique Tactic
T1059 Command and Scripting Interpreter Execution
T1059.001 PowerShell Execution
Kill Chain Phase
  • Installation
NIST
  • DE.AE
CIS20
  • CIS 10
CVE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
`powershell` EventCode=4104 
| eval DoIt = if(match(ScriptBlockText,"(?i)(\$doit)"), "4", 0) 
| eval enccom=if(match(ScriptBlockText,"[A-Za-z0-9+\/]{44,}([A-Za-z0-9+\/]{4}
|[A-Za-z0-9+\/]{3}=
|[A-Za-z0-9+\/]{2}==)") OR match(ScriptBlockText, "(?i)[-]e(nc*o*d*e*d*c*o*m*m*a*n*d*)*\s+[^-]"),4,0) 
| eval suspcmdlet=if(match(ScriptBlockText, "(?i)Add-Exfiltration
|Add-Persistence
|Add-RegBackdoor
|Add-ScrnSaveBackdoor
|Check-VM
|Do-Exfiltration
|Enabled-DuplicateToken
|Exploit-Jboss
|Find-Fruit
|Find-GPOLocation
|Find-TrustedDocuments
|Get-ApplicationHost
|Get-ChromeDump
|Get-ClipboardContents
|Get-FoxDump
|Get-GPPPassword
|Get-IndexedItem
|Get-Keystrokes
|LSASecret
|Get-PassHash
|Get-RegAlwaysInstallElevated
|Get-RegAutoLogon
|Get-RickAstley
|Get-Screenshot
|Get-SecurityPackages
|Get-ServiceFilePermission
|Get-ServicePermission
|Get-ServiceUnquoted
|Get-SiteListPassword
|Get-System
|Get-TimedScreenshot
|Get-UnattendedInstallFile
|Get-Unconstrained
|Get-VaultCredential
|Get-VulnAutoRun
|Get-VulnSchTask
|Gupt-Backdoor
|HTTP-Login
|Install-SSP
|Install-ServiceBinary
|Invoke-ACLScanner
|Invoke-ADSBackdoor
|Invoke-ARPScan
|Invoke-AllChecks
|Invoke-BackdoorLNK
|Invoke-BypassUAC
|Invoke-CredentialInjection
|Invoke-DCSync
|Invoke-DllInjection
|Invoke-DowngradeAccount
|Invoke-EgressCheck
|Invoke-Inveigh
|Invoke-InveighRelay
|Invoke-Mimikittenz
|Invoke-NetRipper
|Invoke-NinjaCopy
|Invoke-PSInject
|Invoke-Paranoia
|Invoke-PortScan
|Invoke-PoshRat
|Invoke-PostExfil
|Invoke-PowerDump
|Invoke-PowerShellTCP
|Invoke-PsExec
|Invoke-PsUaCme
|Invoke-ReflectivePEInjection
|Invoke-ReverseDNSLookup
|Invoke-RunAs
|Invoke-SMBScanner
|Invoke-SSHCommand
|Invoke-Service
|Invoke-Shellcode
|Invoke-Tater
|Invoke-ThunderStruck
|Invoke-Token
|Invoke-UserHunter
|Invoke-VoiceTroll
|Invoke-WScriptBypassUAC
|Invoke-WinEnum
|MailRaider
|New-HoneyHash
|Out-Minidump
|Port-Scan
|PowerBreach
|PowerUp
|PowerView
|Remove-Update
|Set-MacAttribute
|Set-Wallpaper
|Show-TargetScreen
|Start-CaptureServer
|VolumeShadowCopyTools
|NEEEEWWW
|(Computer
|User)Property
|CachedRDPConnection
|get-net\S+
|invoke-\S+hunter
|Install-Service
|get-\S+(credent
|password)
|remoteps
|Kerberos.*(policy
|ticket)
|netfirewall
|Uninstall-Windows
|Verb\s+Runas
|AmsiBypass
|nishang
|Invoke-Interceptor
|EXEonRemote
|NetworkRelay
|PowerShelludp
|PowerShellIcmp
|CreateShortcut
|copy-vss
|invoke-dll
|invoke-mass
|out-shortcut
|Invoke-ShellCommand"),1,0) 
| eval base64 = if(match(lower(ScriptBlockText),"frombase64"), "4", 0) 
| eval empire=if(match(lower(ScriptBlockText),"system.net.webclient") AND match(lower(ScriptBlockText), "frombase64string") ,5,0) 
| eval mimikatz=if(match(lower(ScriptBlockText),"mimikatz") OR match(lower(ScriptBlockText), "-dumpcr") OR match(lower(ScriptBlockText), "SEKURLSA::Pth") OR match(lower(ScriptBlockText), "kerberos::ptt") OR match(lower(ScriptBlockText), "kerberos::golden") ,5,0) 
| eval iex=if(match(ScriptBlockText, "(?i)iex
|invoke-expression"),2,0) 
| eval webclient=if(match(lower(ScriptBlockText),"http") OR match(lower(ScriptBlockText),"web(client
|request)") OR match(lower(ScriptBlockText),"socket") OR match(lower(ScriptBlockText),"download(file
|string)") OR match(lower(ScriptBlockText),"bitstransfer") OR match(lower(ScriptBlockText),"internetexplorer.application") OR match(lower(ScriptBlockText),"xmlhttp"),5,0) 
| eval get = if(match(lower(ScriptBlockText),"get-"), "1", 0) 
| eval rundll32 = if(match(lower(ScriptBlockText),"rundll32"), "4", 0) 
| eval suspkeywrd=if(match(ScriptBlockText, "(?i)(bitstransfer
|mimik
|metasp
|AssemblyBuilderAccess
|Reflection\.Assembly
|shellcode
|injection
|cnvert
|shell\.application
|start-process
|Rc4ByteStream
|System\.Security\.Cryptography
|lsass\.exe
|localadmin
|LastLoggedOn
|hijack
|BackupPrivilege
|ngrok
|comsvcs
|backdoor
|brute.?force
|Port.?Scan
|Exfiltration
|exploit
|DisableRealtimeMonitoring
|beacon)"),1,0) 
| eval syswow64 = if(match(lower(ScriptBlockText),"syswow64"), "3", 0) 
| eval httplocal = if(match(lower(ScriptBlockText),"http://127.0.0.1"), "4", 0) 
| eval reflection = if(match(lower(ScriptBlockText),"reflection"), "1", 0) 
| eval invokewmi=if(match(lower(ScriptBlockText), "(?i)(wmiobject
|WMIMethod
|RemoteWMI
|PowerShellWmi
|wmicommand)"),5,0) 
| eval downgrade=if(match(ScriptBlockText, "(?i)([-]ve*r*s*i*o*n*\s+2)") OR match(lower(ScriptBlockText),"powershell -version"),3,0) 
| eval compressed=if(match(ScriptBlockText, "(?i)GZipStream
|::Decompress
|IO.Compression
|write-zip
|(expand
|compress)-Archive"),5,0) 
| eval invokecmd = if(match(lower(ScriptBlockText),"invoke-command"), "4", 0) 
| addtotals fieldname=Score DoIt, enccom, suspcmdlet, suspkeywrd, compressed, downgrade, mimikatz, iex, empire, rundll32, webclient, syswow64, httplocal, reflection, invokewmi, invokecmd, base64, get 
| stats values(Score) by UserID, Computer, DoIt, enccom, compressed, downgrade, iex, mimikatz, rundll32, empire, webclient, syswow64, httplocal, reflection, invokewmi, invokecmd, base64, get, suspcmdlet, suspkeywrd 
| rename Computer as dest, UserID as user 
| `powershell_4104_hunting_filter`

Macros

The SPL above uses the following Macros:

:information_source: powershell_4104_hunting_filter is a empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.

Required fields

List of fields required to use this analytic.

  • _time
  • ScriptBlockText
  • Opcode
  • Computer
  • UserID
  • EventCode

How To Implement

The following Hunting analytic requires PowerShell operational logs to be imported. Modify the powershell macro as needed to match the sourcetype or add index. This analytic is specific to 4104, or PowerShell Script Block Logging.

Known False Positives

Limited false positives. May filter as needed.

Associated Analytic Story

RBA

Risk Score Impact Confidence Message
80.0 80 100 Powershell was identified on endpoint $host$ by user $user$ executing suspicious commands.

:information_source: The Risk Score is calculated by the following formula: Risk Score = (Impact * Confidence/100). Initial Confidence and Impact is set by the analytic author.

Reference

Test Dataset

Replay any dataset to Splunk Enterprise by using our replay.py tool or the UI. Alternatively you can replay a dataset into a Splunk Attack Range

source | version: 4