typeanalysisfamilyletsdiskusscomconfidencehighcreated2026-08-23updated2026-08-23malware-familyloaderscriptnodejsobfuscationevasionpersistencemitre-attck
SHA-256: 7d47ca60c6ec500c39868a79cdd15d3af2c35221b52aff6a4976e58dca47748a

letsdiskusscom: 7d47ca60 — Update_18.js, eighteenth confirmed sibling

Executive Summary

Eighteenth confirmed sibling in the letsdiskusscom Node.js poem-word-list dropper cluster. The carrier script Update_18.js (7.7 MB) uses numbered-suffix poem steganography to decode five embedded payloads — a signed Revo EXE, three Microsoft VC++ runtime DLLs, and a BAT persistence launcher — to a fake Microsoft Edge Updates Helper directory under %ProgramData%. Same EXE, vcruntime140.dll, vcruntime140_1.dll, and BAT hash as all 17 prior poem-stego siblings. The msvcp140.dll is a new morph (SHA-256 23bf2a4543384cc3032e25136bb7f6be801eb9d483f545c543fde0936271829b, 904,192 bytes), bringing the cluster's distinct msvcp140 morph count to eighteen. Static-only analysis; CAPE skipped because the sample is plain JavaScript source.

What It Is

  • Filename: Update_18.js ^[metadata.json]
  • File type: JavaScript source, ASCII text, very long lines (63,365 chars), CRLF terminators ^[file.txt]
  • Size: 7,674,528 bytes (7.7 MB) ^[exiftool.json]
  • SHA-256: 7d47ca60c6ec500c39868a79cdd15d3af2c35221b52aff6a4976e58dca47748a
  • Family: letsdiskusscom (high confidence, cluster sibling #18)
  • OpenCTI labels: js, malware-bazaar ^[metadata.json]

How It Works

The script is a self-contained Node.js installer with no external network dependencies. It uses the same 256-word English poem lookup-table steganography observed across all poem-stego siblings, with numbered suffixes on repeated vocabulary words (gentle1, hush2, wraps3, etc.) to defeat simple word-frequency deduplication. ^[strings.txt:6]

Execution flow:

  1. Decode payloads via writePositionsToFile(wlist, <payload>, outPath) — each payload string is a sequence of poem words; the decoder maps each word to its zero-based index in wlist, producing a byte array. ^[strings.txt:18-25]
  2. Stage to disk at %ProgramData%\Microsoft Edge Updates Helper b7mqJjEYdRYn\:
    • Microsoft Edge Updates Helper.exe — signed Revo EXE (52,400 bytes, SHA-256 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f)
    • msvcp140.dll — MSVC runtime (904,192 bytes, SHA-256 23bf2a4543384cc3032e25136bb7f6be801eb9d483f545c543fde0936271829b)
    • vcruntime140.dll — MSVC runtime (101,672 bytes, SHA-256 ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833)
    • vcruntime140_1.dll — MSVC runtime (44,328 bytes, SHA-256 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7)
    • b7mqJjEYdRYn.bat — registry persistence launcher (440 bytes, SHA-256 dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919)
  3. Launch the BAT with the EXE path as argument, then launch the EXE directly. ^[strings.txt:39-41]

The BAT adds HKCU\Software\Microsoft\Windows\CurrentVersion\Run persistence under the value name Microsoft Edge Updates Helper, pointing to the staged EXE. ^[strings.txt:11]

A minor builder artifact is present: dll4Path is assigned to the same BAT path as autorunPath, suggesting copy-paste drift in the builder template. ^[strings.txt:17]

Decompiled Behavior

Not applicable — this is plain JavaScript source, not a compiled PE. No Ghidra or radare2 analysis required. The entire logic is readable from strings.txt (which is the source file itself, as file confirms it is ASCII text with no binary overlay). ^[file.txt]

C2 Infrastructure

None. The carrier is entirely self-contained. No network URLs, no download cradles, no hardcoded IPs or domains. The malicious act is the silent staging and execution of a signed third-party binary under a deceptive directory name. Any actual C2 would live inside the dropped EXE, which has not been independently detonated or reverse-engineered in this corpus.

Interesting Tidbits

  • Build counter continues: filename Update_18.js continues the Update_N.js pattern. The builder appears to maintain an internal counter. ^[metadata.json]
  • Eighteenth msvcp140 morph: prior siblings cycled through seventeen distinct msvcp140.dll builds. This sample adds an eighteenth (SHA-256 23bf2a4543384cc3032e25136bb7f6be801eb9d483f545c543fde0936271829b, 904,192 bytes). All are legitimate Microsoft VC++ runtime DLLs; the morph rotation likely serves as a trivial sandbox/AV evasion tactic (rotate file hashes to avoid hash-based detection on the DLL). ^[strings.txt:14]
  • Payload hash stability: EXE, DLL2, DLL3, and BAT hashes match all 17 prior poem-stego siblings exactly. The builder reuses the signed Revo EXE and two vcruntime DLLs across every build, only swapping msvcp140.dll. ^[strings.txt:12-17]
  • Staging suffix entropy: b7mqJjEYdRYn — 12-character alphanumeric random suffix, consistent with the cluster's per-build unique directory naming. ^[strings.txt:5]
  • Smaller file size: 7.7 MB vs 8.2–10.1 MB for recent siblings; reflects the smaller msvcp140.dll morph (904 KB vs 1.0–1.2 MB). The total file size scales directly with the embedded DLL size because the word-list encoding is 1 byte → 1 word. ^[exiftool.json]
  • BAT content unchanged: identical HKCU Run registry persistence script as all prior siblings. ^[strings.txt:11]

How To Mess With It (Homelab Replication)

  1. Encode any binary as a poem-word sequence:
    • Build a 256-word vocabulary list (English poem prose works well).
    • For each byte b of your payload, emit vocab[b].
    • Number repeated words (word1, word2) to bloat file size and evade frequency analysis.
  2. Wrap in Node.js using the writePositionsToFile pattern from this sample.
  3. Stage and execute via fs.writeFileSync + child_process.spawn with shell: true.
  4. Verification: your output JS should be ~7–10 MB for ~50–900 KB of embedded PE payload (roughly 200× bloat factor due to word encoding). Run node yourfile.js on a Windows VM with Node.js installed.

Deployable Signatures

YARA rule — letsdiskusscom poem-stego dropper

rule letsdiskusscom_poem_stego_dropper {
    meta:
        description = "Node.js poem-word-list steganography dropper (letsdiskusscom cluster)"
        author = "PacketPursuit"
        date = "2026-08-23"
        reference = "/intel/analyses/7d47ca60c6ec500c39868a79cdd15d3af2c35221b52aff6a4976e58dca47748a.html"
    strings:
        $wlist = "const wlist = \"gentle" ascii wide
        $app_name = "Microsoft Edge Updates Helper" ascii wide
        $func1 = "writePositionsToFile" ascii wide
        $func2 = "safeMakeDir" ascii wide
        $func3 = "launchExecutable" ascii wide
        $spawn = "require('child_process')" ascii wide
        $programdata = "process.env.PROGRAMDATA" ascii wide
    condition:
        filesize > 1MB and
        $wlist and $app_name and $func1 and $func2 and $func3 and $spawn and $programdata
}

Sigma rule — Node.js poem dropper execution

title: Node.js Poem-Stego Dropper Execution
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        CommandLine|contains:
            - 'Update_'
            - '.js'
        ParentImage|endswith:
            - '\node.exe'
            - '\wscript.exe'
        Image|endswith:
            - '\cmd.exe'
            - '\conhost.exe'
    cmdline:
        CommandLine|contains:
            - 'Microsoft Edge Updates Helper'
            - 'b7mqJjEYdRYn'
    condition: selection or cmdline
falsepositives:
    - Unknown — the Update_N.js pattern and directory name are specific
level: high

IOC list

Indicator Value Note
Carrier SHA-256 7d47ca60c6ec500c39868a79cdd15d3af2c35221b52aff6a4976e58dca47748a Update_18.js
Dropped EXE Microsoft Edge Updates Helper.exe Signed Revo component (SHA-256 8b94af60...)
Dropped DLL1 msvcp140.dll Rotates per build (18 distinct morphs observed)
Dropped DLL2 vcruntime140.dll Stable across cluster (SHA-256 ff43e813...)
Dropped DLL3 vcruntime140_1.dll Stable across cluster (SHA-256 7b8f70dd...)
Dropped BAT b7mqJjEYdRYn.bat HKCU Run persistence
Registry key HKCU\Software\Microsoft\Windows\CurrentVersion\Run Value: Microsoft Edge Updates Helper
Staging directory %ProgramData%\Microsoft Edge Updates Helper <12-char suffix>\ Per-build random suffix
Node.js functions writePositionsToFile, safeMakeDir, launchExecutable Static fingerprint

Behavioral fingerprint

This is a self-contained Node.js script that writes five files (one EXE, three DLLs, one BAT) to a fake Microsoft Edge Updates Helper directory under %ProgramData%, then spawns the BAT followed by the EXE via child_process.spawn with shell: true. No network activity in the carrier. The script contains a 256-word English poem lookup table and encodes binary payloads as sequences of poem words with numbered suffixes on repeats.

Detection Signatures

Capability ATT&CK ID Evidence
JavaScript execution T1059.007 require('fs'), require('child_process') ^[strings.txt:1-3]
Obfuscated Files or Info T1027.002 256-word poem lookup-table steganography ^[strings.txt:6]
Masquerading T1036.005 Microsoft Edge Updates Helper directory name ^[strings.txt:5]
Registry Run Keys T1547.001 BAT calls reg add on HKCU\...\Run ^[strings.txt:11]
Create/modify system process T1543.003 spawn(..., {shell: true, stdio: 'inherit'}) ^[strings.txt:39-41]

References

  • Artifact ID: 981a125c-dce2-4464-8e72-a3c8df643256 ^[metadata.json]
  • MalwareBazaar source
  • letsdiskusscom — entity page for the family
  • poem-word-list-steganography — technique page for the encoding method
  • registry-run-persistence — procedure page for the BAT-based Run key technique

Provenance

  • file.txt — file utility output (JavaScript source, ASCII, very long lines)
  • exiftool.json — ExifTool metadata (7.7 MB, 60 lines, Windows CRLF)
  • metadata.json — OpenCTI artifact record (filename Update_18.js, labels js, malware-bazaar)
  • strings.txt — full JavaScript source (same as file output, no binary overlay)
  • triage.json — triage-fast record (tier: deep, no family attribution)
  • capa.txt — capa error (unsupported file format, as expected for JS source)
  • floss.txt — floss error (CLI argument parsing failure, as expected for JS source)
  • rabin2-info.txt — radare2 binary info (bits=0, havecode=false, confirms non-PE)
  • binwalk.txt — no embedded artefacts detected
  • dynamic-analysis.md — CAPE skipped (JS source not a supported binary class)