Back

Windows Update Lure Delivers Bun-Based RAT via IT Impersonation

Luis Garcia
Luis Garcia
September 21, 2026
Research
Windows Update Lure Delivers Bun-Based RAT via IT ImpersonationBright curved horizon of a planet glowing against the dark backdrop of space.Bright curved horizon of a planet glowing against the dark backdrop of space.

Executive Summary

Daylight researchers investigated an intrusion in which a threat actor impersonated an organization's IT department to deliver a custom remote access tool (RAT) built on the Bun JavaScript runtime. The victim was directed to download an archive from an S3 bucket constructed to resemble the organization's internal IT infrastructure, which extracted and launched a four-component RAT disguised as a Windows Update.

The malware shares characteristics with the DinDoor Deno RAT, previously documented by Daylight, and we will continue tracking both activity clusters.

The Lure: IT Impersonation

The victim was directed to download a file from an S3 bucket whose name was constructed to impersonate the organization's internal IT department. We weren't able to conclusively determine the exact initial contact vector. The URL followed the pattern:

hxxps://<org>-it[.]s3[.]us-east-1[.]amazonaws[.]com/download1/<kb-article>.p

The file was a disguised archive referencing a fake Windows KB article number that carried through consistently into the extraction path, the on-screen lure, and the process tree. This level of detail makes the activity look like routine patch management at a glance.

The Payload: A Windows Update That Wasn't

The archive was extracted using tar.exe, a native Windows utility, into AppData\Roaming\<kb-article>:

tar -xf C:\Users\<redacted>\Downloads\<kb-article>.p -C C:\Users\<redacted>\AppData\Roaming\<kb-article>

The archive contained five files. All component filenames were randomly generated strings with no identifying pattern. We use functional names throughout this article to distinguish them.

Functional Name Role
<runtime>.exe Bundled Bun runtime (bun v1.4.0.0, self-contained), named to match the KB article number
<launcher>.js Launcher / lure UI / process orchestrator
<agent>.js Local command execution and filesystem agent
<proxy>.js TCP socket proxy
<relay>.js Command and control (C2) relay and command dispatcher

All JavaScript files were obfuscated using array-rotation string encoding (the a0_0x... pattern), hiding all meaningful strings including C2 URLs, registry commands, and API routes behind decoded lookups at runtime.

Initial execution was launched via:

conhost.exe --headless C:\...\<kb-article>\<runtime>.exe C:\...\<kb-article>\<launcher>.js

Using conhost.exe --headless suppresses the console window and obscures the Bun process from casual inspection. Within seconds, <launcher>.js spawned all three child components.

The Windows Update Lure

Before hiding the console, <launcher>.js prints a convincing progress bar to the terminal with the message:

      Processing KB-XXXXXXX update, please wait...

The bar animates to 100% over a randomized 3-10 second window using kernel32.dll and user32.dll calls via Bun's Foreign Function Interface (FFI) to invoke GetConsoleWindow() and ShowWindow(hwnd, SW_HIDE). By the time the bar completes, the window is gone and all four components are running silently. The KB number is consistent across the download URL, the archive name, the extraction path, and the on-screen UI, a level of detail that would make the lure convincing to most users.

Malware Architecture: Four Components, One C2

The malware splits its functionality across four loosely coupled services communicating over localhost.

The C2 Relay: <relay>.js

This is the most complex component. It connects outbound to attacker infrastructure over WebSocket, serves a local WebSocket server on 127.0.0.1:39045 that the TCP proxy connects to, and dispatches incoming operator commands to the other two local agents. On first connection it sends an encoded registration beacon containing the host's domain, username, computername, and a randomly generated implant ID, then automatically runs whoami, ipconfig /all, route print, and tasklist.

Primary C2 endpoints use randomly generated subdomains across two CDN providers, following the patterns <redacted>[.]z03[.]azurefd[.]net/api/connect (Azure Front Door) and <redacted>[.]cloudfront[.]net/api/connect (CloudFront).

If both fail after repeated attempts, the relay falls back to a domain generation algorithm: it derives a daily-rotating S3 bucket name using HMAC-SHA256, fetches an object (info.dat) containing an AES-128-CTR encrypted C2 URL, and verifies it against an embedded Ed25519 public key before use. This provides a cryptographically authenticated fallback channel that cannot be sinkhholed without the private key.

All messages are double-encoded as base64-wrapped JSON. Command fields are disguised using e-commerce vocabulary (payment_status, subscription_id, webpush, math) to blend into application-layer inspection.

