Beyond the Obfuscation: Reconstructing a Multi-Stage Malware Framework

Executive Summary

The analyzed sample is a multi-stage Windows malware delivery chain consisting of several independent components rather than a single monolithic payload.

The initial stages are relatively small and exist solely to bootstrap progressively larger payloads. The JavaScript stage is heavily obfuscated but has been successfully deobfuscated to the point where its execution flow and major functionality are now understood.

Current evidence suggests the JavaScript component functions as a persistent loader/orchestrator, responsible for generating and deploying a PowerShell persistence mechanism which eventually downloads and executes a Windows executable.

At the time of writing, the final executable has not been recovered or executed.

Stage 1 – Initial Loader

The original sample (renamed during analysis) is a VBScript launcher.

Its responsibilities are minimal:

  • Launch PowerShell hidden
  • Download the next stage
  • Execute it

No significant malicious functionality exists within this stage beyond acting as a bootstrapper.

Stage 2 – PowerShell Downloader

The PowerShell stage retrieves the next payload:

  • Downloads an obfuscated JavaScript file
  • Saves it locally
  • Executes it using Node.js

Again, this stage primarily acts as a downloader.

Stage 3 – Obfuscated NodeJS Malware

The downloaded JavaScript is a large bundled NodeJS application.

Characteristics:

  • Single-line bundle
  • Approximately 43,000+ logical lines after formatting
  • Multiple embedded modules
  • Custom module loader
  • Heavy string obfuscation
  • Runtime string decoding

The malware is clearly modular rather than being written as one large script.

Obfuscation Analysis

The JavaScript uses two central functions responsible for nearly all string recovery.

String Table

Located at approximately:

 
37960
 

Function:

 
_0x333e()
 

This function returns the large encoded string table used throughout the malware.

Decoder

Located at approximately:

 
43438
 

Function:

 
_0x12f2()
 

Analysis confirmed that this function:

  • retrieves entries from the string table
  • Base64 decodes them
  • applies URI decoding
  • caches decoded values

Importantly:

No RC4 encryption was identified.

No XOR layer was identified.

The majority of the obfuscation is therefore based on runtime string lookup rather than encrypted strings.


Automated Deobfuscation

Custom scripts were written during analysis to:

  • identify wrapper functions
  • replace wrapper calls
  • recover decoded strings

Results:

  • ~45 wrapper functions recovered
  • 237 wrapper calls automatically replaced

This significantly improved readability of the malware.

Modular Architecture

Recovered modules indicate the malware contains functionality for:

  • filesystem interaction
  • process creation
  • networking
  • software enumeration
  • clipboard access
  • system information
  • persistence generation

The malware behaves more like a modular RAT framework than a simple downloader.

Environment Configuration

One module manually parses environment configuration and stores values inside a configuration object.

Recovered configuration includes variables such as:

 
RELAY_URL
BLOCKCHAIN_CONTRACT
SUPER_ADMIN_KEY
CLIENT_COMMENT
 

It also defines reconnect behaviour:

 
RECONNECT_MIN_MS = 3000
RECONNECT_MAX_MS = 30000
CONNECT_TIMEOUT_MS = 12000
 

These values suggest the malware was designed to maintain long-lived communication rather than performing a one-time operation.

Child Process Usage

Recovered code confirms the malware dynamically resolves and imports:

 
child_process
 

Specifically:

 
spawnSync
 

is imported through dynamically constructed strings rather than literal imports.

This allows the malware to launch external processes while avoiding simple signature detection.

Persistence Builder

One of the most significant discoveries was identification of the persistence builder.

Recovered export:

 
exports = {
    buildPersistentCaptureScript: _0x5f26aa
}
 

Elsewhere in the malware:

 
buildPersistentCaptureScript
 

is imported as:

 
_0x209083
 

Analysis confirmed these are the same function.

Dynamic PowerShell Generation

Unlike ordinary malware that embeds PowerShell directly, this sample constructs an entire PowerShell script dynamically.

The builder consists almost entirely of thousands of concatenated decoded strings.

Simplified:

 
return (
    decode(...)
    + decode(...)
    + decode(...)
    + ...
);
 

The script therefore exists only at runtime.

Persistence Execution Flow

Execution tracing recovered the following behaviour:

 
buildPersistentCaptureScript()

↓

Generate PowerShell

↓

Write script to disk

↓

Launch hidden PowerShell

↓

Execute script
 

This execution chain has been confirmed through static analysis.

Module Wrapper

The persistence builder is not standalone.

It resides inside a CommonJS-style module wrapper.

Recovered structure:

 
_0x37e9a3 = _0x844699((module, exports) => {

    function _0x5f26aa() {

    }

});
 

The exact implementation of _0x844699() has not yet been recovered.

Current evidence strongly suggests it functions as the bundle’s internal module loader.

