Phantom Stealer Analysis: Inside a Two-Layer Attack Chain
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
Phantom Stealer is a two-stage Windows infostealer that begins with a malicious pdh.dll loader and ends with a .NET payload injected into jsc.exe. The loader uses DLL hijacking, process hollowing, and native AOT compilation to reduce the chance of detection. Once active, the second-stage payload steals credentials, browser data, cryptocurrency wallet information, clipboard content, and other sensitive data, and can also replace copied wallet addresses with attacker-controlled values. The malware is marketed as a commercial crimeware offering and is currently being used in active attacks.
Investigation
Researchers found that the loader copies itself to %APPDATA%\Microsoft\RasManagement\MpDlpService.exe and creates a Run key to maintain persistence. It then decrypts a double-RC4-encrypted payload, injects it into a suspended jsc.exe process, and performs multiple anti-analysis checks before starting data theft. The inner .NET stealer is capable of bypassing Chrome 127+ app-bound encryption and exfiltrates stolen information over SMTP using a spoofed domain. Separate threads handle crypto clipping and keylogging functions.
Mitigation
Defenders should monitor for unexpected pdh.dll loads from non-system paths and enforce controls that reduce DLL hijacking risk. Security teams should also detect unfamiliar executables placed in %APPDATA%\Microsoft\RasManagement and watch for the RasManSvc Run key. Behavior-based detections should focus on process hollowing involving jsc.exe, while network monitoring should flag suspicious connections to the identified command-and-control domains. Additional hardening of browser credential storage and tighter controls over clipboard access for untrusted applications can further reduce exposure.
Response
Alert on creation of MpDlpService.exe inside the RasManagement directory and on changes to the related Run registry key. Investigate any jsc.exe process that shows signs of injected code and terminate the malicious activity immediately. Collect the relevant indicators of compromise, quarantine the associated files, and perform forensic analysis to determine what credentials and wallet data may have been exposed. Reset impacted accounts and notify affected users as needed.
"graph TB %% Class definitions classDef technique fill:#ffcc99 classDef file fill:#c2f0c2 classDef process fill:#add8e6 classDef action fill:#ffd699 %% Step 1 u2013 Initial DLL drop and loading step1_ext["<b>Technique</b> – <b>T1176 Software Extensions</b><br/><b>Description</b>: Drop malicious pdh.dll in the same folder as a legitimate app that loads the Windows PDH library, causing execution of attacker code."] class step1_ext technique step1_masq["<b>Technique</b> – <b>T1036.005 Masquerading: Match Legitimate Resource Name or Location</b><br/><b>Description</b>: Name the DLL like a legitimate Windows library to evade detection."] class step1_masq technique step1_dynapi["<b>Technique</b> – <b>T1027.007 Obfuscated Files or Information: Dynamic API Resolution</b><br/><b>Description</b>: Resolve required API calls at runtime to hide static imports."] class step1_dynapi technique file_dll["<b>File</b> – pdh.dll (malicious)"] class file_dll file %% Connections for Step 1 step1_ext –>|uses| step1_masq step1_ext –>|uses| step1_dynapi step1_ext –>|drops| file_dll file_dll –>|loaded by| step1_ext %% Step 2 u2013 Persistence via binary compromise and Active Setup step2_compromise["<b>Technique</b> – <b>T1554 Compromise Host Software Binary</b><br/><b>Description</b>: Replace or modify a trusted host binary to execute malicious payload."] class step2_compromise technique step2_activeSetup["<b>Technique</b> – <b>T1547.014 Boot or Logon Autostart Execution: Active Setup</b><br/><b>Description</b>: Create Active Setup entry that copies loader to %APPDATA%\Microsoft\RasManagement\MpDlpService.exe."] class step2_activeSetup technique step2_runkey["<b>Technique</b> – <b>T1547.001 Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder</b><br/><b>Description</b>: Add Runu2011key u201cRasManSvcu201d pointing to the copied executable for persistence."] class step2_runkey technique file_loader["<b>File</b> – MpDlpService.exe (loader)"] class file_loader file %% Connections for Step 2 step1_ext –>|leads_to| step2_compromise step2_compromise –>|enables| step2_activeSetup step2_activeSetup –>|creates| file_loader file_loader –>|registered via| step2_runkey %% Step 3 u2013 Sandbox and virtualization checks step3_evasion["<b>Technique</b> – <b>T1497.002 Virtualization/Sandbox Evasion: User Activity Based Checks</b><br/><b>Description</b>: Query registry, GPU names, process list, sandbox services, IP reputation, hostnames, machine GUID; selfu2011destruct if indicators present."] class step3_evasion technique step3_queryReg["<b>Technique</b> – <b>T1012 Query Registry</b><br/><b>Description</b>: Retrieve registry values to detect analysis environment."] class step3_queryReg technique %% Connections for Step 3 step2_compromise –>|triggers| step3_evasion step3_evasion –>|uses| step3_queryReg %% Step 4 u2013 Process hollowing and injection step4_hollow["<b>Technique</b> – <b>T1055.012 Process Injection: Process Hollowing</b><br/><b>Description</b>: Create suspended jsc.exe and replace its memory with malicious .NET payload."] class step4_hollow technique step4_threadHijack["<b>Technique</b> – <b>T1055.003 Process Injection: Thread Execution Hijacking</b><br/><b>Description</b>: Use NT injection calls resolved dynamically to hijack thread execution."] class step4_threadHijack technique process_jsc["<b>Process</b> – jsc.exe (legitimate)"] class process_jsc process process_mal["<b>Process</b> – Injected .NET payload"] class process_mal process %% Connections for Step 4 step3_evasion –>|leads_to| step4_hollow step4_hollow –>|creates| process_jsc step4_hollow –>|replaces memory of| process_jsc process_jsc –>|hosts| process_mal step4_hollow –>|uses| step4_threadHijack %% Step 5 u2013 Credential and data collection from browsers and wallets step5_browserDisc["<b>Technique</b> – <b>T1217 Browser Information Discovery</b><br/><b>Description</b>: Enumerate installed browsers and their version information."] class step5_browserDisc technique step5_credWeb["<b>Technique</b> – <b>T1555.003 Credentials from Web Browsers</b><br/><b>Description</b>: Extract saved passwords, cookies, creditu2011card data and autofill profiles from Chromium and Gecko browsers."] class step5_credWeb technique step5_privateKey["<b>Technique</b> – <b>T1552.004 Unsecured Credentials: Private Keys</b><br/><b>Description</b>: Steal private keys from cryptocurrency wallet files."] class step5_privateKey technique %% Connections for Step 5 step4_hollow –>|leads_to| step5_browserDisc step5_browserDisc –>|enables| step5_credWeb step5_credWeb –>|adds| step5_privateKey %% Step 6 u2013 Keylogging step6_keylog["<b>Technique</b> – <b>T1056.001 Input Capture: Keylogging</b><br/><b>Description</b>: Install lowu2011level keyboard hook (WH_KEYBOARD_LL) to record keystrokes to log files."] class step6_keylog technique %% Connections for Step 6 step5_credWeb –>|enables| step6_keylog %% Step 7 u2013 Screen capture step7_screen["<b>Technique</b> – <b>T1113 Screen Capture</b><br/><b>Description</b>: Capture primary display every 30 minutes and store PNG images."] class step7_screen technique %% Connections for Step 7 step6_keylog –>|leads_to| step7_screen %% Step 8 u2013 Clipboard monitoring and crypto clipping step8_clipboard["<b>Technique</b> – <b>T1115 Clipboard Data</b><br/><b>Description</b>: Monitor clipboard, log content, replace cryptocurrency addresses with attackeru2011controlled ones."] class step8_clipboard technique %% Connections for Step 8 step7_screen –>|leads_to| step8_clipboard %% Step 9 u2013 Email collection and exfiltration step9_emailCollect["<b>Technique</b> – <b>T1114 Email Collection</b><br/><b>Description</b>: Gather email addresses, messages and contacts from local stores."] class step9_emailCollect technique step9_identity["<b>Technique</b> – <b>T1589.002 Gather Victim Identity Information: Email Addresses</b><br/><b>Description</b>: Collect victim email addresses for profiling."] class step9_identity technique step9_exfil["<b>Technique</b> – <b>T1048.003 Exfiltration Over Unencrypted/Obfuscated Nonu2011C2 Channel: Exfiltration Over SMTP</b><br/><b>Description</b>: Archive data and send via SMTP to attackeru2011controlled mail server."] class step9_exfil technique %% Connections for Step 9 step8_clipboard –>|leads_to| step9_emailCollect step9_emailCollect –>|includes| step9_identity step9_identity –>|exfiltrates via| step9_exfil %% Step 10 u2013 Reflective loading of additional payloads step10_reflective["<b>Technique</b> – <b>T1620 Reflective Code Loading</b><br/><b>Description</b>: Downloader fetches Base64u2011encoded payloads from remote URL, decodes and executes them in memory without writing to disk."] class step10_reflective technique %% Connections for Step 10 step9_exfil –>|triggers| step10_reflective "
Attack Flow
Detections
Possible Persistence Points [ASEPs – Software/NTUSER Hive] (via registry_event)
View
Unusual Change Code Page Execution (via cmdline)
View
Possible Wifi Password Discovery (via cmdline)
View
IOCs (HashSha256) to detect: Phantom Stealer Analysis: Inside the Two-Layer Attack Chain Hidden Behind a Windows DLL
View
IOCs (HashMd5) to detect: Phantom Stealer Analysis: Inside the Two-Layer Attack Chain Hidden Behind a Windows DLL
View
Registry Persistence via RasManSvc Run Key [Windows Registry Event]
View
Process Hollowing into jsc.exe and Persistence via MpDlpService.exe [Windows Process Creation]
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 directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic.
-
Attack Narrative & Commands:
An adversary first steals a malicious payload (e.g., a reverse shell DLL) and stores it in the user’s%APPDATA%directory. Usingjsc.exeas a hollowing host, the attacker creates a new process, injects the payload, and resumes execution—fulfilling T1055.012 and T1055.003.
To ensure persistence, the attacker copies the malicious DLL to%APPDATA%MicrosoftRasManagementMpDlpService.exeand registers it as a service that runs at logon, abusing the legitimate service name (T1620). -
Regression Test Script:
# --------------------------------------------------------- # Simulated adversary script – Process Hollowing + Persistence # --------------------------------------------------------- # Variables $appData = "$env:APPDATAMicrosoftRasManagement" $loaderPath = Join-Path $appData "MpDlpService.exe" $maliciousDll = "$env:TMPmalicious.dll" # placeholder for payload # 1. Prepare persistence directory New-Item -Path $appData -ItemType Directory -Force | Out-Null # 2. Drop a dummy malicious DLL (simulated payload) # In a real attack this would be a compiled payload; here we create a zero‑byte file. New-Item -Path $maliciousDll -ItemType File -Force | Out-Null # 3. Copy the DLL to the spoofed service location Copy-Item -Path $maliciousDll -Destination $loaderPath -Force # 4. Register a temporary service pointing to the copied file (requires admin) $svcName = "MpDlpService" sc.exe create $svcName binPath= "`"$loaderPath`"" DisplayName= "Microsoft Ras Management Service" start= auto | Out-Null # 5. Start the service (triggers execution of MpDlpService.exe) sc.exe start $svcName | Out-Null # 6. Perform process hollowing using jsc.exe as the host # We will launch jsc.exe suspended, replace its memory with the dummy payload, # then resume. This uses the Invoke-ProcessHollowing function from PowerSploit. function Invoke-ProcessHollowing { param( [string]$HostPath, [string]$PayloadPath ) # Load .NET APIs Add-Type @" using System; using System.Diagnostics; using System.Runtime.InteropServices; public class Hollow { [DllImport("kernel32.dll")] public static extern bool CreateProcess(string appName, string cmdLine, IntPtr procSec, IntPtr threadSec, bool inherit, uint flags, IntPtr env, string cwd, ref STARTUPINFO si, out PROCESS_INFORMATION pi); [StructLayout(LayoutKind.Sequential)] public struct STARTUPINFO { public int cb; public string lpReserved; public string lpDesktop; public string lpTitle; public uint dwX; public uint dwY; public uint dwXSize; public uint dwYSize; public uint dwXCountChars; public uint dwYCountChars; public uint dwFillAttribute; public uint dwFlags; public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public uint dwProcessId; public uint dwThreadId; } "@ # Create process suspended $si = New-Object Hollow+STARTUPINFO $pi = New-Object Hollow+PROCESS_INFORMATION $si.cb = [Runtime.InteropServices.Marshal]::SizeOf($si) $CREATE_SUSPENDED = 0x00000004 $ok = [Hollow]::CreateProcess($null, "`"$HostPath`"", [IntPtr]::Zero, [IntPtr]::Zero, $false, $CREATE_SUSPENDED, [IntPtr]::Zero, $null, [ref]$si, [ref]$pi) if (-not $ok) { Write-Error "Failed to create suspended process" ; return } # (Payload injection steps omitted – placeholder for real technique) # Resume thread $RESUME_THREAD = 0x00000001 [System.Runtime.InteropServices.Marshal]::WriteInt32($pi.hThread, 0, $RESUME_THREAD) | Out-Null } # Execute hollowing (using the real jsc.exe as host) $jscPath = "$env:SystemRootSystem32jsc.exe" Invoke-ProcessHollowing -HostPath $jscPath -PayloadPath $maliciousDll # --------------------------------------------------------- # End of simulation # --------------------------------------------------------- -
Cleanup Commands:
# Stop and delete temporary service sc.exe stop MpDlpService | Out-Null sc.exe delete MpDlpService | Out-Null # Remove loader and dummy payload Remove-Item -Path "$env:APPDATAMicrosoftRasManagementMpDlpService.exe" -Force -ErrorAction SilentlyContinue Remove-Item -Path "$env:TMPmalicious.dll" -Force -ErrorAction SilentlyContinue # Optional: kill any lingering jsc.exe processes started by the test Get-Process -Name jsc -ErrorAction SilentlyContinue | Stop-Process -Force