typeanalysisfamilyletsdiskusscomconfidencehighcreated2026-08-23updated2026-08-23malware-familyloaderscriptnodejsobfuscationevasionpersistencepoem-word-list-steganographynatural-language-payload-encodingregistry-run-persistence
SHA-256: 2274d74fcc2ad81b9c41c4ca578be6f252a34aaa858020bdaa07eb34e2cd196b

letsdiskusscom: 2274d74f — Ninth confirmed sibling, ninth distinct msvcp140.dll morph (MSVC 14.27, Jun 2020), plain 256-word poem steganography

Executive Summary

A 9.3 MB Node.js dropper (Update_11.js) that belongs to the letsdiskusscom cluster. It uses the same 256-word English poem lookup-table steganography seen in siblings d0ca14b3 through ddcb25ee to encode five payloads (one signed Revo EXE, three VC++ runtime DLLs, and one BAT persistence script) by word-to-byte index mapping. This sample carries a ninth distinct msvcp140.dll variant (MSVC 14.27.29016.0, compiled 2020-06-16), confirming the builder operator re-bundles a fresh VC++ runtime with every build rather than reusing a fixed set. The BAT file adds HKCU\Software\Microsoft\Windows\CurrentVersion\Run persistence before launching the staged EXE. No C2; fully self-contained. ^[file.txt] ^[strings.txt:1-45]

What It Is

Field Value
SHA-256 2274d74fcc2ad81b9c41c4ca578be6f252a34aaa858020bdaa07eb34e2cd196b
Filename (ingestion) Update_11.js
File type JavaScript source, ASCII text, 60 lines, 63,365-char lines, CRLF ^[file.txt]
Size 9,283,780 bytes (9.3 MB) ^[exiftool.json]
Family letsdiskusscom (high confidence, ninth confirmed sibling)
Build Node.js JavaScript, raw .js delivery
Obfuscation None at JS level; payload concealment via 256-word English poem lookup-table steganography
CAPE status skipped — JavaScript source is not a supported binary class ^[dynamic-analysis.md]

How It Works

  1. Poem-word-list steganography. A 256-word English poem is defined as wlist. Five payload strings (exe, dll1, dll2, dll3, bat) are each encoded as sequences of poem words. At runtime, writePositionsToFile() maps each word back to its index in wlist, masks to & 0xFF, and writes the resulting byte stream to disk. ^[strings.txt:6-45]

  2. Staging directory. folder = path.join(process.env.PROGRAMDATA, "Microsoft Edge Updates Helper GQYJq5Av3lIJ"). The random suffix GQYJq5Av3lIJ varies per sample (e.g., hvdyNBO34tkN, xp7v5lqfYx3t in prior siblings). ^[strings.txt:5]

  3. Payloads dropped. Five files written:

    • Microsoft Edge Updates Helper.exe — signed RevoSrp.exe (DigiCert, VS REVO GROUP OOD)
    • msvcp140.dll — MSVC 14.27.29016.0, 2020-06-16 timestamp (ninth distinct morph)
    • vcruntime140.dll — identical to all prior siblings
    • vcruntime140_1.dll — identical to all prior siblings
    • GQYJq5Av3lIJ.bat — registry persistence + launcher ^[strings.txt:12-17]
  4. Persistence. The BAT script calls reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "Microsoft Edge Updates Helper" /t REG_SZ /d "\"%~1\"" /f before launching the EXE. ^[strings.txt:40-45]

  5. Execution. The Node.js script spawns the BAT via child_process.spawn(..., { shell: true, stdio: 'inherit' }), which in turn launches the EXE. ^[strings.txt:29-41]

Decompiled Behavior

Not applicable — source is plaintext JavaScript, not a compiled PE. The full logic is visible in strings.txt. No javascript-obfuscator IIFE or control-flow flattening is present; the obfuscation layer is entirely the poem-word-list payload encoding.

C2 Infrastructure

None. The sample is fully self-contained with no network IAT, no hardcoded URLs, and no callback. The malicious act is silent local payload staging + execution + registry persistence.

Interesting Tidbits

  • Ninth distinct msvcp140.dll morph: SHA-256 5bce8c8b7a80030599367853da4c82f85dd59f11634ea249e467d033638609d0, compiled 2020-06-16, MSVC 14.27.29016.0. Prior siblings carried eight other distinct hashes. This confirms the builder re-packages a new VC++ runtime with every build rather than reusing a cached set.
  • Plain poem, no numbered suffixes: Unlike sibling 3465e6ee which introduced gentle1, hush2, etc., this sample reverts to the plain 256-word vocabulary. The builder oscillates between plain and numbered-suffix templates.
  • RevoSrp.exe payload: The staged EXE is a signed Revo Registry Cleaner component (RevoSrp.exe, VS REVO GROUP OOD, DigiCert). Its presence is not inherently malicious — the threat is the deceptive delivery mechanism.
  • DLL name masquerade: The three dropped DLLs are legitimate Microsoft VC++ runtime DLLs, lending credibility to the staging directory.
  • No detached: true: The spawn call uses shell: true, stdio: 'inherit' but not detached, meaning the Node.js parent will block until the child exits (or at least inherit stdio).

How To Mess With It (Homelab Replication)

Goal: Reproduce the poem-word-list steganography dropper in Node.js.

Toolchain: Node.js 18+ (LTS), any text editor.

Steps:

  1. Choose a 256-word English vocabulary (a poem, prose passage, or random word list). Map each word to index 0..255.
  2. Encode a binary payload by replacing every byte with its corresponding word. For byte 0x00, use word at index 0; for 0xFF, use word at index 255.
  3. In Node.js, read the word list and payload word string. Split both on spaces. For each payload word, find its index in the vocabulary list, mask to & 0xFF, and write to a Buffer.
  4. Write the buffer to %ProgramData%\Microsoft Edge Updates Helper <random_suffix>\<filename>.
  5. Optionally wrap in a BAT file that adds a HKCU\Run registry entry before executing the payload.