The Command Execution Engine: <agent>.js

This runs on 127.0.0.1:39315. It accepts POST /exec with a command string, executes it via cmd.exe /c, and returns stdout and stderr. Also exposes /fs for full filesystem operations (read, write, move, delete, enumerate directories, enumerate drives) and /osver to query Windows version from the registry.

The TCP Proxy: <proxy>.js

This runs on 127.0.0.1:39540. It exposes /connect, /send, and /closesocket, allowing the operator to open arbitrary TCP connections from the victim machine to any host and port, relay binary data through them, and close them on demand. Data received from open sockets is forwarded back to the C2 relay over the local WebSocket. This turns the implant into a SOCKS-like TCP tunnel, enabling network traversal through the victim host.

The Orchestrator: <launcher>.js

This manages the lure UI, hides the console, and spawns the three components. Beyond startup, it has no runtime role.

Post-Compromise Activity

Network and process telemetry confirmed that within approximately four minutes of execution, the Bun process established connections to the internal network on port 53 (DNS), port 636 (LDAPS), and port 389 (LDAP), targeting the organization's Active Directory infrastructure. This is consistent with initial host and network reconnaissance and suggests the operator was preparing for lateral movement.

The first-run recon command observed in the C2 source:

cmd.exe /c "set && ipconfig /all && route print && tasklist"

This returns environment variables, network adapter configuration, routing tables, and process list in a single execution.

Persistence

The C2 relay includes a remotely triggered persistence installer that writes to the Windows Run key:

  • Key: HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  • Value name: A randomly generated alphanumeric string hardcoded in this build
  • Data: conhost.exe --headless <runtime_path> --allow-run <workdir>\<launcher>.js

The Run key uses conhost.exe --headless as the wrapper, maintaining the same process-hiding behavior on every subsequent login. A corresponding uninstall command removes the key on operator instruction.

Evasion Characteristics

  • Bundled runtime: <runtime>.exe is a complete self-contained Bun binary, requiring no system installation. It leaves no installer record and avoids detections targeting known scripting runtimes.
  • CDN-fronted C2: Both primary endpoints are dynamically assigned CDN subdomains across Azure Front Door and CloudFront. Domain-reputation-based blocking is ineffective without TLS inspection.
  • DGA fallback: S3-hosted encrypted payload with Ed25519 signature verification gives the operator a resilient, authenticated fallback that survives infrastructure takedown.
  • Loopback-only services: The command execution and TCP proxy agents bind exclusively to 127.0.0.1. No malicious ports are externally exposed.
  • String obfuscation: Array-rotation encoding hides all meaningful strings until runtime. Static string-based detection will not match the raw files without deobfuscation.
  • conhost --headless wrapper: Suppresses console visibility and adds a legitimate Windows process to the parent chain.

Evolving Tradecraft: From DinDoor to This Campaign

When Daylight published our analysis of the DinDoor Deno RAT earlier this year, the defining characteristics were a bundled Deno runtime, Microsoft Teams-based IT impersonation as the delivery vector, a single CloudFront-fronted WebSocket C2, and a Run key persistence mechanism using conhost.exe --headless. The campaign documented here shares the same conceptual blueprint but shows clear signs of continued development across several dimensions.

The runtime has changed from Deno to Bun. Both are modern JavaScript runtimes that ship as self-contained binaries and carry minimal detection coverage, but Bun is newer and less commonly encountered in enterprise environments. The practical effect for defenders is the same: a legitimate-looking binary with an arbitrary filename, no installer record, and no PE injection.

The lure is more polished. DinDoor delivered a file named generically as a patch. This campaign threads a fake KB article number through the entire attack chain: the S3 download URL, the archive filename, the extraction path, the process tree, and an animated on-screen progress bar that impersonates a Windows Update in progress. That level of narrative consistency across the full chain suggests deliberate investment in making the lure hold up under casual scrutiny.

The C2 infrastructure is more resilient. DinDoor used a single CloudFront subdomain. This campaign adds Azure Front Door as a second CDN-fronted endpoint, and backs both with a fully implemented domain generation algorithm using HMAC-SHA256 bucket derivation, AES-128-CTR encryption, and Ed25519 signature verification against an embedded public key. The hardcoded endpoints being blocked do not take down the C2 channel. Sinkhholing the DGA requires the private HMAC seed, which is not recoverable from the binary.