Generated PowerShell

The generated PowerShell has not yet been fully reconstructed.

Attempts were made to extract the builder into a standalone script.

This failed because the extracted function depends upon surrounding module state.

Specifically, extraction cut the module before all required definitions were available.

This remains the primary outstanding reverse engineering task.

Recovered PowerShell Behaviour

A later PowerShell stage recovered during analysis performs the following actions:

  • Creates
 
C:\Tool
 

if necessary.

  • Generates a random executable name:
 
hige_<GUID>.exe
 
  • Downloads an executable into that directory.
  • Executes it using:
 
Start-Process
 

Rather than embedding configuration inside the executable, the script passes a command-line argument to the process.

Recovered argument:

 
nextjs2385.ngrok.io
 

This indicates the executable likely receives its communication endpoint at runtime rather than having it hardcoded.

Infrastructure Observations

One notable design choice is that the executable appears to be configured externally through PowerShell.

This architecture would allow the operator to rotate infrastructure by modifying only the PowerShell script while leaving the executable unchanged.

Current evidence is consistent with a staged loader architecture.

Current Execution Chain

Based on confirmed analysis:

 
VBScript

↓

PowerShell Downloader

↓

Obfuscated NodeJS Bundle

↓

Generate PowerShell Persistence Script

↓

Write Script

↓

Execute Hidden PowerShell

↓

Download Windows Executable

↓

Launch Executable
    └── receives:
        nextjs2385.ngrok.io
 

Outstanding Work

The following items remain unresolved:

  • Recover the implementation of _0x844699() (module loader).
  • Recover the implementation of _0x161069().
  • Fully reconstruct the dynamically generated PowerShell produced by buildPersistentCaptureScript().
  • Determine the exact persistence mechanism employed by the generated script (e.g., scheduled task, registry, service, or other).
  • Recover and analyze the final downloaded Windows executable.
  • Determine the communication protocol and capabilities of the final implant.

Current Assessment

At this stage, the malware appears to be a modular, staged loader rather than a simple commodity downloader. Each component performs a narrowly defined task before handing execution to the next stage. The JavaScript component acts as the orchestration layer, dynamically constructing PowerShell rather than embedding it directly, while subsequent PowerShell stages download and launch a configurable Windows executable.

The reverse engineering effort has successfully removed the primary obfuscation layer, mapped the execution flow, identified the persistence builder, and confirmed how later stages are deployed. The principal remaining task is reconstructing the dynamically generated PowerShell, as this is expected to reveal the exact persistence mechanism and bridge the gap between the NodeJS loader and the final Windows executable.

File Hashes

stage2.ps1

Algorithm 
MD5307e73bb7d7e0a710fe38d9a6a1f5b73
SHA1e674e30ccf95a6f3612a5a12696eb79bad83c30a
SHA2563fa6e2ade383cb3baaf6064805abb333c4bac7753e2c99317da540fddfb8a6df
SHA512ee06531dc2c31c5b358ad6306d06484f2bb8425c3822299633a58b7e4b690df6a478bfbba6f347c92e589339c4fffe1a69fbaf83625ade09c8ce9ea00fe78ca9

main.js

Algorithm 
MD52086d6c67da0d73de156bc31296f3f6d
SHA154c6dd7e0a6e9585b80302354b2d7d4ffbabc939
SHA256f3bec7bcd0461d7ba02574ffa87c34eba110cbe184ffdcdfe09a1d9fbb6c31bd
SHA512f4c58d70502c7dc619ccd975d2197ee435e039796e09880359973511b2dcce8474cf7ced21da8f804eb56f44ed34d028998c553ad279c1ba06b04195311c9e83

Original.vbs

Algorithm 
MD5c491cf88775d9f8e7d4fae087dc68630
SHA1fb3fb36d9d612c0dfdfddb89c452bd718dc39258
SHA256ea8fcad382a64ad10f139ba40fa81dc597cd779eda8a6fdadd5125fb96471c5f
SHA51238339c639a2e88f5782b285077dcace0f8254fc4088058c017e1c126aec825c51769d41484e49f2f90f6d3c75125968a03a8dbf84970fcad31d8c20af7d171ba

Dynamic Analysis

Static analysis gave a solid understanding of the malware’s architecture, but executing the recovered PowerShell stage inside an isolated sandbox revealed how the infection chain behaves in the real world.

The initial PowerShell payload didn’t simply execute a few commands and exit. Instead, it acted as an orchestrator, downloading additional components before transitioning execution into a bundled Node.js runtime.

The observed execution chain looked like this:

 
VBS
   ↓
stage2.ps1
   ↓
Downloads Node.js runtime
   ↓
Launches node.exe
   ↓
Executes the NodeJS RAT
 

Rather than relying on Node.js already being installed on the victim machine, the malware brings its own runtime, ensuring the JavaScript payload executes consistently across infected systems.

