typeanalysisfamilyletsdiskusscomconfidencehighcreated2026-08-21updated2026-08-21scriptnodejsloaderobfuscationevasionpersistencemalware-family
SHA-256: 3465e6eea1a937b941ef77ac819591c3578e14da950de0d78e8b2d467b819357

letsdiskusscom: 3465e6ee — Numbered-suffix poem steganography with new msvcp140.dll morph

Executive Summary

Sixth confirmed sibling of the letsdiskusscom Node.js dropper cluster. Uses the same 256-word English poem lookup-table steganography as siblings d0ca14b3/247b54b5/af4313e4/c075aeba, but introduces numbered suffixes on repeated vocabulary (e.g. gentle1, hush2) to defeat naive word-list deduplication. Drops the same signed RevoSrp.exe and two vcruntime DLLs as all prior siblings, but carries a sixth distinct msvcp140.dll morph (5975596f...). Self-contained local installer with BAT-based HKCU Run persistence.

What It Is

Field Value
SHA-256 3465e6eea1a937b941ef77ac819591c3578e14da950de0d78e8b2d467b819357
Filename Update_20.js
Size 7.9 MB (7,883,546 bytes)
Type JavaScript source, ASCII text, CRLF line terminators ^[file.txt]
Language Node.js (requires fs, path, child_process)

No PE header. Not a supported binary class for CAPE; dynamic analysis skipped. ^[dynamic-analysis.md]

How It Works

  1. Obfuscation: A 256-word poem serves as a byte lookup table (wlist). Four PE files plus a BAT script are encoded as sequences of poem-word indices. ^[strings.txt:6]
  2. Decoding: writePositionsToFile splits the word list, looks up each payload word's index, and writes index & 0xFF to disk via Buffer.from. ^[strings.txt:18-25]
  3. Staging: Creates %ProgramData%\Microsoft Edge Updates Helper w3lo1kUOohHh\ and drops:
    • Microsoft Edge Updates Helper.exe — RevoSrp.exe (52,400 bytes, signed) ^[strings.txt:12]
    • msvcp140.dll — VC++ runtime (932,864 bytes, new morph) ^[strings.txt:14]
    • vcruntime140.dll — same as prior siblings (101,672 bytes) ^[strings.txt:15]
    • vcruntime140_1.dll — same as prior siblings (44,328 bytes) ^[strings.txt:16]
    • w3lo1kUOohHh.bat — persistence + launcher (440 bytes) ^[strings.txt:13]
  4. Execution: Calls launchExecutable twice — first the BAT (which writes HKCU Run and launches the EXE), then the EXE directly. ^[strings.txt:40-41]

Decompiled Behavior

No native code to decompile. The JavaScript is delivered in near-plaintext; obfuscation is lexical rather than algorithmic. The payload reconstruction logic (decoded from strings.txt lines 18-25) is:

function writePositionsToFile(listA, listB, outPath) {
  const a = listA.split(' ');
  const b = listB.split(' ');
  const positions = b.map(word => {
    const idx = a.indexOf(word);
    return idx >= 0 ? idx : 0;
  });
  const buffer = Buffer.from(positions.map(p => p & 0xFF));
  fs.writeFileSync(outPath, buffer);
}

This is the same decoder pattern observed in all poem-lookup siblings.

C2 Infrastructure

None in the carrier. The Node.js script is entirely self-contained; no network APIs are imported. The signed RevoSrp.exe payload may contain its own update-check logic, but no C2 was recovered from the carrier or the decoded PE statically.

Interesting Tidbits

  • Numbered suffix builder variant: The poem repeats after ~92 words; from index 92 onward each word gains a numeric suffix (gentle1, hush2, that3 ... fail164). This is a builder-level change intended to poison word-frequency analysis and prevent analysts from quickly deduplicating the vocabulary. First observed in this sibling. ^[strings.txt:6]
  • Sixth msvcp140.dll morph: The msvcp140.dll SHA-256 (5975596f...) does not match any of the five prior siblings. The EXE and both vcruntime DLLs remain identical across all six siblings, suggesting the builder randomizes or cycles the VC++ runtime redistributable. ^[strings.txt:14]
  • dll4Path bug: Line 17 assigns dll4Path to the BAT filename (w3lo1kUOohHh.bat), but the variable is never consumed. The BAT is written using autorunPath. Dead code from builder template drift. ^[strings.txt:17]
  • RevoSrp.exe: Decoded EXE is Revo Registry Cleaner\x64\Release\RevoSrp.pdb, signed by VS REVO GROUP OOD via DigiCert. Legitimate software abused as payload carrier.