Taken together these changes reflect an operator actively maintaining and hardening a toolset rather than reusing a static implant. The core architecture, loopback HTTP services, WebSocket relay, CDN fronting, and Run key persistence, has stayed consistent while the runtime, lure, and infrastructure resilience have all improved. Organizations that built detections specifically for Deno following the DinDoor campaign should validate those rules cover Bun and other bundled JavaScript runtimes as well.

Detection Guidance

Endpoint

  • Execution of conhost.exe with --headless argument as a parent to a Bun process
  • A Bun runtime binary spawning cmd.exe as a child process
  • tar.exe extraction into %AppData%\Roaming\ followed immediately by execution of the extracted binary
  • Registry writes to HKCU\Software\Microsoft\Windows\CurrentVersion\Run with a short randomly generated alphanumeric value name
  • Local HTTP servers on ports 39315, 39045, or 39540 spawned by a JavaScript runtime process
  • cmd.exe /c "set && ipconfig /all && route print && tasklist" as a child of a runtime process

Network

  • Outbound WebSocket connections (port 443) to *.azurefd.net or *.cloudfront.net from non-browser processes
  • Outbound LDAP or LDAPS connections from a user workstation shortly after an unknown binary executes
  • DNS queries for *.s3.<region>.amazonaws.com from a Bun process (DGA fallback activity)

Indicators of Compromise

Specific filenames and C2 subdomain strings have been redacted to prevent linkage to the affected organization. Patterns are provided in their place.

Network

Type Value
C2 WebSocket wss://<redacted>[.]z03[.]azurefd[.]net/api/connect
C2 WebSocket wss://<redacted>[.]cloudfront[.]net/api/connect
Download URL hxxps://<org>-it[.]s3[.]us-east-1[.]amazonaws[.]com/download1/<kb-article>.p
C2 path /api/connect (consistent across both CDN endpoints)

Host

Type Value
Dropper filename <kb-article>.p — archive named to match a fake KB article number
Install path %AppData%\Roaming\<kb-article>\
Runtime filename Randomly named .exe containing the KB article number pattern (Bun v1.4.0.0)
JS component filenames Four randomly named .js files dropped alongside the runtime
Registry key HKCU\Software\Microsoft\Windows\CurrentVersion\Run
Registry value name Short randomly generated alphanumeric string, hardcoded per build
Persistence command conhost.exe --headless <runtime_path> --allow-run <workdir>\<launcher>.js
Local listeners 127.0.0.1:39045 / 127.0.0.1:39315 / 127.0.0.1:39540
First-run recon cmd.exe /c "set && ipconfig /all && route print && tasklist"
Fake lure string Processing KB-XXXXXXX update, please wait...

Recommendations

  • Implement detections based on endpoint and network activity: Review the detection guidance above and prioritize implementing rules covering conhost.exe --headless execution chains and Bun runtimes operating outside standard directories.
  • Set EDR policies to prevent, not detect: In this intrusion, the EDR in place was configured to detect-only for this activity. The malware ran unimpeded before containment began. Prevention policies covering script runtime execution chains should be in blocking mode.
  • Train users to verify IT contact out-of-band: Any unsolicited instruction to download and run software should be verified through a known internal channel before any action is taken, regardless of how credible the request appears.
  • Monitor WSS connections from non-browser processes: Outbound WebSocket Secure connections on port 443 originating from script runtime processes rather than a browser are anomalous and should be investigated. This malware's C2 channel is indistinguishable from legitimate CDN traffic at the domain level, making process context the most reliable signal.

Broader Implications

Attackers are deliberately choosing modern JavaScript runtimes (Bun, Deno, Node) as malware hosts because security tooling has not yet built robust detection coverage for them. A self-contained runtime binary with an arbitrary filename leaves no installer record, no registry footprint from installation, and produces no shellcode or PE injection. Behavioral detections based on process ancestry and loopback socket activity are more durable than file-based signatures for this class of threat.

The social engineering here was also effective because the Windows Update lure is visually convincing. The progress bar runs for only a few seconds before the console is hidden, giving a user no obvious moment to pause and question what they just executed.

Table of contents
form submission image form submission image

Ready to escape the dark and elevate your security?

Get a demo
form submission image form submission image

Ready to escape the dark and elevate your security?

Get a demo

Ready to escape the dark and elevate your security?

Stop settling for escalation factories. Get AI-native detection and response with senior experts and full accountability.

Book a Demo
moutain illustration
form submission image form submission image

Ready to escape the dark and elevate your security?

Get a demo
moutain illustration