Detection: PowerShell 4104 Hunting

Description

The following analytic identifies suspicious PowerShell execution using Script Block Logging (EventCode 4104). It leverages specific patterns and keywords within the ScriptBlockText field to detect potentially malicious activities. This detection is significant for SOC analysts as PowerShell is commonly used by attackers for various malicious purposes, including code execution, privilege escalation, and persistence. If confirmed malicious, this activity could allow attackers to execute arbitrary commands, exfiltrate data, or maintain long-term access to the compromised system, posing a severe threat to the organization's security.

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

Data Source

Name Platform Sourcetype Source Supported App
Powershell Script Block Logging 4104 Windows icon Windows 'xmlwineventlog' 'XmlWinEventLog:Microsoft-Windows-PowerShell/Operational' N/A

Macros Used

Name Value
powershell (source=WinEventLog:Microsoft-Windows-PowerShell/Operational OR source="XmlWinEventLog:Microsoft-Windows-PowerShell/Operational")
powershell_4104_hunting_filter search *
powershell_4104_hunting_filter is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.

Annotations

- MITRE ATT&CK
+ Kill Chain Phases
+ NIST
+ CIS
- Threat Actors
ID Technique Tactic
T1059 Command and Scripting Interpreter Execution
T1059.001 PowerShell Execution
KillChainPhase.INSTALLATION
NistCategory.DE_AE
Cis18Value.CIS_10
APT19
APT32
APT37
APT39
Dragonfly
FIN5
FIN6
FIN7
Fox Kitten
Ke3chang
OilRig
Stealth Falcon
Whitefly
Windigo
APT19
APT28
APT29
APT3
APT32
APT33
APT38
APT39
APT41
APT5
Aquatic Panda
BRONZE BUTLER
Blue Mockingbird
Chimera
Cinnamon Tempest
Cobalt Group
Confucius
CopyKittens
DarkHydrus
DarkVishnya
Deep Panda
Dragonfly
Earth Lusca
Ember Bear
FIN10
FIN13
FIN6
FIN7
FIN8
Fox Kitten
GALLIUM
GOLD SOUTHFIELD
Gallmaker
Gamaredon Group
Gorgon Group
HAFNIUM
HEXANE
Inception
Indrik Spider
Kimsuky
Lazarus Group
LazyScripter
Leviathan
Magic Hound
Molerats
MoustachedBouncer
MuddyWater
Mustang Panda
Nomadic Octopus
OilRig
Patchwork
Poseidon Group
Sandworm Team
Sidewinder
Silence
Stealth Falcon
TA2541
TA459
TA505
TeamTNT
Threat Group-3390
Thrip
ToddyCat
Tonto Team
Turla
Volt Typhoon
WIRTE
Wizard Spider
menuPass

Default Configuration

This detection is configured by default in Splunk Enterprise Security to run with the following settings:

Setting Value
Disabled true
Cron Schedule 0 * * * *
Earliest Time -70m@m
Latest Time -10m@m
Schedule Window auto
Creates Risk Event False
This configuration file applies to all detections of type hunting.

Implementation

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

Risk Based Analytics (RBA)

Risk Message Risk Score Impact Confidence
Powershell was identified on endpoint $host$ by user $user$ executing suspicious commands. 80 80 100
The Risk Score is calculated by the following formula: Risk Score = (Impact * Confidence/100). Initial Confidence and Impact is set by the analytic author.

References

Detection Testing

Test Type Status Dataset Source Sourcetype
Validation Passing N/A N/A N/A
Unit Passing Dataset XmlWinEventLog:Microsoft-Windows-PowerShell/Operational xmlwineventlog
Integration ✅ Passing Dataset XmlWinEventLog:Microsoft-Windows-PowerShell/Operational xmlwineventlog

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: GitHub | Version: 5