New Castle Campaigns Reveal Evolving Tooling and NeedleStealer Ties
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
Arctic Wolf Labs has uncovered new developments in the CastleLoader infection chain, including the integration of the NeedleStealer framework. The updated activity introduces Rust-based cryptocurrency wallet spoofers and Golang-based malicious browser extensions. The campaign also relies on advanced delivery techniques such as NodeJS-based injectors and digitally signed installers to reduce detection.
Investigation
Researchers used active C2 querying, YARA-based retrohunting, and sandbox detonation to analyze the latest activity. They identified three separate campaigns, Urutyka, Garrigin, and Noidret, each featuring differences in payloads and supporting infrastructure. The investigation also decrypted C2 responses with recovered RC4 keys, allowing analysts to confirm payload manifests and campaign behavior.
Mitigation
Defenders should enforce application allowlisting to prevent unauthorized execution from writable locations such as %ProgramData%. Enabling PowerShell Script Block Logging and monitoring for suspicious Python or NodeJS activity can help detect malicious behavior. Organizations should also verify code-signing certificates and block infrastructure associated with identified malicious campaigns.
Response
If CastleLoader activity is detected, organizations should immediately block known C2 domains and IP addresses at both DNS and firewall layers. Investigators should examine any NodeJS or IronPython (ipyw32.exe) processes running from unusual or non-standard locations. A broader environment-wide hunt should also be conducted for the approximately 8 KB x64 shellcode stub.
Attack Flow
Detections
Suspicious RunMRU Entry With LOLBin Semantics (via registry_event)
View
NodeJS Binary Executing From Uncommon Location (via cmdline)
View
Suspicious Powershell Strings (via powershell)
View
Call Suspicious .NET Methods from Powershell (via powershell)
View
Suspicious File Download Direct IP (via proxy)
View
Possible Cloudflare Development Domain Abuse (via dns)
View
IOCs (HashSha256) to detect: Expanding the Castle: New Campaigns, New Tooling, and the NeedleStealer Connection
View
IOCs (HashMd5) to detect: Expanding the Castle: New Campaigns, New Tooling, and the NeedleStealer Connection
View
IOCs (SourceIP) to detect: Expanding the Castle: New Campaigns, New Tooling, and the NeedleStealer Connection
View
IOCs (DestinationIP) to detect: Expanding the Castle: New Campaigns, New Tooling, and the NeedleStealer Connection
View
Detect IOC Domains IP Blocking for CastleLoader Campaigns [Firewall]
View
Detection of CastleLoader Infection Chain [Windows Powershell]
View
Simulation Execution
Prerequisite: The Telemetry & Baseline Pre-flight Check must have passed.
Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative MUST directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic. Abstract or unrelated examples will lead to misdiagnosis.
-
Attack Narrative & Commands: An adversary has deployed a NeedleStealer payload via a CastleLoader campaign. To communicate with the Command and Control (C2) server, the malware attempts to resolve and connect to
goodbyetelegramm.com. This action is intended to generate a firewall connection event (Event ID 5156) containing the malicious domain/IP, which should trigger the detection rule. Following this, we simulate a “bypass” by connecting togoodbyetelegramm-updated.comto show how infrastructure rotation evades the static list. -
Regression Test Script:
# Simulation Script: CastleLoader IOC Trigger # This script attempts to create network traffic to the specific IOCs listed in the Sigma rule. $IOC_Domains = @("goodbyetelegramm.com", "urutyka.com", "eazysitebuilder.com") $IOC_IPs = @("91.92.33.167", "179.132.128.189") Write-Host "[+] Starting CastleLoader IOC Simulation..." -ForegroundColor Cyan # 1. Triggering the Rule via Domain foreach ($domain in $IOC_Domains) { Write-Host "[!] Attempting connection to IOC Domain: $domain" -ForegroundColor Yellow try { # Using a low-level socket connection to ensure Event 5156 is generated $tcpClient = New-Object System.Net.Sockets.TcpClient $connect = $tcpClient.BeginConnect($domain, 80, $null, $null) $wait = $connect.AsyncWaitHandle.WaitOne(2000, $false) if (-not $wait) { Write-Host "[?] Connection timed out (expected if domain is sinkholed/blocked)" -ForegroundColor Gray } $tcpClient.Close() } catch { Write-Host "[?] Connection failed (expected if domain is non-existent)" -ForegroundColor Gray } } # 2. Triggering the Rule via IP foreach ($ip in $IOC_IPs) { Write-Host "[!] Attempting connection to IOC IP: $ip" -ForegroundColor Yellow try { $tcpClient = New-Object System.Net.Sockets.TcpClient $tcpClient.Connect($ip, 80) $tcpClient.Close() } catch { Write-Host "[?] Connection failed (expected if IP is unreachable)" -ForegroundColor Gray } } # 3. Demonstrating Evasion (The "Resilience Test") Write-Host "[!] Demonstrating Evasion: Connecting to a slightly modified domain..." -ForegroundColor Magenta try { $evasionDomain = "goodbyetelegramm-new-version.com" $tcpClient = New-Object System.Net.Sockets.TcpClient $connect = $tcpClient.BeginConnect($evasionDomain, 80, $null, $null) $wait = $connect.AsyncWaitHandle.WaitOne(2000, $false) $tcpClient.Close() Write-Host "[+] Evasion connection attempted. Check SIEM: This should NOT trigger the rule." -ForegroundColor Green } catch { Write-Host "[?] Evasion connection failed, but the logic remains untested by the rule." -ForegroundColor Gray } Write-Host "[+] Simulation Complete." -ForegroundColor Cyan -
Cleanup Commands:
# No persistent changes made by the simulation script. # However, clear local DNS cache to ensure no artifacts remain. Clear-DnsClientCache Write-Host "[+] Cleanup complete: DNS Cache cleared." -ForegroundColor Green