bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316letsdiskusscom: bfc9e6e7 — Twenty-fourth confirmed sibling, Update_4.js poem-stego dropper (largest in cluster)
Executive Summary
An 11 MB Node.js self-extracting dropper (Update_4.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-fourth confirmed sibling in the letsdiskusscom cluster — and the largest by file size at 11,086,748 bytes. 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 | bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316 |
| Filename | Update_4.js |
| File type | JavaScript source, ASCII text, CRLF line terminators ^[file.txt] |
| Size | 11,086,748 bytes (11 MB) |
| ssdeep | 6144:rubnYpscL3SqA5mPYsTvQw1z8jBZlLtH+Bp89S5mfsowpNWVwS0msFJvXiESUWj6:NP3kO ^[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/bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316/exe.bin] |
| msvcp140.dll | 1,378,304 B | d58de9dc9a1404d1597ba8c68e9a284cd302c08cc244f559ee5cb2aa75444bb9 | MSVC 14.27.29016.0, compiled 2020-06-16 (timestamp 0x5EE83852). PE32+ x64. Twenty-fourth distinct morph in cluster. ^[raw/analyses/bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316/dll1.bin] |
| vcruntime140.dll | 101,672 B | ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 | Same as all 23 prior siblings |
| vcruntime140_1.dll | 44,328 B | 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 | Same as all 23 prior siblings |
| vIQNgHpMmTiD.bat | 440 B | dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919 | HKCU Run persistence — adds "Microsoft Edge Updates Helper" pointing to EXE path |
Execution Chain
- Creates
%ProgramData%\Microsoft Edge Updates Helper vIQNgHpMmTiDwithmode 0o755. ^[strings.txt:27] - Decodes all five payloads from poem-word indices to disk via
writePositionsToFile. ^[strings.txt:18] - Launches the BAT file with the EXE path as argument — BAT adds
HKCU\Software\Microsoft\Windows\CurrentVersion\Runentry. ^[strings.txt:30] - 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
- Largest in cluster: At 11,086,748 bytes, this is the largest letsdiskusscom sibling observed. The size inflation comes from the encoded payload strings, not the lookup table, suggesting the builder pads or the msvcp140.dll morph is simply larger. ^[triage.json]
- Build counter gap fill: Filename
Update_4.jsfills a gap betweenUpdate_1.js(bf5c69a5) andUpdate_5.js(b53d6a32). Combined withUpdate_9.js(5ebd96a1),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), andUpdate_25.js(1fbaf8ab), the internal counter now spans 1–25 with onlyUpdate_2,Update_6–Update_8,Update_10–Update_11,Update_20–Update_21, andUpdate_23–Update_24unobserved. The builder is clearly producing large batches. ^[triage.json] - Template artifact —
dll4Path: A fourth DLL path is computed (vIQNgHpMmTiD.bat) but never passed towritePositionsToFile. The BAT path is already handled by thebatvariable. This suggests a builder template that optionally emits four DLLs, and this build left the fourth slot empty. ^[strings.txt:17] module.exportsdead code: The script ends withmodule.exports = writePositionsToFile;, which has no effect in a standalone.jsfile 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-fourth 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. The 1,378,304-byte size is notably larger than most prior morphs (~900 KB–1.1 MB range). ^[raw/analyses/bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316/dll1.bin]
How To Mess With It (Homelab Replication)
- Create a 256-word lookup table with numbered suffixes after the first cycle:
gentle1 hush2 that3 wraps4 ... fail164 - Encode a file:
words = lookup.split() with open('payload.exe','rb') as f: data = f.read() encoded = ' '.join(words[b] for b in data) - Carrier script: Wrap in a Node.js file using the
writePositionsToFilepattern withfs.writeFileSyncandchild_process.spawn. - Verify: Decode the poem string back to the original payload; compare SHA-256.
- 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/bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316.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'
- 'vIQNgHpMmTiD'
- 'writePositionsToFile'
selection2:
- ParentImage|endswith: 'node.exe'
- Image|endswith:
- 'reg.exe'
- 'cmd.exe'
- CommandLine|contains:
- 'Microsoft Edge Updates Helper'
- 'vIQNgHpMmTiD'
condition: selection or selection2
falsepositives:
- Unknown
level: high
IOC List
| Indicator | Type | Value |
|---|---|---|
| SHA-256 | Hash | bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316 |
| Filename | String | Update_4.js |
| Staging directory | Path | %ProgramData%\Microsoft Edge Updates Helper vIQNgHpMmTiD |
| Registry key | Registry | HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Microsoft Edge Updates Helper |
| Revo payload | Hash | 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f |
| msvcp140.dll (this build) | Hash | d58de9dc9a1404d1597ba8c68e9a284cd302c08cc244f559ee5cb2aa75444bb9 |
| 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-four 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:
bfc9e6e703793e0fd480b98a95351d1b3b5c64bcf6ecf0afece8064a8954b316(Update_4.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. PE headers inspected with pefile 2023.2.7. 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-24.