YARA Rules
Rule 1: Direwolf Core Malware Detection
yara
rule Direwolf_Infostealer_Core
{
meta:
description = "Detects Direwolf information stealer core components"
author = "SOC Threat Intelligence"
date = "2024-12-25"
severity = "critical"
malware_family = "Direwolf"
target_platform = "Windows"
strings:
// Credential harvesting patterns
$cred1 = "Login Data" wide ascii
$cred2 = "logins.json" wide ascii
$cred3 = "Cookies" wide ascii
$cred4 = "Web Data" wide ascii
$cred5 = "encrypted_key" ascii
$cred6 = "password_value" ascii
// Cryptocurrency wallet targeting
$crypto1 = "wallet.dat" ascii wide
$crypto2 = "\\Ethereum\\keystore\\" wide
$crypto3 = "\\Electrum\\wallets\\" wide
$crypto4 = "\\Exodus\\exodus.wallet" wide
$crypto5 = "metamask" nocase ascii
$crypto6 = "private_key" ascii
$crypto7 = "seed_phrase" ascii
// Browser targeting
$browser1 = "Google\\Chrome\\User Data" wide
$browser2 = "Mozilla\\Firefox\\Profiles" wide
$browser3 = "Microsoft\\Edge\\User Data" wide
$browser4 = "Opera Software\\Opera Stable" wide
$browser5 = "BraveSoftware\\Brave-Browser" wide
// Clipboard monitoring
$clip1 = "GetClipboardData" ascii
$clip2 = "SetClipboardViewer" ascii
$clip3 = "OpenClipboard" ascii
$clip4 = {68 00 02 00 00 FF 15} // clipboard API pattern
// Keylogging functionality
$keylog1 = "GetAsyncKeyState" ascii
$keylog2 = "SetWindowsHookEx" ascii
$keylog3 = "WH_KEYBOARD_LL" ascii
$keylog4 = "VK_" ascii
// C2 communication
$c2_1 = "api/checkin" ascii
$c2_2 = "api/upload" ascii
$c2_3 = "api/command" ascii
$c2_4 = "X-Client-ID" ascii
$c2_5 = "X-Bot-Version" ascii
condition:
uint16(0) == 0x5a4d and
(
(3 of ($cred*) and 2 of ($browser*)) or
(2 of ($crypto*) and 2 of ($cred*)) or
(2 of ($clip*) and 2 of ($keylog*)) or
(3 of ($cred*) and 2 of ($c2_*)) or
(2 of ($crypto*) and 2 of ($clip*) and any of ($c2_*))
) and filesize < 5MB
}
Rule 2: Direwolf PowerShell Dropper
yara
rule Direwolf_PowerShell_Dropper
{
meta:
description = "Detects PowerShell-based Direwolf droppers"
author = "SOC Threat Intelligence"
severity = "high"
malware_family = "Direwolf"
strings:
// PowerShell evasion
$ps1 = "-ExecutionPolicy Bypass" ascii wide nocase
$ps2 = "-WindowStyle Hidden" ascii wide nocase
$ps3 = "-EncodedCommand" ascii wide nocase
$ps4 = "-enc" ascii wide nocase
$ps5 = "IEX" ascii wide nocase
$ps6 = "Invoke-Expression" ascii wide nocase
// Download functionality
$dl1 = "Net.WebClient" ascii wide
$dl2 = "DownloadString" ascii wide
$dl3 = "DownloadFile" ascii wide
$dl4 = "System.Net.WebClient" ascii wide
$dl5 = "Start-BitsTransfer" ascii wide
// Execution from temp
$temp1 = "$env:TEMP" ascii wide
$temp2 = "$env:APPDATA" ascii wide
$temp3 = "\\Local\\Temp\\" wide
$temp4 = "\\Roaming\\" wide
// Anti-AV techniques
$av1 = "Add-MpPreference" ascii wide
$av2 = "ExclusionPath" ascii wide
$av3 = "DisableRealtimeMonitoring" ascii wide
$av4 = "Set-MpPreference" ascii wide
// Base64 indicators
$b64_1 = /[A-Za-z0-9+\/]{100,}={0,2}/ ascii
// Registry manipulation
$reg1 = "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" ascii wide
$reg2 = "New-ItemProperty" ascii wide
$reg3 = "Set-ItemProperty" ascii wide
condition:
(
(2 of ($ps*) and 2 of ($dl*)) or
(any of ($ps*) and any of ($dl*) and any of ($temp*)) or
(2 of ($av*) and any of ($ps*)) or
(any of ($ps*) and any of ($reg*) and any of ($dl*))
)
}
Rule 3: Direwolf Multi-Stage Loader
yara
rule Direwolf_MultiStage_Loader
{
meta:
description = "Detects multi-stage loading behavior in Direwolf"
author = "SOC Threat Intelligence"
severity = "critical"
strings:
// Stage separation markers
$stage1 = "STAGE1" ascii
$stage2 = "STAGE2" ascii
$stage3 = "PAYLOAD" ascii
// Decryption routines
$decrypt1 = {8B 45 ?? 33 45 ?? 89 45 ??} // XOR decryption loop
$decrypt2 = "CryptDecrypt" ascii
$decrypt3 = "CryptImportKey" ascii
$decrypt4 = {6A 00 6A 00 FF 15} // Crypto API call pattern
// Memory manipulation
$mem1 = "VirtualAlloc" ascii
$mem2 = "VirtualProtect" ascii
$mem3 = "WriteProcessMemory" ascii
$mem4 = "CreateRemoteThread" ascii
$mem5 = "NtAllocateVirtualMemory" ascii
// Process injection
$inj1 = "ZwUnmapViewOfSection" ascii
$inj2 = "NtUnmapViewOfSection" ascii
$inj3 = "ResumeThread" ascii
$inj4 = "SetThreadContext" ascii
// Hollowing patterns
$hollow1 = {6A 04 68 00 30 00 00} // Process hollowing signature
$hollow2 = {6A 00 6A 00 6A 00 6A 00 FF 15} // CreateProcess pattern
// Anti-sandbox checks
$sandbox1 = "GetTickCount" ascii
$sandbox2 = "Sleep" ascii
$sandbox3 = "IsDebuggerPresent" ascii
$sandbox4 = "CheckRemoteDebuggerPresent" ascii
condition:
uint16(0) == 0x5a4d and
(
(any of ($stage*) and 2 of ($decrypt*)) or
(3 of ($mem*) and 2 of ($inj*)) or
(any of ($hollow*) and 2 of ($mem*)) or
(2 of ($decrypt*) and 2 of ($sandbox*) and any of ($mem*))
)
}
Rule 4: Direwolf Persistence Mechanism
yara
rule Direwolf_Persistence_Module
{
meta:
description = "Detects Direwolf persistence establishment"
author = "SOC Threat Intelligence"
severity = "high"
strings:
// Registry persistence
$reg1 = "Software\\Microsoft\\Windows\\CurrentVersion\\Run" wide
$reg2 = "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce" wide
$reg3 = "RegCreateKeyEx" ascii
$reg4 = "RegSetValueEx" ascii
$reg5 = {48 8D 15 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? FF 15} // Registry API pattern
// Scheduled task creation
$task1 = "schtasks" ascii wide nocase
$task2 = "/create" ascii wide
$task3 = "/tn" ascii wide
$task4 = "ITaskService" ascii
$task5 = "ITaskFolder" ascii
// Service installation
$svc1 = "CreateService" ascii
$svc2 = "OpenSCManager" ascii
$svc3 = "StartService" ascii
$svc4 = "SERVICE_AUTO_START" ascii
// Startup folder
$startup1 = "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup" wide
$startup2 = "CreateFile" ascii
$startup3 = "CopyFile" ascii
// WMI persistence
$wmi1 = "Win32_Process" ascii
$wmi2 = "EventFilter" ascii
$wmi3 = "EventConsumer" ascii
$wmi4 = "FilterToConsumerBinding" ascii
// File copy operations
$copy1 = {6A 00 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? FF 15} // CopyFile pattern
condition:
uint16(0) == 0x5a4d and
(
(3 of ($reg*)) or
(3 of ($task*)) or
(3 of ($svc*)) or
(any of ($startup*) and any of ($copy*)) or
(2 of ($wmi*)) or
(2 of ($reg*) and 2 of ($task*))
)
}
Rule 5: Direwolf Data Exfiltration Module
yara
rule Direwolf_Data_Exfiltration
{
meta:
description = "Detects Direwolf data exfiltration components"
author = "SOC Threat Intelligence"
severity = "critical"
strings:
// Network APIs
$net1 = "InternetOpenA" ascii
$net2 = "InternetConnectA" ascii
$net3 = "HttpSendRequestA" ascii
$net4 = "InternetReadFile" ascii
$net5 = "WinHttpOpen" ascii
$net6 = "WinHttpConnect" ascii
$net7 = "WinHttpSendRequest" ascii
// SSL/TLS usage
$ssl1 = "INTERNET_FLAG_SECURE" ascii
$ssl2 = "SECURITY_FLAG_IGNORE" ascii
$ssl3 = "schannel" ascii
// Data compression
$zip1 = "CreateFile" ascii
$zip2 = "RtlCompressBuffer" ascii
$zip3 = "compress" ascii
// File enumeration
$enum1 = "FindFirstFile" ascii
$enum2 = "FindNextFile" ascii
$enum3 = "GetFileSize" ascii
// Data encoding
$enc1 = "CryptBinaryToString" ascii
$enc2 = "base64" ascii
$enc3 = {41 42 43 44 45 46 47 48} // Base64 alphabet
// POST data patterns
$post1 = "Content-Type: multipart/form-data" ascii
$post2 = "Content-Disposition: form-data" ascii
$post3 = "boundary=" ascii
// Upload endpoints
$upload1 = "/api/upload" ascii
$upload2 = "/upload.php" ascii
$upload3 = "/api/exfil" ascii
$upload4 = "/gate.php" ascii
condition:
uint16(0) == 0x5a4d and
(
(3 of ($net*) and any of ($ssl*)) or
(2 of ($net*) and 2 of ($enum*) and any of ($enc*)) or
(3 of ($net*) and any of ($post*)) or
(2 of ($net*) and any of ($upload*) and any of ($enc*))
)
}
Rule 6: Direwolf Anti-Analysis Techniques
yara
rule Direwolf_AntiAnalysis
{
meta:
description = "Detects anti-analysis techniques used by Direwolf"
author = "SOC Threat Intelligence"
severity = "medium"
strings:
// VM detection
$vm1 = "VBOX" ascii wide
$vm2 = "VMware" ascii wide nocase
$vm3 = "VirtualBox" ascii wide nocase
$vm4 = "QEMU" ascii wide
$vm5 = "Xen" ascii wide
$vm6 = "Hyper-V" ascii wide
// Sandbox detection
$sandbox1 = "SbieDll" ascii
$sandbox2 = "SandboxieControlWndClass" ascii
$sandbox3 = "SandboxieCryptoCloseServer" ascii
$sandbox4 = "wine_get_version" ascii
$sandbox5 = "GetSystemFirmwareTable" ascii
// Debugger detection
$debug1 = "IsDebuggerPresent" ascii
$debug2 = "CheckRemoteDebuggerPresent" ascii
$debug3 = "NtQueryInformationProcess" ascii
$debug4 = "OutputDebugString" ascii
$debug5 = {64 8B 05 30 00 00 00} // PEB access
// Analysis tools detection
$tools1 = "procmon" ascii nocase
$tools2 = "wireshark" ascii nocase
$tools3 = "fiddler" ascii nocase
$tools4 = "ollydbg" ascii nocase
$tools5 = "ida" ascii nocase
$tools6 = "x64dbg" ascii nocase
// Time-based evasion
$time1 = "GetTickCount" ascii
$time2 = "QueryPerformanceCounter" ascii
$time3 = "Sleep" ascii
$time4 = {6A 00 FF 15 ?? ?? ?? ?? 3D ?? ?? ?? ?? 7C} // timing check
// String obfuscation
$obf1 = {8A 04 0B 34 ?? 88 04 0F 41} // XOR string deobfuscation
$obf2 = {AC 3C ?? 74 ?? 34 ?? AA EB} // another obfuscation pattern
condition:
uint16(0) == 0x5a4d and
(
(2 of ($vm*) and any of ($debug*)) or
(2 of ($sandbox*) and any of ($time*)) or
(3 of ($tools*)) or
(any of ($debug*) and any of ($time*) and any of ($obf*)) or
(2 of ($vm*) and 2 of ($sandbox*))
)
}
Sigma Rules
Sigma Rule 1: Direwolf Installation Activity
yaml
title: Direwolf Malware Installation Pattern Detection
id: a9f7c4d3-8e6b-4f2a-9c5d-7b8e9a1f3c4d
status: experimental
description: Detects installation activities consistent with Direwolf infostealer deployment
author: SOC Threat Intelligence Team
date: 2024/12/25
modified: 2024/12/25
tags:
- attack.execution
- attack.t1204.002
- attack.persistence
- attack.t1547.001
- attack.defense_evasion
- attack.t1112
logsource:
category: process_creation
product: windows
detection:
selection_download:
CommandLine|contains:
- 'powershell'
- 'cmd.exe'
CommandLine|contains:
- 'WebClient'
- 'DownloadFile'
- 'DownloadString'
- 'Invoke-WebRequest'
- 'iwr'
- 'curl'
- 'wget'
selection_temp_execution:
Image|contains:
- '\AppData\Local\Temp\'
- '\AppData\Roaming\'
- '\ProgramData\'
Image|endswith:
- '.exe'
- '.scr'
- '.com'
selection_registry_mod:
CommandLine|contains:
- 'reg add'
- 'New-ItemProperty'
- 'Set-ItemProperty'
CommandLine|contains:
- 'CurrentVersion\Run'
- 'CurrentVersion\RunOnce'
selection_schtask:
CommandLine|contains: 'schtasks'
CommandLine|contains:
- '/create'
- '-create'
CommandLine|contains:
- '\Temp\'
- '\AppData\'
- '\ProgramData\'
selection_defender_disable:
CommandLine|contains:
- 'Set-MpPreference'
- 'Add-MpPreference'
CommandLine|contains:
- 'DisableRealtimeMonitoring'
- 'ExclusionPath'
- 'DisableBehaviorMonitoring'
timeframe: 5m
condition: (selection_download and selection_temp_execution) or
(selection_temp_execution and selection_registry_mod) or
(selection_temp_execution and selection_schtask) or
(selection_defender_disable and selection_temp_execution)
fields:
- CommandLine
- Image
- ParentImage
- User
- Computer
falsepositives:
- Legitimate software installations from temporary directories
- System administrator activities
level: high
Sigma Rule 2: Direwolf Credential Harvesting
yaml
title: Direwolf Browser Credential Theft Activity
id: b8e9f5a6-7c4d-4e3b-9f6a-8c7d9e2f4b5a
status: experimental
description: Detects file access patterns consistent with Direwolf stealing browser credentials
author: SOC Threat Intelligence Team
date: 2024/12/25
tags:
- attack.credential_access
- attack.t1555.003
- attack.collection
- attack.t1005
logsource:
product: windows
category: file_access
detection:
selection_chrome:
TargetFilename|contains:
- '\Google\Chrome\User Data\'
- '\BraveSoftware\Brave-Browser\User Data\'
- '\Microsoft\Edge\User Data\'
TargetFilename|endswith:
- '\Login Data'
- '\Cookies'
- '\Web Data'
selection_firefox:
TargetFilename|contains: '\Mozilla\Firefox\Profiles\'
TargetFilename|endswith:
- 'logins.json'
- 'key4.db'
- 'cookies.sqlite'
selection_suspicious_process:
Image|contains:
- '\Temp\'
- '\AppData\Local\'
- '\ProgramData\'
Image|endswith: '.exe'
selection_process_name:
Image|endswith:
- 'powershell.exe'
- 'cmd.exe'
- 'wscript.exe'
- 'cscript.exe'
exclusion_legitimate:
Image|contains:
- '\Google\Chrome\Application\'
- '\Mozilla Firefox\'
- '\Microsoft\Edge\'
- '\BraveSoftware\'
timeframe: 30s
condition: (selection_chrome or selection_firefox) and
(selection_suspicious_process or selection_process_name) and
not exclusion_legitimate
fields:
- TargetFilename
- Image
- User
- Computer
- ProcessId
falsepositives:
- Password manager software
- Backup utilities
- Browser synchronization services
level: critical
Sigma Rule 3: Direwolf Cryptocurrency Wallet Theft
yaml
title: Direwolf Cryptocurrency Wallet Access Detection
id: c9f6a7b8-5d4e-4f3c-8a6b-9d7e8f1a2c3b
status: experimental
description: Detects access to cryptocurrency wallet files and directories by suspicious processes
author: SOC Threat Intelligence Team
date: 2024/12/25
tags:
- attack.collection
- attack.t1005
- attack.credential_access
- attack.t1552.001
logsource:
product: windows
category: file_access
detection:
selection_wallet_files:
TargetFilename|contains:
- '\Bitcoin\wallet.dat'
- '\Ethereum\keystore\'
- '\Electrum\wallets\'
- '\Exodus\exodus.wallet'
- '\Coinomi\Coinomi\wallets\'
- '\atomic\'
- '\Monero\'
- '\Litecoin\wallet.dat'
- '\Dash\wallet.dat'
- '\Zcash\wallet.dat'
selection_browser_wallets:
TargetFilename|contains:
- '\Local Extension Settings\nkbihfbeogaeaoehlefnkodbefgpgknn' # MetaMask
- '\Local Extension Settings\bfnaelmomeimhlpmgjnjophhpkkoljpa' # Phantom
- '\Local Extension Settings\hnfanknocfeofbddgcijnmhnfnkdnaad' # Coinbase
selection_suspicious_access:
Image|contains:
- '\Temp\'
- '\AppData\Local\Temp\'
- '\AppData\Roaming\'
- '\ProgramData\'
selection_known_malicious:
Image|endswith:
- 'svchost32.exe'
- 'scvhost.exe'
- 'csrss32.exe'
- 'dwm32.exe'
exclusion_wallet_apps:
Image|contains:
- '\Electrum\'
- '\Exodus\'
- '\Bitcoin\'
- '\Ethereum\'
condition: (selection_wallet_files or selection_browser_wallets) and
(selection_suspicious_access or selection_known_malicious) and
not exclusion_wallet_apps
fields:
- TargetFilename
- Image
- User
- Computer
- AccessMask
falsepositives:
- Legitimate wallet application updates
- Backup software
- Antivirus scans
level: critical
Sigma Rule 4: Direwolf Clipboard Hijacking
yaml
title: Direwolf Clipboard Monitoring and Cryptocurrency Address Replacement
id: d7e8f9a1-6c5b-4e3d-8f7a-9c6d8e2f3a4b
status: experimental
description: Detects clipboard monitoring behavior used by Direwolf to replace cryptocurrency addresses
author: SOC Threat Intelligence Team
date: 2024/12/25
tags:
- attack.collection
- attack.t1115
- attack.credential_access
logsource:
product: windows
category: process_creation
detection:
selection_clipboard_api:
CallTrace|contains:
- 'GetClipboardData'
- 'SetClipboardData'
- 'OpenClipboard'
- 'SetClipboardViewer'
selection_process_location:
Image|contains:
- '\Temp\'
- '\AppData\Local\'
- '\AppData\Roaming\'
- '\ProgramData\'
selection_crypto_pattern:
CommandLine|re: '(bc1|0x|1[0-9A-Za-z]{25,34}|3[0-9A-Za-z]{25,34}|[13][a-km-zA-HJ-NP-Z1-9]{25,34})'
selection_powershell_clipboard:
CommandLine|contains:
- 'Get-Clipboard'
- 'Set-Clipboard'
- '[System.Windows.Forms.Clipboard]'
Image|endswith: 'powershell.exe'
condition: (selection_clipboard_api and selection_process_location) or
(selection_powershell_clipboard and selection_crypto_pattern) or
(selection_clipboard_api and selection_crypto_pattern)
fields:
- CommandLine
- Image
- User
- Computer
- ParentImage
falsepositives:
- Clipboard manager utilities
- Password managers with clipboard functionality
- Remote desktop applications
level: high
Sigma Rule 5: Direwolf C2 Communication Pattern
yaml
title: Direwolf Command and Control Network Communication
id: e8f9a1b2-7d6c-4f5e-9a8b-0c7d9e3f4a5b
status: experimental
description: Detects network communication patterns consistent with Direwolf C2 activity
author: SOC Threat Intelligence Team
date: 2024/12/25
tags:
- attack.command_and_control
- attack.t1071.001
- attack.exfiltration
- attack.t1041
logsource:
category: proxy
product: any
detection:
selection_suspicious_domains:
c-uri|contains:
- '/api/checkin'
- '/api/upload'
- '/api/command'
- '/gate.php'
- '/panel/'
- '/api/exfil'
selection_user_agent:
cs-user-agent|contains:
- 'WindowsUpdateClient'
- 'Microsoft-CryptoAPI'
- 'DirewolfClient'
- 'python-requests'
- 'Go-http-client'
selection_headers:
cs-headers|contains:
- 'X-Client-ID'
- 'X-Bot-Version'
- 'X-System-Info'
selection_new_domains:
domain-age: '<90'
sc-status: 200
selection_suspicious_tld:
c-uri|endswith:
- '.xyz'
- '.top'
- '.pw'
- '.tk'
- '.ml'
selection_post_with_data:
cs-method: 'POST'
cs-bytes: '>10240'
condition: (selection_suspicious_domains) or
(selection_user_agent and selection_post_with_data) or
(selection_headers and selection_post_with_data) or
(selection_new_domains and selection_suspicious_tld and selection_post_with_data)
fields:
- c-ip
- cs-user-agent
- c-uri
- cs-method
- cs-bytes
- sc-bytes
falsepositives:
- Legitimate update services
- Software telemetry
level: high
Sigma Rule 6: Direwolf Keylogger Activity
yaml
title: Direwolf Keylogging Behavior Detection
id: f9a1b2c3-8e7d-4f6c-9b8a-1d7e9f2a3c4b
status: experimental
description: Detects keyboard hook installation and keylogging behavior associated with Direwolf
author: SOC Threat Intelligence Team
date: 2024/12/25
tags:
- attack.collection
- attack.t1056.001
- attack.credential_access
logsource:
product: windows
category: process_creation
detection:
selection_hook_installation:
CallTrace|contains:
- 'SetWindowsHookEx'
- 'GetAsyncKeyState'
- 'GetKeyState'
- 'GetKeyboardState'
selection_low_level_hook:
CommandLine|contains:
- 'WH_KEYBOARD_LL'
- 'WH_KEYBOARD'
- 'WH_MOUSE_LL'
selection_suspicious_process:
Image|contains:
- '\Temp\'
- '\AppData\Local\Temp\'
- '\AppData\Roaming\'
Image|endswith: '.exe'
selection_file_logging:
TargetFilename|contains:
- '\AppData\'
- '\Temp\'
TargetFilename|endswith:
- '.log'
- '.txt'
- '.dat'
selection_powershell_keylog:
CommandLine|contains:
- 'GetAsyncKeyState'
- '[System.Windows.Forms.Keys]'
- 'Add-Type -MemberDefinition'
Image|endswith: 'powershell.exe'
condition: (selection_hook_installation and selection_suspicious_process) or
(selection_low_level_hook and selection_suspicious_process) or
(selection_hook_installation and selection_file_logging) or
selection_powershell_keylog
fields:
- Image
- CommandLine
- TargetFilename
- User
- Computer
falsepositives:
- Legitimate keyboard input software
- Accessibility tools
- Language input methods
level: high
```
Snort / Suricata Rules – Direwolf Malware
Rule 1: Direwolf Initial Payload Download
alert http $EXTERNAL_NET any -> $HOME_NET any (
msg:"MALWARE Direwolf Initial Payload Download Attempt";
flow:established,to_client;
file_data;
content:"MZ"; depth:2;
content:"This program cannot be run in DOS mode";
byte_test:2,>,10000,0,relative;
content:!"Content-Type|3a| text"; http_header;
pcre:"/\/(update|download|files|cdn|static)\/[A-Za-z0-9]{4,16}\.(exe|bin|dat)/i";
threshold:type limit, track by_src, count 1, seconds 300;
classtype:trojan-activity;
sid:7000001;
rev:2;
metadata: malware_family direwolf, attack_stage initial_access, severity critical;
)
Rule 2: Direwolf C2 Check-in Pattern
alert http $HOME_NET any -> $EXTERNAL_NET [443,8080,8443] (
msg:"MALWARE Direwolf C2 Checkin Communication";
flow:established,to_server;
content:"POST"; http_method;
content:"/api/checkin"; http_uri; nocase;
content:"X-Client-ID|3a|"; http_header;
content:"X-Bot-Version|3a|"; http_header;
content:"application/json"; http_header;
threshold:type both, track by_src, count 3, seconds 300;
classtype:trojan-activity;
sid:7000002;
rev:2;
metadata: malware_family direwolf, attack_stage c2_communication;
)
Rule 3: Direwolf Credential Exfiltration
alert http $HOME_NET any -> $EXTERNAL_NET 443 (
msg:"MALWARE Direwolf Credential Data Exfiltration";
flow:established,to_server;
content:"POST"; http_method;
content:"/api/upload"; http_uri;
content:"multipart/form-data"; http_header;
content:"Login Data"; http_client_body;
content:"password"; http_client_body;
dsize:>5120;
threshold:type threshold, track by_src, count 1, seconds 60;
classtype:credential-theft;
sid:7000003;
rev:2;
metadata: malware_family direwolf, attack_stage exfiltration, data_type credentials;
)
Rule 4: Direwolf Cryptocurrency Wallet Exfiltration
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE Direwolf Cryptocurrency Wallet Data Exfiltration";
flow:established,to_server;
content:"POST"; http_method;
content:!"Mozilla"; http_header;
content:"wallet"; http_client_body; nocase;
pcre:"/(seed|private_key|mnemonic|keystore)/i"; http_client_body;
dsize:>1024;
threshold:type limit, track by_src, count 1, seconds 300;
classtype:trojan-activity;
sid:7000004;
rev:2;
metadata: malware_family direwolf, attack_type cryptocurrency_theft;
)
Rule 5: Direwolf Beaconing Pattern
alert http $HOME_NET any -> $EXTERNAL_NET 443 (
msg:"MALWARE Direwolf Regular C2 Beacon Activity";
flow:established,to_server;
content:"GET"; http_method;
content:"User-Agent|3a|"; http_header;
pcre:"/User-Agent\x3a\s+(WindowsUpdateClient|Microsoft-CryptoAPI|DirewolfClient)/i";
dsize:<512;
detection_filter:track by_src, count 5, seconds 300;
classtype:trojan-activity;
sid:7000005;
rev:2;
metadata: malware_family direwolf, pattern beaconing;
)
Rule 6: Direwolf PowerShell Download Cradle
alert http $HOME_NET any -> $EXTERNAL_NET [80,443,8080] (
msg:"MALWARE Direwolf PowerShell Download Cradle Detected";
flow:established,to_server;
content:"GET"; http_method;
content:"powershell"; http_uri; nocase;
pcre:"/\.(ps1|txt|dat)\?[a-z0-9]{8,}/i";
content:"Mozilla"; http_header;
threshold:type limit, track by_src, count 1, seconds 60;
classtype:trojan-activity;
sid:7000006;
rev:2;
metadata: malware_family direwolf, attack_vector powershell_dropper;
)
Rule 7: Direwolf Clipboard Cryptocurrency Address Exfiltration
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE Direwolf Clipboard Cryptocurrency Address Exfiltration";
flow:established,to_server;
content:"POST"; http_method;
pcre:"/clipboard/i"; http_client_body;
pcre:"/(bc1|0x|[13][a-km-zA-HJ-NP-Z1-9]{25,42})/"; http_client_body;
threshold:type threshold, track by_src, count 1, seconds 60;
classtype:trojan-activity;
sid:7000007;
rev:2;
metadata: malware_family direwolf, attack_type clipboard_hijacking;
)
Rule 8: Direwolf Encoded C2 Command Response
alert http $EXTERNAL_NET any -> $HOME_NET any (
msg:"MALWARE Direwolf Encoded Command Response from C2";
flow:established,to_client;
content:"200"; http_stat_code;
content:"application/octet-stream"; http_header;
content:"|00 00 00|"; depth:3; http_server_body;
byte_test:4,>,256,3,relative; http_server_body;
threshold:type limit, track by_dst, count 1, seconds 120;
classtype:trojan-activity;
sid:7000008;
rev:2;
metadata: malware_family direwolf, direction inbound_command;
)
Splunk Detection Queries
Query 1: Direwolf Installation and Persistence Detection
spl
index=windows (source="WinEventLog:Security" OR source="WinEventLog:Microsoft-Windows-Sysmon/Operational")
(EventCode=1 OR EventCode=4688)
(
(CommandLine="*powershell*" AND CommandLine="*-enc*" AND CommandLine="*WebClient*")
OR (CommandLine="*powershell*" AND CommandLine="*DownloadFile*" AND CommandLine="*Temp*")
OR (Image="*\\AppData\\Local\\Temp\\*" AND Image="*.exe")
OR (Image="*\\AppData\\Roaming\\*" AND Image="*.exe")
OR (CommandLine="*schtasks*" AND CommandLine="*/create*" AND CommandLine="*Temp*")
OR (CommandLine="*reg add*" AND CommandLine="*CurrentVersion\\Run*")
)
| eval action=case(
match(CommandLine, "powershell.*-enc"), "Encoded_PowerShell_Execution",
match(CommandLine, "DownloadFile|WebClient"), "Download_Activity",
match(Image, "Temp.*\.exe"), "Temp_Execution",
match(CommandLine, "schtasks"), "Scheduled_Task_Creation",
match(CommandLine, "reg add.*Run"), "Registry_Persistence",
true(), "Other")
| transaction ComputerName maxspan=10m
| where mvcount(action) >= 2
| stats count,
values(CommandLine) as commands,
values(action) as actions,
values(Image) as processes,
values(User) as users,
min(_time) as first_activity,
max(_time) as last_activity
by ComputerName
| eval infection_duration_min=round((last_activity-first_activity)/60, 2)
| eval threat_score=0
| eval threat_score=threat_score + if(match(actions, "Encoded_PowerShell"), 25, 0)
| eval threat_score=threat_score + if(match(actions, "Download_Activity"), 20, 0)
| eval threat_score=threat_score + if(match(actions, "Temp_Execution"), 15, 0)
| eval threat_score=threat_score + if(match(actions, "Registry_Persistence"), 20, 0)
| eval threat_score=threat_score + if(match(actions, "Scheduled_Task"), 20, 0)
| where threat_score >= 40
| eval severity=case(
threat_score >= 70, "critical",
threat_score >= 50, "high",
"medium")
| eval suspected_malware="Direwolf"
| table first_activity, ComputerName, users, actions, infection_duration_min,
threat_score, severity, suspected_malware
| sort -threat_score
Query 2: Direwolf Browser Credential Theft Detection
spl
index=windows source="WinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=11
(
TargetFilename="*\\Google\\Chrome\\User Data\\*\\Login Data*"
OR TargetFilename="*\\Microsoft\\Edge\\User Data\\*\\Login Data*"
OR TargetFilename="*\\Mozilla\\Firefox\\Profiles\\*\\logins.json*"
OR TargetFilename="*\\BraveSoftware\\*\\Login Data*"
OR TargetFilename="*\\Opera Software\\*\\Login Data*"
OR TargetFilename="*\\Cookies*"
OR TargetFilename="*\\Web Data*"
)
NOT (
Image="*\\Google\\Chrome\\Application\\*"
OR Image="*\\Microsoft\\Edge\\Application\\*"
OR Image="*\\Mozilla Firefox\\*"
OR Image="*\\BraveSoftware\\*"
OR Image="*\\Opera\\*"
)
| eval file_type=case(
match(TargetFilename, "Login Data"), "Credentials",
match(TargetFilename, "Cookies"), "Cookies",
match(TargetFilename, "Web Data"), "Autofill",
match(TargetFilename, "logins\.json"), "Firefox_Credentials",
true(), "Other")
| eval browser=case(
match(TargetFilename, "Chrome"), "Chrome",
match(TargetFilename, "Edge"), "Edge",
match(TargetFilename, "Firefox"), "Firefox",
match(TargetFilename, "Brave"), "Brave",
match(TargetFilename, "Opera"), "Opera",
true(), "Unknown")
| eval suspicious_location=if(match(Image, "(Temp|AppData\\Local|AppData\\Roaming|ProgramData)"), 1, 0)
| stats count as access_count,
dc(TargetFilename) as unique_files,
values(TargetFilename) as accessed_files,
values(file_type) as file_types,
values(browser) as browsers,
values(Image) as processes,
sum(suspicious_location) as suspicious_count,
earliest(_time) as first_access,
latest(_time) as last_access
by ComputerName, User
| eval access_duration_sec=last_access-first_access
| where unique_files >= 2 OR suspicious_count > 0
| eval risk_score=0
| eval risk_score=risk_score + (unique_files * 15)
| eval risk_score=risk_score + (suspicious_count * 30)
| eval risk_score=risk_score + if(mvcount(browsers) >= 2, 25, 0)
| where risk_score >= 40
| join type=left ComputerName [
search index=firewall action=allowed dest_port=443
| stats count as outbound_connections by src_ip
| rename src_ip as ComputerName
]
| eval severity=case(
risk_score >= 80 AND outbound_connections > 10, "critical",
risk_score >= 60, "high",
"medium")
| table first_access, ComputerName, User, browsers, file_types, unique_files,
access_count, suspicious_count, outbound_connections, risk_score, severity
| eval attack_type="Browser Credential Theft"
| eval suspected_malware="Direwolf"
| sort -risk_score
Query 3: Direwolf Cryptocurrency Wallet Access Detection
spl
index=windows source="WinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=11
(
TargetFilename="*\\Bitcoin\\wallet.dat*"
OR TargetFilename="*\\Ethereum\\keystore\\*"
OR TargetFilename="*\\Electrum\\wallets\\*"
OR TargetFilename="*\\Exodus\\exodus.wallet*"
OR TargetFilename="*\\Coinomi\\*\\wallets\\*"
OR TargetFilename="*\\atomic\\*"
OR TargetFilename="*\\Monero\\*"
OR TargetFilename="*\\Litecoin\\wallet.dat*"
OR TargetFilename="*\\Local Extension Settings\\nkbihfbeogaeaoehlefnkodbefgpgknn*"
OR TargetFilename="*\\Local Extension Settings\\bfnaelmomeimhlpmgjnjophhpkkoljpa*"
)
NOT (
Image="*\\Electrum\\*"
OR Image="*\\Exodus\\*"
OR Image="*\\Bitcoin\\*"
OR Image="*\\Ethereum\\*"
)
| eval wallet_type=case(
match(TargetFilename, "Bitcoin"), "Bitcoin",
match(TargetFilename, "Ethereum"), "Ethereum",
match(TargetFilename, "Electrum"), "Electrum",
match(TargetFilename, "Exodus"), "Exodus",
match(TargetFilename, "Coinomi"), "Coinomi",
match(TargetFilename, "Monero"), "Monero",
match(TargetFilename, "Litecoin"), "Litecoin",
match(TargetFilename, "nkbihfbeogaeaoehlefnkodbefgpgknn"), "MetaMask",
match(TargetFilename, "bfnaelmomeimhlpmgjnjophhpkkoljpa"), "Phantom",
true(), "Other")
| eval file_category=case(
match(TargetFilename, "wallet\.dat"), "Wallet_File",
match(TargetFilename, "keystore"), "Keystore",
match(TargetFilename, "Extension Settings"), "Browser_Wallet",
true(), "Other")
| eval suspicious_process=if(match(Image, "(Temp|svchost32|scvhost|csrss32|dwm32)"), 1, 0)
| stats count as access_count,
dc(TargetFilename) as unique_wallets,
dc(wallet_type) as wallet_types_count,
values(TargetFilename) as wallet_files,
values(wallet_type) as wallet_types,
values(Image) as accessing_processes,
sum(suspicious_process) as suspicious_process_count,
earliest(_time) as first_access,
latest(_time) as last_access
by ComputerName, User
| eval access_window_sec=last_access-first_access
| where unique_wallets >= 1
| eval threat_score=0
| eval threat_score=threat_score + (unique_wallets * 25)
| eval threat_score=threat_score + (wallet_types_count * 15)
| eval threat_score=threat_score + if(suspicious_process_count > 0, 40, 0)
| where threat_score >= 50
| join type=left ComputerName [
search index=firewall dest_port=443 action=allowed
| stats sum(bytes_out) as total_bytes_sent, count as connections by src_ip
| rename src_ip as ComputerName
]
| eval data_exfiltration_likely=if(total_bytes_sent > 1048576, 1, 0)
| eval severity=case(
threat_score >= 80 AND data_exfiltration_likely=1, "critical",
threat_score >= 60, "high",
"medium")
| table first_access, ComputerName, User, wallet_types, unique_wallets,
accessing_processes, total_bytes_sent, threat_score, severity
| eval attack_type="Cryptocurrency Wallet Theft"
| eval suspected_malware="Direwolf"
| sort -threat_score
Query 4: Direwolf C2 Communication Detection
spl
(index=proxy OR index=firewall)
(
(uri_path="/api/checkin" OR uri_path="/api/upload" OR uri_path="/api/command" OR uri_path="/gate.php")
OR (user_agent="*WindowsUpdateClient*" OR user_agent="*Microsoft-CryptoAPI*" OR user_agent="*DirewolfClient*")
OR (http_header="*X-Client-ID*" OR http_header="*X-Bot-Version*" OR http_header="*X-System-Info*")
OR (dest_domain="*.xyz" OR dest_domain="*.top" OR dest_domain="*.pw")
)
dest_port IN (80, 443, 8080, 8443)
method="POST"
| eval suspicious_uri=if(match(uri_path, "/(api|gate|panel)/(checkin|upload|command|exfil)"), 1, 0)
| eval suspicious_ua=if(match(user_agent, "(WindowsUpdateClient|Microsoft-CryptoAPI|DirewolfClient|python-requests|Go-http-client)"), 1, 0)
| eval custom_headers=if(match(http_header, "(X-Client-ID|X-Bot-Version|X-System-Info)"), 1, 0)
| eval new_domain=if(domain_age < 90, 1, 0)
| eval suspicious_tld=if(match(dest_domain, "\.(xyz|top|pw|tk|ml)$"), 1, 0)
| stats count as connection_count,
sum(bytes_out) as total_sent,
sum(bytes_in) as total_received,
dc(dest_ip) as unique_destinations,
values(dest_domain) as c2_domains,
values(uri_path) as uri_paths,
values(user_agent) as user_agents,
sum(suspicious_uri) as suspicious_uri_count,
sum(suspicious_ua) as suspicious_ua_count,
sum(custom_headers) as custom_header_count,
sum(new_domain) as new_domain_count,
sum(suspicious_tld) as suspicious_tld_count,
earliest(_time) as first_connection,
latest(_time) as last_connection
by src_ip
| eval session_duration_hours=round((last_connection-first_connection)/3600, 2)
| eval total_data_mb=round((total_sent+total_received)/1048576, 2)
| eval c2_score=0
| eval c2_score=c2_score + (suspicious_uri_count * 30)
| eval c2_score=c2_score + (suspicious_ua_count * 25)
| eval c2_score=c2_score + (custom_header_count * 30)
| eval c2_score=c2_score + (new_domain_count * 15)
| eval c2_score=c2_score + (suspicious_tld_count * 10)
| where c2_score >= 30
| eval severity=case(
c2_score >= 70, "critical",
c2_score >= 50, "high",
"medium")
| table first_connection, src_ip, c2_domains, uri_paths, connection_count,
total_data_mb, session_duration_hours, c2_score, severity
| eval threat_type="Command and Control Communication"
| eval suspected_malware="Direwolf"
| sort -c2_score
Query 5: Direwolf Keylogger Detection
spl
index=windows source="WinEventLog:Microsoft-Windows-Sysmon/Operational"
(EventCode=1 OR EventCode=7 OR EventCode=11)
(
(CommandLine="*SetWindowsHookEx*" OR CommandLine="*GetAsyncKeyState*")
OR (ImageLoaded="*user32.dll*" AND CommandLine="*WH_KEYBOARD*")
OR (Image="*\\Temp\\*" AND ImageLoaded="*user32.dll*")
OR (TargetFilename="*\\AppData\\*" AND TargetFilename="*.log")
OR (TargetFilename="*\\Temp\\*" AND TargetFilename="*.txt")
)
| eval activity_type=case(
match(CommandLine, "SetWindowsHookEx"), "Hook_Installation",
match(CommandLine, "GetAsyncKeyState"), "Key_State_Check",
match(CommandLine, "WH_KEYBOARD"), "Keyboard_Hook",
match(ImageLoaded, "user32\.dll"), "User32_Load",
match(TargetFilename, "\.log|\.txt"), "Log_File_Creation",
true(), "Other")
| eval suspicious_location=if(match(Image, "(Temp|AppData\\Local|AppData\\Roaming|ProgramData)"), 1, 0)
| stats count as event_count,
dc(activity_type) as unique_activities,
values(activity_type) as activities,
values(Image) as processes,
values(TargetFilename) as log_files,
sum(suspicious_location) as suspicious_count,
earliest(_time) as first_event,
latest(_time) as last_event
by ComputerName, User
| eval activity_window_min=round((last_event-first_event)/60, 2)
| where unique_activities >= 2 OR suspicious_count > 0
| eval keylog_score=0
| eval keylog_score=keylog_score + (unique_activities * 20)
| eval keylog_score=keylog_score + if(suspicious_count > 0, 30, 0)
| eval keylog_score=keylog_score + if(match(activities, "Hook_Installation"), 25, 0)
| eval keylog_score=keylog_score + if(isnotnull(log_files), 25, 0)
| where keylog_score >= 40
| join type=left ComputerName [
search index=windows source="WinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
dest_port=443
| stats count as outbound_https by ComputerName
]
| eval severity=case(
keylog_score >= 75 AND outbound_https > 5, "critical",
keylog_score >= 60, "high",
"medium")
| table first_event, ComputerName, User, activities, processes, log_files,
event_count, outbound_https, keylog_score, severity
| eval attack_type="Keylogging Activity"
| eval suspected_malware="Direwolf"
| sort -keylog_score
Query 6: Direwolf Complete Attack Chain Analysis
spl
index=windows source="WinEventLog:Microsoft-Windows-Sysmon/Operational"
| transaction ComputerName maxspan=4h
| where eventcount >= 5
| eval stage_initial_access=if(match(_raw, "(powershell.*-enc|DownloadFile|WebClient)"), 1, 0)
| eval stage_execution=if(match(_raw, "(Temp.*\.exe|AppData.*\.exe)"), 1, 0)
| eval stage_persistence=if(match(_raw, "(schtasks.*create|reg add.*Run|systemctl)"), 1, 0)
| eval stage_defense_evasion=if(match(_raw, "(Set-MpPreference|Add-MpPreference|DisableRealtimeMonitoring)"), 1, 0)
| eval stage_credential_access=if(match(_raw, "(Login Data|logins\.json|wallet\.dat|keystore)"), 1, 0)
| eval stage_collection=if(match(_raw, "(SetWindowsHookEx|GetClipboardData|screenshot)"), 1, 0)
| eval stage_c2=if(match(_raw, "(api/checkin|api/upload|gate\.php)"), 1, 0)
| eval stage_exfiltration=if(match(_raw, "POST.*443.*bytes_out>[0-9]{6,}"), 1, 0)
| eval total_stages=stage_initial_access + stage_execution + stage_persistence +
stage_defense_evasion + stage_credential_access + stage_collection +
stage_c2 + stage_exfiltration
| where total_stages >= 3
| stats values(EventCode) as event_codes,
min(_time) as attack_start,
max(_time) as attack_end,
sum(stage_initial_access) as initial_access,
sum(stage_execution) as execution,
sum(stage_persistence) as persistence,
sum(stage_defense_evasion) as defense_evasion,
sum(stage_credential_access) as credential_access,
sum(stage_collection) as collection,
sum(stage_c2) as c2_communication,
sum(stage_exfiltration) as exfiltration,
max(total_stages) as stages_observed
by ComputerName, User
| eval attack_duration_hours=round((attack_end-attack_start)/3600, 2)
| eval attack_chain=mvappend(
if(initial_access > 0, "Initial Access", null()),
if(execution > 0, "Execution", null()),
if(persistence > 0, "Persistence", null()),
if(defense_evasion > 0, "Defense Evasion", null()),
if(credential_access > 0, "Credential Access", null()),
if(collection > 0, "Collection", null()),
if(c2_communication > 0, "C2 Communication", null()),
if(exfiltration > 0, "Exfiltration", null()))
| eval severity=case(
stages_observed >= 6, "critical",
stages_observed >= 4, "high",
"medium")
| eval compromise_level=case(
stages_observed >= 6, "Full Compromise",
stages_observed >= 4, "Significant Compromise",
"Partial Compromise")
| table attack_start, ComputerName, User, stages_observed, attack_chain,
attack_duration_hours, compromise_level, severity
| eval suspected_malware="Direwolf"
| sort -stages_observed, -severity
Microsoft Sentinel KQL Queries
KQL Query 1: Direwolf Installation and Persistence
kql
// Direwolf Installation Chain Detection
let TimeWindow = 1h;
let DownloadActivity =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where (ProcessCommandLine has_any ("powershell", "cmd") and
ProcessCommandLine has_any ("WebClient", "DownloadFile", "DownloadString", "Invoke-WebRequest"))
or (ProcessCommandLine has "curl" and ProcessCommandLine has "-o")
| extend ActivityType = "Download"
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, FileName, ActivityType;
let TempExecution =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where FolderPath has_any ("\\Temp\\", "\\AppData\\Local\\", "\\AppData\\Roaming\\", "\\ProgramData\\")
| where FileName endswith ".exe"
| extend ActivityType = "Temp_Execution"
| project Timestamp, DeviceName, AccountName, FolderPath, FileName, ProcessCommandLine, ActivityType;
let PersistenceActivity =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where (ProcessCommandLine has "schtasks" and ProcessCommandLine has "/create")
or (ProcessCommandLine has "reg add" and ProcessCommandLine has_any ("Run", "RunOnce"))
or (ProcessCommandLine has_any ("New-ItemProperty", "Set-ItemProperty") and ProcessCommandLine has "CurrentVersion\\Run")
| extend ActivityType = "Persistence"
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, ActivityType;
let DefenseEvasion =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where ProcessCommandLine has_any ("Set-MpPreference", "Add-MpPreference")
| where ProcessCommandLine has_any ("DisableRealtimeMonitoring", "ExclusionPath", "DisableBehaviorMonitoring")
| extend ActivityType = "Defense_Evasion"
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, ActivityType;
union DownloadActivity, TempExecution, PersistenceActivity, DefenseEvasion
| summarize
Activities = make_set(ActivityType),
Commands = make_set(ProcessCommandLine),
Files = make_set(FileName),
FirstActivity = min(Timestamp),
LastActivity = max(Timestamp),
EventCount = count()
by DeviceName, AccountName
| extend
ActivityCount = array_length(Activities),
InstallationDurationMinutes = datetime_diff('minute', LastActivity, FirstActivity)
| where ActivityCount >= 2
| extend
ThreatScore = 0,
ThreatScore = ThreatScore + iff(Activities has "Download", 20, 0),
ThreatScore = ThreatScore + iff(Activities has "Temp_Execution", 25, 0),
ThreatScore = ThreatScore + iff(Activities has "Persistence", 25, 0),
ThreatScore = ThreatScore + iff(Activities has "Defense_Evasion", 30, 0),
ThreatScore = ThreatScore + iff(InstallationDurationMinutes < 10, 20, 0)
| where ThreatScore >= 45
| extend
Severity = case(
ThreatScore >= 80, "Critical",
ThreatScore >= 60, "High",
"Medium"),
ThreatFamily = "Direwolf",
AttackStage = "Installation + Persistence"
| project
FirstActivity,
DeviceName,
AccountName,
Activities,
ActivityCount,
InstallationDurationMinutes,
ThreatScore,
Severity,
ThreatFamily,
Commands
| sort by ThreatScore desc
KQL Query 2: Direwolf Credential Harvesting
kql
// Direwolf Browser Credential Access Detection
let TimeFrame = 6h;
let CredentialFiles = dynamic([
"Login Data", "Cookies", "Web Data", "logins.json", "key4.db", "cookies.sqlite"
]);
let BrowserPaths = dynamic([
"Google\\Chrome\\User Data", "Microsoft\\Edge\\User Data",
"Mozilla\\Firefox\\Profiles", "BraveSoftware\\Brave-Browser",
"Opera Software\\Opera Stable"
]);
let LegitimateProcesses = dynamic([
"chrome.exe", "msedge.exe", "firefox.exe", "brave.exe", "opera.exe"
]);
DeviceFileEvents
| where Timestamp > ago(TimeFrame)
| where ActionType in ("FileCreated", "FileModified", "FileRenamed")
| where FolderPath has_any (BrowserPaths)
| where FileName has_any (CredentialFiles)
| where InitiatingProcessFileName !in~ (LegitimateProcesses)
| extend
Browser = case(
FolderPath has "Chrome", "Chrome",
FolderPath has "Edge", "Edge",
FolderPath has "Firefox", "Firefox",
FolderPath has "Brave", "Brave",
FolderPath has "Opera", "Opera",
"Unknown"),
FileType = case(
FileName has "Login Data", "Credentials",
FileName has "Cookies", "Cookies",
FileName has "Web Data", "Autofill",
FileName has "logins.json", "Firefox_Credentials",
"Other"),
SuspiciousLocation = iff(InitiatingProcessFolderPath has_any ("Temp", "AppData\\Local", "AppData\\Roaming", "ProgramData"), 1, 0)
| summarize
AccessCount = count(),
UniqueFiles = dcount(FolderPath),
Browsers = make_set(Browser),
FileTypes = make_set(FileType),
AccessedFiles = make_set(FolderPath),
Processes = make_set(InitiatingProcessFileName),
FirstAccess = min(Timestamp),
LastAccess = max(Timestamp),
SuspiciousAccessCount = sum(SuspiciousLocation)
by DeviceName, AccountName, InitiatingProcessFolderPath
| extend
AccessDurationMinutes = datetime_diff('minute', LastAccess, FirstAccess),
MultipleBrowsers = iff(array_length(Browsers) >= 2, 1, 0)
| where UniqueFiles >= 2 or SuspiciousAccessCount > 0
| join kind=leftouter (
DeviceNetworkEvents
| where Timestamp > ago(TimeFrame)
| where RemotePort == 443
| where ActionType == "ConnectionSuccess"
| summarize OutboundConnections = count() by DeviceName
) on DeviceName
| extend
RiskScore = 0,
RiskScore = RiskScore + (UniqueFiles * 15),
RiskScore = RiskScore + (SuspiciousAccessCount * 30),
RiskScore = RiskScore + (MultipleBrowsers * 25),
RiskScore = RiskScore + iff(OutboundConnections > 10, 20, 0)
| where RiskScore >= 40
| extend
Severity = case(
RiskScore >= 80, "Critical",
RiskScore >= 60, "High",
"Medium"),
AttackType = "Browser Credential Theft",
ThreatFamily = "Direwolf"
| project
FirstAccess,
DeviceName,
AccountName,
Browsers,
FileTypes,
UniqueFiles,
AccessCount,
SuspiciousAccessCount,
OutboundConnections,
Processes,
RiskScore,
Severity,
ThreatFamily
| sort by RiskScore desc
KQL Query 3: Direwolf Cryptocurrency Wallet Theft
kql
// Direwolf Cryptocurrency Wallet Access Detection
let TimeWindow = 12h;
let WalletPaths = dynamic([
"Bitcoin\\wallet.dat", "Ethereum\\keystore", "Electrum\\wallets",
"Exodus\\exodus.wallet", "Coinomi\\Coinomi\\wallets", "atomic",
"Monero", "Litecoin\\wallet.dat", "Dash\\wallet.dat"
]);
let BrowserWalletExtensions = dynamic([
"nkbihfbeogaeaoehlefnkodbefgpgknn", // MetaMask
"bfnaelmomeimhlpmgjnjophhpkkoljpa", // Phantom
"hnfanknocfeofbddgcijnmhnfnkdnaad" // Coinbase Wallet
]);
let LegitimateWalletApps = dynamic([
"electrum.exe", "exodus.exe", "bitcoin-qt.exe", "ethereum-wallet.exe"
]);
DeviceFileEvents
| where Timestamp > ago(TimeWindow)
| where ActionType in ("FileCreated", "FileModified", "FileRead")
| where (FolderPath has_any (WalletPaths) or FolderPath has_any (BrowserWalletExtensions))
| where InitiatingProcessFileName !in~ (LegitimateWalletApps)
| extend
WalletType = case(
FolderPath has "Bitcoin", "Bitcoin",
FolderPath has "Ethereum", "Ethereum",
FolderPath has "Electrum", "Electrum",
FolderPath has "Exodus", "Exodus",
FolderPath has "Coinomi", "Coinomi",
FolderPath has "Monero", "Monero",
FolderPath has "Litecoin", "Litecoin",
FolderPath has "nkbihfbeogaeaoehlefnkodbefgpgknn", "MetaMask",
FolderPath has "bfnaelmomeimhlpmgjnjophhpkkoljpa", "Phantom",
"Other"),
FileCategory = case(
FileName has "wallet.dat", "Wallet_File",
FolderPath has "keystore", "Keystore",
FolderPath has "Extension Settings", "Browser_Wallet",
"Other"),
SuspiciousProcess = iff(InitiatingProcessFileName has_any ("svchost32", "scvhost", "csrss32", "dwm32") or
InitiatingProcessFolderPath has "Temp", 1, 0)
| summarize
AccessCount = count(),
UniqueWallets = dcount(FolderPath),
WalletTypeCount = dcount(WalletType),
WalletTypes = make_set(WalletType),
WalletFiles = make_set(FolderPath),
AccessingProcesses = make_set(InitiatingProcessFileName),
FirstAccess = min(Timestamp),
LastAccess = max(Timestamp),
SuspiciousProcessCount = sum(SuspiciousProcess)
by DeviceName, AccountName
| extend AccessWindowSeconds = datetime_diff('second', LastAccess, FirstAccess)
| where UniqueWallets >= 1
| join kind=leftouter (
DeviceNetworkEvents
| where Timestamp > ago(TimeWindow)
| where RemotePort == 443
| summarize
TotalBytesSent = sum(SentBytes),
Connections = count()
by DeviceName
) on DeviceName
| extend
ThreatScore = 0,
ThreatScore = ThreatScore + (UniqueWallets * 25),
ThreatScore = ThreatScore + (WalletTypeCount * 15),
ThreatScore = ThreatScore + iff(SuspiciousProcessCount > 0, 40, 0),
DataExfiltrationLikely = iff(TotalBytesSent > 1048576, 1, 0),
ThreatScore = ThreatScore + iff(DataExfiltrationLikely == 1, 25, 0)
| where ThreatScore >= 50
| extend
Severity = case(
ThreatScore >= 90 and DataExfiltrationLikely == 1, "Critical",
ThreatScore >= 70, "High",
"Medium"),
AttackType = "Cryptocurrency Wallet Theft",
ThreatFamily = "Direwolf"
| project
FirstAccess,
DeviceName,
AccountName,
WalletTypes,
UniqueWallets,
AccessingProcesses,
TotalBytesSent,
Connections,
ThreatScore,
Severity,
ThreatFamily
| sort by ThreatScore desc
KQL Query 4: Direwolf C2 Communication
kql
// Direwolf Command and Control Detection
let TimeWindow = 24h;
let SuspiciousURIPaths = dynamic([
"/api/checkin", "/api/upload", "/api/command", "/gate.php",
"/panel/", "/api/exfil", "/upload.php"
]);
let SuspiciousUserAgents = dynamic([
"WindowsUpdateClient", "Microsoft-CryptoAPI", "DirewolfClient",
"python-requests", "Go-http-client"
]);
let SuspiciousTLDs = dynamic([".xyz", ".top", ".pw", ".tk", ".ml"]);
DeviceNetworkEvents
| where Timestamp > ago(TimeWindow)
| where RemotePort in (80, 443, 8080, 8443)
| where ActionType == "ConnectionSuccess"
| extend
SuspiciousURI = iff(RemoteUrl has_any (SuspiciousURIPaths), 1, 0),
SuspiciousUA = iff(InitiatingProcessCommandLine has_any (SuspiciousUserAgents), 1, 0),
NewDomain = iff(todatetime(RemoteUrl) > ago(90d), 1, 0),
SuspiciousTLD = iff(RemoteUrl has_any (SuspiciousTLDs), 1, 0),
LargeUpload = iff(SentBytes > 10240, 1, 0)
| where SuspiciousURI == 1 or SuspiciousUA == 1 or (NewDomain == 1 and SuspiciousTLD == 1 and LargeUpload == 1)
| summarize
ConnectionCount = count(),
TotalBytesSent = sum(SentBytes),
TotalBytesReceived = sum(ReceivedBytes),
UniqueDestinations = dcount(RemoteIP),
C2Domains = make_set(RemoteUrl),
RemoteIPs = make_set(RemoteIP),
FirstConnection = min(Timestamp),
LastConnection = max(Timestamp),
SuspiciousURICount = sum(SuspiciousURI),
SuspiciousUACount = sum(SuspiciousUA),
NewDomainCount = sum(NewDomain),
SuspiciousTLDCount = sum(SuspiciousTLD)
by DeviceName, InitiatingProcessFileName, LocalIP
| extend
SessionDurationHours = datetime_diff('hour', LastConnection, FirstConnection),
TotalDataMB = (TotalBytesSent + TotalBytesReceived) / 1048576.0,
C2Score = 0
| extend C2Score = C2Score + (SuspiciousURICount * 30)
| extend C2Score = C2Score + (SuspiciousUACount * 25)
| extend C2Score = C2Score + (NewDomainCount * 15)
| extend C2Score = C2Score + (SuspiciousTLDCount * 10)
| extend C2Score = C2Score + iff(ConnectionCount > 50, 20, iff(ConnectionCount > 20, 10, 0))
| where C2Score >= 30
| extend
Severity = case(
C2Score >= 70, "Critical",
C2Score >= 50, "High",
"Medium"),
ThreatType = "Command and Control Communication",
ThreatFamily = "Direwolf"
| project
FirstConnection,
DeviceName,
LocalIP,
InitiatingProcessFileName,
C2Domains,
RemoteIPs,
ConnectionCount,
TotalDataMB,
SessionDurationHours,
C2Score,
Severity,
ThreatFamily
| sort by C2Score desc
KQL Query 5: Direwolf Complete Attack Timeline
kql
// Direwolf Full Attack Chain Analysis
let TimeWindow = 48h;
// Stage 1: Initial Access
let InitialAccess =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where (ProcessCommandLine has_any (“powershell”, “cmd”) and
ProcessCommandLine has_any (“WebClient”, “DownloadFile”, “-enc”))
| extend Stage = “Initial_Access”
| summarize InitialAccessTime = min(Timestamp) by DeviceName
| extend Stage1 = 1;
// Stage 2: Execution
let Execution =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where FolderPath has_any (“\\Temp\\”, “\\AppData\\”)
| where FileName endswith “.exe”
| extend Stage = “Execution”
| summarize ExecutionTime = min(Timestamp) by DeviceName
| extend Stage2 = 1;
// Stage 3: Persistence
let Persistence =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where ProcessCommandLine has_any (“schtasks”, “reg add”, “CurrentVersion\\Run”)
| extend Stage = “Persistence”
| summarize PersistenceTime = min(Timestamp) by DeviceName
| extend Stage3 = 1;
// Stage 4: Defense Evasion
let DefenseEvasion =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where ProcessCommandLine has_any (“Set-MpPreference”, “DisableRealtimeMonitoring”, “ExclusionPath”)
| extend Stage = “Defense_Evasion”
| summarize DefenseEvasionTime = min(Timestamp) by DeviceName
| extend Stage4 = 1;
// Stage 5: Credential Access
let CredentialAccess =
DeviceFileEvents
| where Timestamp > ago(TimeWindow)
| where FolderPath has_any (“Login Data”, “logins.json”, “wallet.dat”, “keystore”)
| extend Stage = “Credential_Access”
| summarize CredentialAccessTime = min(Timestamp) by DeviceName
| extend Stage5 = 1;
// Stage 6: Collection
let Collection =
DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where ProcessCommandLine has_any (“SetWindowsHookEx”, “GetClipboardData”, “Screenshot”)
| extend Stage = “Collection”
| summarize CollectionTime = min(Timestamp) by DeviceName
| extend Stage6 = 1;
// Stage 7: C2 Communication
let C2 =
DeviceNetworkEvents
| where Timestamp > ago(TimeWindow)
| where RemoteUrl has_any (“/api/checkin”, “/api/upload”, “/gate.php”)
| extend Stage = “C2_Communication”
| summarize C2Time = min(Timestamp), C2Connections = count() by DeviceName
| extend Stage7 = 1;
// Stage 8: Exfiltration
let Exfiltration =
DeviceNetworkEvents
| where Timestamp > ago(TimeWindow)
| where RemotePort == 443
| where SentBytes > 1048576
| extend Stage = “Exfiltration”
| summarize ExfiltrationTime = min(Timestamp), TotalExfiltrated = sum(SentBytes) by DeviceName
| extend Stage8 = 1;
// Combine all stages
InitialAccess
| join kind=fullouter (Execution) on DeviceName
| join kind=fullouter (Persistence) on DeviceName
| join kind=fullouter (DefenseEvasion) on DeviceName
| join kind=fullouter (CredentialAccess) on DeviceName
| join kind=fullouter (Collection) on DeviceName
| join kind=fullouter (C2) on DeviceName
| join kind=fullouter (Exfiltration) on DeviceName
| extend DeviceName = coalesce(DeviceName, DeviceName1, DeviceName2, DeviceName3, DeviceName4, DeviceName5, DeviceName6, DeviceName7)
| summarize arg_min(InitialAccessTime, *) by DeviceName
| extend
StagesCompleted =
iff(Stage1 == 1, 1, 0) +
iff(Stage2 == 1, 1, 0) +
iff(Stage3 == 1, 1, 0) +
iff(Stage4 == 1, 1, 0) +
iff(Stage5 == 1, 1, 0) +
iff(Stage6 == 1, 1, 0) +
iff(Stage7 == 1, 1, 0) +
iff(Stage8 == 1, 1, 0)
| where StagesCompleted >= 3
| extend
AttackTimeline = pack_array(
iff(Stage1 == 1, strcat(“Initial Access: “, InitialAccessTime), “”),
iff(Stage2 == 1, strcat(“Execution: “, ExecutionTime), “”),
iff(Stage3 == 1, strcat(“Persistence: “, PersistenceTime), “”),
iff(Stage4 == 1, strcat(“Defense Evasion: “, DefenseEvasionTime), “”),
iff(Stage5 == 1, strcat(“Credential Access: “, CredentialAccessTime), “”),
iff(Stage6 == 1, strcat(“Collection: “, CollectionTime), “”),
iff(Stage7 == 1, strcat(“C2: “, C2Time), “”),
iff(Stage8 == 1, strcat(“Exfiltration: “, ExfiltrationTime), “”)
),
TotalDurationHours = datetime_diff(‘hour’,
max_of(ExecutionTime, PersistenceTime, DefenseEvasionTime, CredentialAccessTime, CollectionTime, C2Time, ExfiltrationTime),
InitialAccessTime),
Severity = case(
StagesCompleted >= 6, “Critical”,
StagesCompleted >= 4, “High”,
“Medium”),
CompromiseLevel = case(
StagesCompleted >= 6, “Full Compromise”,
StagesCompleted >= 4, “Significant Compromise”,
“Partial Compromise”),
ThreatFamily = “Direwolf”
| project
FirstActivity = InitialAccessTime,
DeviceName,
StagesCompleted,
CompromiseLevel,
TotalDurationHours,
AttackTimeline,
C2Connections,
TotalExfiltratedMB = TotalExfiltrated / 1048576.0,
Severity,
ThreatFamily
| sort by StagesCompleted desc, Severity desc
