typeanalysisfamilyletsdiskusscomconfidencehighcreated2026-08-23updated2026-08-23scriptnodejsobfuscationevasionpersistencemalware-family
SHA-256: 5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b

letsdiskusscom: 5ebd96a1 — Twenty-third confirmed sibling, Update_9.js poem-stego dropper

Executive Summary

A 9.2 MB Node.js self-extracting dropper (Update_9.js) masquerading as a Microsoft Edge update helper. Uses numbered-suffix poem-word-list steganography (gentle1, hush2, etc.) to encode a signed RevoSrp.exe payload plus three VC++ runtime DLLs and a BAT-based HKCU Run persistence script. Twenty-third confirmed sibling in the letsdiskusscom cluster. No C2 — fully self-contained. Static-only (CAPE skipped — JS source not a supported binary class). ^[strings.txt:1]

What It Is

Field Value
SHA-256 5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b
Filename Update_9.js
File type JavaScript source, ASCII text, CRLF line terminators ^[file.txt]
Size 9,227,899 bytes (9.2 MB)
ssdeep 6144:/ubnYpscp3SqA5mPYsTvQw1z8jBZlLtH+Bp89S5mfsw9wpNQVwS0msFJvXiESUWq:DPBqO ^[ssdeep.txt]
tlsh 4896DFAB6DEC361D3000B1C2F48521F5E6621336DBDE12D9B8F924337AFA49AC46D746 ^[tlsh.txt]

Preliminary family: letsdiskusscom (OpenCTI label letsdiskuss-com). High confidence — exact same Microsoft Edge Updates Helper masquerade, same poem-word-list encoding technique, same signed Revo payload and vcruntime DLLs, same BAT persistence pattern. ^[entities/letsdiskusscom.md]

How It Works

Payload Encoding

The carrier defines a 256-word English poem lookup table with numbered suffixes (gentle1, hush2, ... fail164). Five embedded binaries are encoded as space-delimited word sequences. At runtime writePositionsToFile splits the lookup table, maps each encoded word back to its index, and writes index & 0xFF to disk. This produces the original PE byte-for-byte. ^[strings.txt:6] ^[strings.txt:18]

Staged Files

Staged file Size SHA-256 Notes
Microsoft Edge Updates Helper.exe 52,400 B 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f RevoSrp.exe (Registry Cleaner), signed by VS REVO GROUP OOD via DigiCert Trusted G4 Code Signing CA ^[raw/analyses/5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b/exe.bin]
msvcp140.dll 1,119,232 B 72e5b6aaa61f9dcadee52fd680080e0b51389016190533f94a88b0cbc2797684 MSVC 14.27.29016.0, compiled 2020-06-16 (timestamp 0x5EE83852). PE32+ x64. Twenty-third distinct morph in cluster. ^[raw/analyses/5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b/dll1.bin]
vcruntime140.dll 101,672 B ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 Same as all 22 prior siblings
vcruntime140_1.dll 44,328 B 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 Same as all 22 prior siblings
CLTNCl7Ekb2U.bat 440 B dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919 HKCU Run persistence — adds "Microsoft Edge Updates Helper" pointing to EXE path

Execution Chain

  1. Creates %ProgramData%\Microsoft Edge Updates Helper CLTNCl7Ekb2U with mode 0o755. ^[strings.txt:27]
  2. Decodes all five payloads from poem-word indices to disk via writePositionsToFile. ^[strings.txt:18]
  3. Launches the BAT file with the EXE path as argument — BAT adds HKCU\Software\Microsoft\Windows\CurrentVersion\Run entry. ^[strings.txt:30]
  4. Launches the EXE directly via spawn(..., { shell: true, stdio: 'inherit' }). ^[strings.txt:29]

Note: dll4Path is declared but never written — a template artifact. ^[strings.txt:17]

Decompiled Behavior

Not applicable. The artifact is a raw Node.js script (not a PE binary). No compiled machine code is present; threat logic is plaintext JavaScript with lexical obfuscation. Ghidra / radare2 do not apply. ^[file.txt]

C2 Infrastructure

None. The dropper is fully self-contained — no network requests, no C2 URLs, no callback. The malicious act is the deceptive delivery of a signed third-party executable under a false identity, with registry persistence. ^[strings.txt]

Interesting Tidbits

  • Build counter continuity: Filename Update_9.js slots between existing siblings Update_5.js (b53d6a32), Update_12.js (2c86df65), Update_13.js (70862e4d), Update_14.js (a27bda89), Update_15.js (4c57911f), Update_16.js (26155786), Update_17.js (c075aeba), Update_18.js (7d47ca60), Update_19.js (b23bb560), Update_22.js (ff3ae2e7), Update_25.js (1fbaf8ab), and Update_1.js (bf5c69a5). The internal counter suggests at least 25 builds in this template. ^[triage.json]
  • Template artifact — dll4Path: A fourth DLL path is computed (CLTNCl7Ekb2U.bat) but never passed to writePositionsToFile. The BAT path is already handled by the bat variable. This suggests a builder template that optionally emits four DLLs, and this build left the fourth slot empty. ^[strings.txt:17]
  • module.exports dead code: The script ends with module.exports = writePositionsToFile;, which has no effect in a standalone .js file executed directly. Builder template leakage from a Node.js module context. ^[strings.txt:26]
  • Double EXE launch: The BAT adds the registry entry but does not launch the EXE. The subsequent launchExecutable(exePath) directly spawns the payload, meaning the EXE runs once immediately and will run again at next logon via the Run key. ^[strings.txt:30]
  • MSVC 14.27.29016.0 msvcp140.dll: The twenty-third distinct morph uses the same compiler version as most siblings (14.27.29016.0, 2020-06-16), confirming a fixed pool of legitimate runtime DLLs being rotated rather than custom-compiled payloads. ^[raw/analyses/5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b/dll1.bin]