Once running, the Node process immediately began profiling the host.

Among the first actions observed were process enumeration using tasklist, collection of system information through WMI/CIM cmdlets, and retrieval of the victim’s public IP address via api.ipify.org.

Only after gathering this information did the malware establish communication with its command-and-control infrastructure.

Unlike many modern families that tunnel communications over HTTP or WebSockets, this sample establishes a raw TCP connection to its C2 server:

 
213.145.86.180:22861
 

Capturing and analyzing the network traffic showed that the protocol is surprisingly straightforward.

Every packet begins with a 4-byte big-endian length field followed by a UTF-8 JSON object.

The first message sent by the client is a registration packet containing host profiling information similar to the following:

 
{
  "type": "register",
  "machine_uuid": "...",
  "hostname": "DESKTOP-JGLLJLD",
  "username": "admin",
  "runAs": "user",
  "isElevated": false,
  "platform": "windows",
  "arch": "x64",
  "connection_platform": "node-tcp",
  "connected_transport": "tcp",
  "connected_endpoint": "213.145.86.180:22861",
  "public_ip": "85.xxx.xxx.xxx",
  "super_admin_key": "dB22d802"
}
 

The server responds by acknowledging the registration:

 
{
  "client_id": 1280,
  "type": "registered"
}
 

Afterwards, the C2 maintains the session using a simple heartbeat mechanism.

Server:

 
{
  "type": "ping",
  "seq": 0
}
 

Client:

 
{
  "type": "pong",
  "clientId": 1280
}
 

This confirms the malware is not performing one-off beaconing but maintaining an interactive TCP session while waiting for operator commands.

One particularly interesting field exposed during registration is the super_admin_key, suggesting the framework may support privileged sessions or operator authentication. Determining whether this value is statically embedded, generated at runtime, or used for access control would require additional reversing of the Node.js source.

Overall, dynamic analysis confirmed several observations made during static reversing:

  • The malware uses a bundled Node.js runtime rather than Windows Script Host.
  • Initial execution performs host reconnaissance before contacting the C2.
  • Communications occur over a custom length-prefixed JSON protocol instead of HTTP.
  • The RAT identifies victims using host metadata including hostname, username, architecture, privilege level, machine UUID, and public IP address.
  • Once registered, the implant maintains a persistent TCP session and exchanges heartbeat packets while awaiting further instructions.

While the JavaScript was heavily obfuscated, observing the malware at runtime demonstrated that the underlying protocol itself is remarkably simple. The complexity lies almost entirely in the delivery chain and code obfuscation rather than the command-and-control implementation, which relies on structured JSON messages transmitted over a persistent TCP socket.

Recovered Remote Resources

Static and dynamic analysis identified several remote resources used throughout the infection chain. These resources host successive payloads and supporting components required for installation and execution.

Stage 2 PowerShell

Downloaded by the initial VBS launcher.

 
https://nextjs2385.ngrok.io/cdn/stage2.ps1
 

Node.js Runtime

The installer retrieves the official Node.js runtime directly from the Node.js project.

x64

 
https://nodejs.org/download/release/v20.11.0/node-v20.11.0-win-x64.zip
 

x86

 
https://nodejs.org/download/release/v20.11.0/node-v20.11.0-win-x86.zip
 

ARM64

 
https://nodejs.org/download/release/v20.11.0/node-v20.11.0-win-arm64.zip
 

JavaScript Implant

Hosted on Google Cloud Storage.

 
https://storage.googleapis.com/gts-files-2026/94675e6d-bebf-4cf0-98aa-0897442f19cc/main.js
 

Additional PowerShell Stage

Following installation, the malware retrieves and executes an additional PowerShell script hosted behind an Ngrok endpoint.

 
https://nextjs781.ngrok.app/cdn/hello_world.txt
 

Executable Payloads

Analysis of the recovered PowerShell revealed support for downloading architecture-specific native payloads.

 
https://nextjs781.ngrok.app/cdn/hige-x86.exe
https://nextjs781.ngrok.app/cdn/hige-x64.exe
https://nextjs781.ngrok.app/cdn/hige-arm64.exe
 

The appropriate executable is selected dynamically based on the victim’s processor architecture before execution.

Safe Retrieval

For forensic analysis, payloads can be retrieved without execution using standard HTTP clients.

 
# JavaScript implant
curl -o main.js \
"https://storage.googleapis.com/gts-files-2026/94675e6d-bebf-4cf0-98aa-0897442f19cc/main.js"

# Additional PowerShell stage
curl -o hello_world.ps1 \
"https://nextjs781.ngrok.app/cdn/hello_world.txt"

# Native payload
curl -o hige-x64.exe \
"https://nextjs781.ngrok.app/cdn/hige-x64.exe"