typeanalysisfamilyletsdiskusscomconfidencehighloaderscriptnodejsobfuscationevasionpersistence
SHA-256: 71e6cb9e217945f0ae0b071e6b30417a7f28476fe79ca7b235d11609a8172a43

letsdiskusscom: 71e6cb9e — Twenty-seventh confirmed sibling (Update_8.js), numbered-suffix poem steganography, twenty-seventh distinct msvcp140.dll morph

Executive Summary

Twenty-seventh confirmed sibling in the letsdiskusscom Node.js poem-word-list dropper cluster. Filename Update_8.js fills the build-counter gap between Update_5.js and Update_9.js. Uses numbered-suffix poem steganography (gentle1, hush2, etc.) with the canonical 256-word vocabulary. Drops the same signed RevoSrp.exe + vcruntime DLLs + BAT persistence as all 26 prior siblings, but carries a twenty-seventh distinct msvcp140.dll morph (879,616 bytes, MSVC 14.27.29016.0). Static-only analysis (CAPE skipped — JS source not a supported binary class).

What It Is

  • File: Update_8.js, 7.5 MB (7,493,234 bytes), JavaScript source with CRLF line terminators ^[file.txt]
  • Family: letsdiskusscom — confirmed 27th sibling by payload hash matching and builder template fidelity ^[entities/letsdiskusscom.md]
  • Staging directory: %ProgramData%\Microsoft Edge Updates Helper 6loccZYQrhUC\ ^[strings.txt:5]
  • Obfuscation: Numbered-suffix poem-word-list steganography (256-word vocabulary, words 93+ suffixed with index) ^[strings.txt:6]

How It Works

The carrier is a Node.js script that decodes five embedded payloads from a 256-word English poem via writePositionsToFile(listA, listB, outPath). The lookup table is the same poem used in all 26 prior siblings, with numbered suffixes appended to repeated words starting after the first complete cycle (index 92 = abide92). ^[strings.txt:6] ^[strings.txt:18-26]

Decoded payloads (verified by SHA-256):

File SHA-256 Size Notes
Microsoft Edge Updates Helper.exe 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f 52,400 B Signed RevoSrp.exe, invariant across all 27 siblings
msvcp140.dll 0d9818e4dfc4d93fbd59fda5ba1a8e58d7f4a714c4630572012ece43418ab91d 879,616 B 27th distinct morph, MSVC 14.27.29016.0, compiled 2020-06-16
vcruntime140.dll ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 101,672 B Invariant across all 27 siblings
vcruntime140_1.dll 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 44,328 B Invariant across all 27 siblings
6loccZYQrhUC.bat dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919 440 B Invariant HKCU Run persistence BAT

The script writes all five files to the staging directory, then launches the BAT (which adds the EXE to HKCU\Software\Microsoft\Windows\CurrentVersion\Run) and the EXE directly. ^[strings.txt:33-41]

Decompiled Behavior

Not applicable — source is unobfuscated JavaScript. No Ghidra/radare2 decompilation required. The full logic is visible in strings.txt (the file is the source). ^[strings.txt]

C2 Infrastructure

None. The dropper is self-contained — all payloads are embedded in the JS source. No network IOCs, no download URLs, no hardcoded C2. ^[strings.txt]

Interesting Tidbits

  • Build-counter gap fill: Update_8.js sits between Update_5.js (b53d6a32) and Update_9.js (5ebd96a1), confirming a large batch of builds from the numbered-suffix template. ^[entities/letsdiskusscom.md]
  • Twenty-seventh distinct msvcp140.dll: The builder rotates this DLL on every build while keeping the other three PE payloads constant. This suggests the msvcp140.dll is sourced from a collection of legitimate MSVC redistributables rather than being custom-built.
  • Staging directory suffix 6loccZYQrhUC: Randomized per build, 12-character mixed-case alphanumeric. No dictionary words. Likely PRNG-generated.
  • BAT is assigned to dll4Path: A minor code quirk — the BAT path is stored in dll4Path despite not being a DLL. The JS defines const dll4Path = path.join(folder, "6loccZYQrhUC.bat") but never uses it; the BAT is written via autorunPath instead. ^[strings.txt:17]

