Direwolf Malware: Complete Detection and Threat Hunting Rules

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


Aegiron

Backed by 11+ years in cybersecurity and incident response, we decode the latest threats shaping today’s digital battlefield. This blog cuts through the noise with clear insights on vulnerabilities, emerging exploits, and the cyber news defenders can’t afford to miss.