Photo ZIP campaign targeting hospitality industry delivers Node.js implant for persistent access
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
An active multi-stage intrusion campaign is targeting the hospitality sector through photo-themed ZIP archives that contain malicious LNK files. The infection chain uses obfuscated PowerShell decoders, on-the-fly .NET DLL compilation, and a Node.js-based implant for persistence and command-and-control communication. The threat actor also launders authentication through legitimate services such as Calendly and Google to reduce the chance of email-based detection.
Investigation
Microsoft identified two separate waves of the campaign and observed a progression from simple PowerShell loaders to more complex .NET compilation stages. The investigation also uncovered a dual-persistence strategy that relied on both HKCU\Run and HKCU\RunOnce registry keys. Researchers further noted the use of Cloudflare-fronted domains and non-standard command-and-control ports to obscure the supporting infrastructure.
Mitigation
Organizations should prioritize layered detections for shortcut execution, unexpected .NET compilation, and Node.js processes launched from user-writable directories. Enabling Attack Surface Reduction rules and monitoring for unauthorized Microsoft Defender exclusion changes is strongly recommended. Blocking suspicious .cfd domain patterns and watching for outbound traffic over unusual ports can also help reduce exposure.
Response
If this activity is detected, remediation should include removal of both the ProgramData RunOnce entry and the Node.js Run key to stop the implant from restoring itself. Security teams should also delete the Node.js runtime and related .js payloads from the AppData\Local\Nodejs directory. Complete cleanup requires addressing both the active payload and any persistence mechanisms left behind.
"flowchart TD step_phishing["T1566.002 u2013 Phishing: Spearphishing Link: Uses authentication laundering via Calendly and Google redirects to deliver a photo-themed ZIP archive."] step_user_execution["T1204.002 u2013 User Execution: Malicious File: Victim opens a fake image shortcut (.lnk) which triggers an obfuscated PowerShell downloader."] rules_for_user_execution("<b>Rule Name</b>: Possible Malicious LNK File with Double Extension<br/><b>Rule ID</b>: 13f9a3c1-b2fe-4268-8052-bf6fe353e952") step_obfuscation["T1027 u2013 Obfuscated Files or Information: PowerShell uses arithmetic decoding (XOR, modulo) to retrieve subsequent stages."] rules_for_obfuscation("<b>Rule Name</b>: Possible Powershell Obfuscation Indicators<br/><b>Rule ID</b>: a11f179d-8248-4d34-905c-e61735a72688") step_compilation["T1027.004 u2013 Compile After Delivery: PowerShell triggers .NET compilation using csc.exe and cvtres.exe to create DLLs."] step_implant_execution["Node.js-based implant execution: Deployment of malicious .js payloads via node.exe."] rules_for_implant_execution("<b>Rule Name</b>: Possible Node Spawned By Known Abused Process<br/><b>Rule ID</b>: b36fbdaf-1bab-45c2-a15b-f0c25c696d72") step_persistence["T1547.014 u2013 Boot or Logon Autostart Execution: Active Setup: Dual model using 'Run' and 'RunOnce' registry keys for the Node.js component and ProgramData executable."] rules_for_persistence("<b>Rule Name</b>: Possible Persistence Points [ASEPs – Software/NTUSER Hive]<br/><b>Rule ID</b>: 4cb3ac97-0fab-4447-9054-6f2d6ca102a1") step_command_and_control["TA0011 u2013 Command and Control: Beaconing to fixed IP infrastructure over non-standard ports (8443, 56001) and headless browser automation."] rules_for_c2("<b>Rule Name</b>: Suspicious Command and Control by Unusual Top Level Domain (TLD) DNS Request (via dns)<br/><b>Rule ID</b>: 63f3e8bc-0241-4f00-b9db-d4c309e61036") rules_for_c2_network("<b>Rule Name</b>: Scripting Runtimes Initiating Outbound TLS Connections (via network_connection)<br/><b>Rule ID</b>: 1ac66e9b-fd10-4c8c-af41-8c3d901ba03d") step_phishing –>|leads_to| step_user_execution step_user_execution –>|triggers| step_obfuscation step_user_execution -.->|detected_by| rules_for_user_execution step_obfuscation –>|leads_to| step_compilation step_obfuscation -.->|detected_by| rules_for_obfuscation step_compilation –>|enables| step_implant_execution step_implant_execution –>|establishes| step_persistence step_implant_execution -.->|detected_by| rules_for_implant_execution step_persistence –>|leads_to| step_command_and_control step_persistence -.->|detected_by| rules_for_persistence step_command_and_control -.->|detected_by| rules_for_c2 step_command_and_control -.->|detected_by| rules_for_c2_network "
Attack Flow
Detections
Suspicious Command and Control by Unusual Top Level Domain (TLD) DNS Request (via dns)
View
Possible Persistence Points [ASEPs – Software/NTUSER Hive] (via registry_event)
View
Possible Malicious LNK File with Double Extension (via cmdline)
View
Possible Node Spawned By Known Abused Process (via cmdline)
View
Windows Defender Preferences Suspicious Changes (via powershell)
View
Possible Powershell Obfuscation Indicators (via powershell)
View
Scripting Runtimes Initiating Outbound TLS Connections (via network_connection)
View
Detection of Non-standard C2 Ports and .cfd Domain Traffic [Windows Network Connection]
View
Detect Obfuscated PowerShell BigInt Decoder with Defender Evasion [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 gained initial access via a spearphishing link (T1566.002). To establish persistence and Command and Control (C2), the adversary deploys a lightweight PowerShell-based implant. To avoid detection by basic firewall rules that only monitor standard ports, the attacker decides to use a non-standard port (8443) for the primary heartbeat. Additionally, the implant is configured to perform a secondary “phone home” to a backup domain hosted on a
.cfdTLD to ensure resilience if the primary IP is blocked. This mimics the behavior of the Photo-Zip campaign mentioned in the rule’s references. -
Regression Test Script:
# Simulation Script: C2 Emulation for Rule Validation # This script simulates network connections to non-standard ports and .cfd domains. Write-Host "[+] Starting C2 Simulation..." -ForegroundColor Cyan # 1. Simulate connection to a non-standard C2 port (8443) # We use a public IP that listens on 8443 (or a local listener if available) Write-Host "[+] Attempting connection to non-standard port 8443..." -ForegroundColor Yellow try { $tcpClient = New-Object System.Net.Sockets.TcpClient $tcpClient.Connect("8.8.8.8", 8443) # Using Google DNS as a dummy target for port testing } catch { Write-Host "[!] Port 8443 connection failed (Expected if port is closed), but telemetry should still be generated." -ForegroundColor Gray } finally { $tcpClient.Close() } # 2. Simulate connection to a .cfd domain # We attempt to resolve and connect to a dummy .cfd domain Write-Host "[+] Attempting connection to .cfd domain..." -ForegroundColor Yellow $cfdDomain = "malicious-c2-test.cfd" try { # Using Resolve-DnsName to trigger DNS telemetry, followed by a web request Resolve-DnsName -Name $cfdDomain -ErrorAction SilentlyContinue Invoke-WebRequest -Uri "http://$cfdDomain" -TimeoutSec 2 -ErrorAction SilentlyContinue } catch { Write-Host "[!] .cfd domain connection failed (Expected for dummy domain), but telemetry should be generated." -ForegroundColor Gray } Write-Host "[+] Simulation Complete." -ForegroundColor Cyan -
Cleanup Commands:
# Cleanup: No persistent artifacts were created by this specific script. # If a listener was started, it should be stopped. Write-Host "[+] No cleanup required for this stateless simulation." -ForegroundColor Green