How To Mess With It (Homelab Replication)

  1. Poem table: Write a 256-word prose fragment. Optionally append numeric suffixes to repeated words.
  2. Encode: For each byte of payload, emit the corresponding word.
  3. Carrier: Wrap in Node.js with the writePositionsToFile pattern.
  4. Verify: Decode back to original bytes; compare SHA-256.

Learn: how lexical steganography evades string-based detection and why word-list deduplication must strip suffixes first.

Deployable Signatures

YARA

rule letsdiskusscom_poem_dropper {
    meta:
        description = "Node.js dropper using 256-word poem lookup-table steganography"
        author = "PacketPursuit"
        date = "2026-08-21"
        sha256 = "3465e6eea1a937b941ef77ac819591c3578e14da950de0d78e8b2d467b819357"
    strings:
        $node_fs = "const fs = require('fs');"
        $node_path = "const path = require('path');"
        $node_spawn = "const { spawn } = require('child_process');"
        $app_name = "Microsoft Edge Updates Helper"
        $wlist = "const wlist = \""
        $func = "function writePositionsToFile(listA, listB, outPath)"
        $safe = "function safeMakeDir(dir)"
        $launch = "function launchExecutable(execPath, args = [])"
    condition:
        filesize > 1MB and
        all of ($node_*) and
        $app_name and
        $wlist and
        $func and
        $safe and
        $launch
}

Sigma

title: Letsdiskusscom Node.js Poem Dropper Execution
logsource:
    category: process_creation
    product: windows
detection:
    selection_js:
        CommandLine|contains:
            - 'node.exe'
            - 'Update_20.js'
    selection_child:
        ParentImage|endswith: '\\node.exe'
        Image|endswith:
            - '\\Microsoft Edge Updates Helper.exe'
            - '\\w3lo1kUOohHh.bat'
    selection_dir:
        CommandLine|contains: 'Microsoft Edge Updates Helper w3lo1kUOohHh'
    condition: selection_js or selection_child or selection_dir
falsepositives:
    - Unknown
level: high

IOCs

Indicator Value Type
Carrier SHA-256 3465e6eea1a937b941ef77ac819591c3578e14da950de0d78e8b2d467b819357 hash
Decoded EXE SHA-256 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f hash
Decoded DLL1 (msvcp140) SHA-256 5975596f81f4600baeb70a6eeb308d5465e83d42e9e96df7e45b411fc0d2a61d hash
Decoded DLL2 (vcruntime140) SHA-256 ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 hash
Decoded DLL3 (vcruntime140_1) SHA-256 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 hash
Decoded BAT SHA-256 dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919 hash
Staging directory %ProgramData%\Microsoft Edge Updates Helper w3lo1kUOohHh\ path
Registry Run value Microsoft Edge Updates Helper regkey
Revo EXE PDB path D:\Work_REVO\VSRevo\Windows\Projects\Registry Cleaner\revo-registry-cleaner\Revo Registry Cleaner\x64\Release\RevoSrp.pdb string
Signed by VS REVO GROUP OOD (DigiCert) cert

Behavioral Fingerprint

A Node.js process reads a multi-megabyte JavaScript file containing two very long space-separated word strings. It creates a Microsoft Edge Updates Helper-named directory under %ProgramData%, writes five files (EXE + three DLLs + BAT), spawns a batch script that writes HKCU\Software\Microsoft\Windows\CurrentVersion\Run, then spawns the EXE. No network connections from the carrier script.

Detection Signatures

  • capa: Not applicable — input is JavaScript source, not a supported executable format. ^[capa.txt]
  • floss: Not applicable. ^[floss.txt]

References

  • letsdiskusscom — entity page for the cluster
  • poem-word-list-steganography — technique page for the 256-word poem encoding
  • registry-run-persistence — procedure page for BAT-based HKCU Run persistence
  • natural-language-payload-encoding — broader concept
  • Sibling analysis: /intel/analyses/d0ca14b3ad12100898d69afacfecfbdb186fe1bd801f69aecf355413bf6e502b.html
  • Sibling analysis: /intel/analyses/247b54b524dcdd1a4dbe76ac11473ba26ea003193ad86216fe411f9b80e8c7fb.html

Provenance

  • file.txt, strings.txt, capa.txt, floss.txt, dynamic-analysis.md — generated by triage pipeline (file, strings, capa, floss)
  • Decoded PE payloads verified with file and pefile.py on host
  • SHA-256 computed with sha256sum
  • Poem and payload extraction performed via Python regex on 2026-08-21