71e6cb9e217945f0ae0b071e6b30417a7f28476fe79ca7b235d11609a8172a43letsdiskusscom: 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.jssits betweenUpdate_5.js(b53d6a32) andUpdate_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 indll4Pathdespite not being a DLL. The JS definesconst dll4Path = path.join(folder, "6loccZYQrhUC.bat")but never uses it; the BAT is written viaautorunPathinstead. ^[strings.txt:17]
How To Mess With It (Homelab Replication)
- Toolchain: Node.js v18+ on Windows or Linux
- 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) - Carrier: Wrap in a Node.js script using the
writePositionsToFilepattern fromstrings.txt. - Verify: Decode back to the original file and compare SHA-256.
- 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
- 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
Analysis derived from:
file.txt— file type identificationstrings.txt— full JavaScript source (the file is unobfuscated source code)triage.json— triage metadataexiftool.json— file metadata- Decoded payloads verified via Node.js runtime SHA-256 computation