Verification: Compare your output byte stream to the original payload via sha256sum. The decoded bytes should match bit-for-bit.

What you'll learn: How natural-language steganography defeats naive string-extraction tools (the payload is invisible to strings until decoded) and why YARA rules targeting the poem vocabulary are effective detection.

Deployable Signatures

YARA Rule

rule letsdiskusscom_poem_stego_dropper
{
    meta:
        description = "Node.js dropper using 256-word English poem lookup-table steganography"
        author = "PacketPursuit"
        family = "letsdiskusscom"
        reference = "/intel/analyses/2274d74fcc2ad81b9c41c4ca578be6f252a34aaa858020bdaa07eb34e2cd196b.html"
    strings:
        $wlist_start = "const wlist = \"gentle hush that wraps the midnight air"
        $wlist_end = "unwearied humble code"
        $func_write = "function writePositionsToFile(listA, listB, outPath)"
        $spawn_shell = "spawn(execPath, args, { shell: true"
        $progdata = "Microsoft Edge Updates Helper"
        $reg_add = "reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\""
    condition:
        filesize > 5MB and
        $wlist_start and
        $wlist_end and
        $func_write and
        $progdata and
        any of ($spawn_shell, $reg_add)
}

Sigma Rule

title: Letsdiskusscom Node.js Dropper Execution
status: experimental
description: Detects Node.js spawning a batch file from a Microsoft Edge Updates Helper directory under ProgramData, indicative of letsdiskusscom poem-stego dropper execution.
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    ParentImage|endswith: '\node.exe'
    CommandLine|contains:
      - 'Microsoft Edge Updates Helper'
      - 'ProgramData'
      - '.bat'
  condition: selection
falsepositives:
  - Unlikely — the directory name is attacker-controlled and non-standard.
level: high
tags:
  - attack.execution
  - attack.t1059.007
  - attack.persistence
  - attack.t1547.001

IOC List

Indicator Type Value
Carrier SHA-256 hash 2274d74fcc2ad81b9c41c4ca578be6f252a34aaa858020bdaa07eb34e2cd196b
Staged EXE SHA-256 hash 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f (RevoSrp.exe)
Staged DLL1 SHA-256 hash 5bce8c8b7a80030599367853da4c82f85dd59f11634ea249e467d033638609d0 (msvcp140.dll, MSVC 14.27)
Staged DLL2 SHA-256 hash ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 (vcruntime140.dll)
Staged DLL3 SHA-256 hash 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 (vcruntime140_1.dll)
Staging directory path %ProgramData%\Microsoft Edge Updates Helper*
Registry persistence registry HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Microsoft Edge Updates Helper
Process tree behavior node.exe → cmd.exe /c *.bat → RevoSrp.exe
Poem vocabulary string 256-word English poem beginning with gentle hush that wraps the midnight air...

Behavioral Fingerprint Statement

This JavaScript dropper writes five files to a %ProgramData% subdirectory named Microsoft Edge Updates Helper <random_suffix>: a signed Revo EXE, three VC++ runtime DLLs (msvcp140.dll, vcruntime140.dll, vcruntime140_1.dll), and a BAT file that adds an HKCU\Run registry entry before executing the EXE. The payload bytes are encoded inside the JS source as sequences of words from a 256-word English poem, decoded at runtime by word-to-index mapping. The Node.js parent spawns the BAT via child_process.spawn with shell: true. No network C2 is present. Detection should focus on the anomalous node.exe → .bat → .exe chain under %ProgramData% and the distinctive poem vocabulary strings in the JS source.

Detection Signatures

ATT&CK Technique Evidence
T1059.007 JavaScript Node.js require('fs'), require('child_process') ^[strings.txt:1-3]
T1027.002 Obfuscated Files or Info 256-word poem lookup-table steganography hides PE payloads as natural-language word sequences ^[strings.txt:6-11]
T1036.005 Masquerading Microsoft Edge Updates Helper directory name and signed Revo EXE masquerade ^[strings.txt:4-5]
T1547.001 Registry Run Keys BAT calls reg add HKCU\...\Run with value Microsoft Edge Updates Helper ^[strings.txt:40-45]
T1543.003 Create/modify system process child_process.spawn(..., { shell: true, stdio: 'inherit' }) ^[strings.txt:29-41]

References

  • letsdiskusscom — Cluster entity page (eight prior siblings documented) ^[entities/letsdiskusscom.md]
  • poem-word-list-steganography — Technique page for the 256-word poem encoding ^[techniques/poem-word-list-steganography.md]
  • natural-language-payload-encoding — Concept page for prose-based payload hiding ^[concepts/natural-language-payload-encoding.md]
  • registry-run-persistence — Procedure page for BAT-based Run key technique ^[procedures/registry-run-persistence.md]
  • Sibling d0ca14b3 — First poem-stego variant with BAT persistence
  • Sibling ddcb25ee — Eighth sibling, plain poem, MSVC 14.40 msvcp140.dll

Provenance

  • file.txt — file(1) output, file v5.45
  • exiftool.json — ExifTool 12.76 metadata
  • strings.txt — strings(1) output, GNU strings 2.42
  • dynamic-analysis.md — CAPE sandbox status (skipped)
  • ssdeep.txt — ssdeep 2.14.1
  • tlsh.txt — TLSH 4.12.0
  • Payload SHA-256s computed via Python 3.11 hashlib after custom poem-word-list decoder reimplementation