How To Mess With It (Homelab Replication)

  1. Toolchain: Node.js v18+ on Windows or Linux
  2. Encode a payload:
    with open('words.txt') as f:
        words = f.read().split()
    assert len(words) == 256
    with open('payload.exe', 'rb') as f:
        data = f.read()
    encoded = ' '.join(words[b] for b in data)
    
  3. Carrier: Wrap in a Node.js script using the writePositionsToFile pattern from strings.txt.
  4. Verify: Decode back to the original file and compare SHA-256.
  5. What you'll learn: How natural-language steganography defeats static string analysis — the carrier looks like poetry but hides executable payloads.

Deployable Signatures

YARA

rule letsdiskusscom_poem_stego_js {
    meta:
        description = "Detects letsdiskusscom Node.js poem-word-list steganography dropper"
        author = "PacketPursuit"
        reference = "/intel/analyses/71e6cb9e217945f0ae0b071e6b30417a7f28476fe79ca7b235d11609a8172a43.html"
        date = "2026-08-24"
    strings:
        $func1 = "writePositionsToFile" ascii wide
        $func2 = "safeMakeDir" ascii wide
        $func3 = "launchExecutable" ascii wide
        $app = "Microsoft Edge Updates Helper" ascii wide
        $req_fs = "require('fs')" ascii wide
        $req_path = "require('path')" ascii wide
        $req_spawn = "require('child_process')" ascii wide
        $wlist = "const wlist =" ascii wide
        $exe = "const exe =" ascii wide
        $dll1 = "const dll1 =" ascii wide
        $bat = "const bat =" ascii wide
        $poem = "gentle hush that wraps the midnight air" ascii wide
        $spawn_shell = "shell: true" ascii wide
    condition:
        filesize > 1MB and
        all of ($func1, $func2, $func3) and
        $app and
        2 of ($req_*) and
        $wlist and
        any of ($exe, $dll1, $bat) and
        $poem
}

Sigma

title: Letsdiskusscom Node.js Dropper Execution
status: experimental
description: Detects Node.js executing a payload from a Microsoft Edge Updates Helper staging directory
logsource:
    category: process_creation
    product: windows
detection:
    selection_parent:
        ParentImage|endswith: '\node.exe'
    selection_child:
        Image|contains: 'ProgramData\Microsoft Edge Updates Helper'
    condition: selection_parent and selection_child
falsepositives:
    - Unknown
level: high

IOC List

Indicator Type Value Context
JS filename Filename Update_8.js Build-counter naming pattern
Staging directory Path %ProgramData%\Microsoft Edge Updates Helper 6loccZYQrhUC\ Masquerade directory
EXE payload SHA-256 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f Signed RevoSrp.exe, invariant
DLL1 payload SHA-256 0d9818e4dfc4d93fbd59fda5ba1a8e58d7f4a714c4630572012ece43418ab91d msvcp140.dll, 27th distinct morph
DLL2 payload SHA-256 ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 vcruntime140.dll, invariant
DLL3 payload SHA-256 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 vcruntime140_1.dll, invariant
BAT payload SHA-256 dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919 HKCU Run persistence, invariant
Registry key Registry HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Microsoft Edge Updates Helper Persistence

Behavioral Fingerprint

A Node.js script (typically named Update_N.js) defines a 256-word English poem vocabulary and five large space-separated strings encoded as word indices. It calls writePositionsToFile to decode each string to a binary file in %ProgramData%\Microsoft Edge Updates Helper <random12>\, then uses child_process.spawn with shell: true to execute a BAT file (which adds the EXE to HKCU\Run) and the EXE itself. The EXE is always the same signed RevoSrp.exe; the msvcp140.dll rotates per build.

Detection Signatures

capa ATT&CK Note
N/A T1059.007 JavaScript execution via Node.js
N/A T1027.002 Obfuscated Files or Info — poem-word-list steganography
N/A T1036.005 Masquerading — Microsoft Edge Updates Helper directory name
N/A T1547.001 Registry Run Keys — BAT-based persistence
N/A T1543.003 Create/modify system process — child_process.spawn

References

Provenance

Analysis derived from:

  • file.txt — file type identification
  • strings.txt — full JavaScript source (the file is unobfuscated source code)
  • triage.json — triage metadata
  • exiftool.json — file metadata
  • Decoded payloads verified via Node.js runtime SHA-256 computation