How To Mess With It (Homelab Replication)

  1. Create a 256-word lookup table with numbered suffixes after the first cycle:
    gentle1 hush2 that3 wraps4 ... fail164
    
  2. Encode a file:
    words = lookup.split()
    with open('payload.exe','rb') as f:
        data = f.read()
    encoded = ' '.join(words[b] for b in data)
    
  3. Carrier script: Wrap in a Node.js file using the writePositionsToFile pattern with fs.writeFileSync and child_process.spawn.
  4. Verify: Decode the poem string back to the original payload; compare SHA-256.
  5. What you learn: How natural-language steganography defeats static string extraction and why child-process + %ProgramData% write monitoring is a better detection than content scanning.

Deployable Signatures

YARA Rule

rule Letsdiskusscom_PoemStego_JS
{
    meta:
        description = "Node.js poem-word-list steganography dropper (letsdiskusscom cluster)"
        author = "triage"
        family = "letsdiskusscom"
        reference = "/intel/analyses/5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b.html"
    strings:
        $a1 = "Microsoft Edge Updates Helper"
        $a2 = "writePositionsToFile"
        $a3 = "Buffer.from(positions.map(p => p & 0xFF))"
        $b1 = "gentle1 hush2 that3 wraps4"
        $b2 = "const fs = require('fs');"
        $b3 = "const { spawn } = require('child_process');"
    condition:
        filesize > 1MB and filesize < 20MB
        and #b2 == 1 and #b3 == 1
        and 2 of ($a*)
        and 1 of ($b*)
}

Behavioral Hunt Query (Sigma)

title: Node.js Letsdiskusscom Poem-Stego Dropper Execution
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    - Image|endswith: 'node.exe'
    - CommandLine|contains:
        - 'Microsoft Edge Updates Helper'
        - 'CLTNCl7Ekb2U'
        - 'writePositionsToFile'
  selection2:
    - ParentImage|endswith: 'node.exe'
    - Image|endswith:
        - 'reg.exe'
        - 'cmd.exe'
    - CommandLine|contains:
        - 'Microsoft Edge Updates Helper'
        - 'CLTNCl7Ekb2U'
  condition: selection or selection2
falsepositives:
  - Unknown
level: high

IOC List

Indicator Type Value
SHA-256 Hash 5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b
Filename String Update_9.js
Staging directory Path %ProgramData%\Microsoft Edge Updates Helper CLTNCl7Ekb2U
Registry key Registry HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Microsoft Edge Updates Helper
Revo payload Hash 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f
msvcp140.dll (this build) Hash 72e5b6aaa61f9dcadee52fd680080e0b51389016190533f94a88b0cbc2797684
vcruntime140.dll Hash ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833
vcruntime140_1.dll Hash 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7
BAT persistence Hash dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919

Behavioral Fingerprint

This artifact is a Node.js script that drops four PE files and one BAT to a %ProgramData% subdirectory named after a legitimate browser product. It uses a 256-word English poem with numbered suffixes as a byte-to-word lookup table, decoding payloads by word-index position. It then spawns a BAT that adds an HKCU Run registry key pointing to the dropped EXE, followed by direct execution of the EXE via child_process.spawn with shell: true. No network activity is generated by the carrier. The EXE payload is a signed copy of RevoSrp.exe (Registry Cleaner) with a rotating msvcp140.dll runtime.

Detection Signatures

Source Mapping Note
capa N/A capa errored — JS source is not a supported binary class ^[capa.txt]

References

  • letsdiskusscom — cluster entity page (twenty-three confirmed siblings)
  • poem-word-list-steganography — technique page for the 256-word poem encoding
  • natural-language-payload-encoding — concept page for prose-based payload hiding
  • registry-run-persistence — procedure page for the BAT-based Run key technique
  • MalwareBazaar: 5ebd96a1eb9cf6179dc7ea68b5b221c7aab22c460567071a930a11a24cd03f8b (Update_9.js)

Provenance

Analysis derived from file.txt, strings.txt, ssdeep.txt, tlsh.txt, triage.json, exiftool.json, and manual JavaScript deobfuscation via Python regex extraction. Python 3.12 used for payload decoding and SHA-256 verification. capa v8.0.1 and floss v3.1.0 errored on JS source; expected behavior. CAPE skipped — JavaScript source is not a supported binary class for detonation. No dynamic analysis performed. Report generated 2026-08-23.