typeanalysisfamilyletsdiskusscomconfidencehighcreated2026-08-24updated2026-08-24malware-familyloaderscriptnodejsobfuscationevasionpersistencemitre-attck
SHA-256: adc5a0b48efb808930acadd51091509e481512446aac030a367d4577be861eb2

letsdiskusscom: adc5a0b48efb — Update_23.js, 25th confirmed sibling, 25th distinct msvcp140.dll morph

Executive Summary

Twenty-fifth confirmed sibling in the letsdiskusscom Node.js poem-word-list dropper cluster (Update_23.js, 7.8 MB). Uses the active numbered-suffix steganography template (gentle1, hush2, etc.) to encode four PE files and one BAT script inside a 256-word English poem. Embeds the same signed Revo EXE and both vcruntime DLLs as all twenty-four prior siblings, confirming payload reuse, but swaps msvcp140.dll for a twenty-fifth distinct morph (915,968 bytes, MSVC 14.27.29016.0). Staging directory suffix is P0fUY3DjdXfI. No C2, no network — self-contained local installer with BAT-based HKCU Run persistence. Static-only (CAPE skipped — JS source unsupported).

What It Is

Field Value
SHA-256 adc5a0b48efb808930acadd51091509e481512446aac030a367d4577be861eb2
Filename Update_23.js
Size 7,761,938 bytes (7.8 MB)
Type JavaScript source, ASCII, CRLF line terminators, 60 lines, very long lines (63,365 chars) ^[file.txt]
OpenCTI labels js, malware-bazaar ^[triage.json]
Family letsdiskusscom (high-confidence cluster sibling)
Tier deep

How It Works

The carrier is a Node.js script that relies on the victim having node.exe available (or being bundled with a portable runtime). It defines five payload strings encoded via a 256-word English poem lookup table with numbered suffixes on repeated vocabulary words (e.g. gentle1, hush2). At runtime, the writePositionsToFile function splits the poem into an array, looks up each payload word to recover its byte index, and writes the resulting bytes to disk. ^[strings.txt:0-59]

Decoded payloads (all five written to %ProgramData%\Microsoft Edge Updates Helper P0fUY3DjdXfI\):

File SHA-256 Size Notes
Microsoft Edge Updates Helper.exe 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f 52,400 Same as all 24 prior siblings. Signed RevoSrp.exe (VS Revo Group, DigiCert), MSVC 14.44, compiled 2025-06-02. ^[exiftool.json]
msvcp140.dll fa77a57e508320f005266cd8d28efb61dd36de3a019e8fcf940045c322a13c1a 915,968 25th distinct morph in cluster. MSVC 14.27.29016.0, compiled 2020-06-16. Microsoft-signed (certificate parse warning in rabin2). ^[exiftool.json]
vcruntime140.dll ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 101,672 Same as all prior siblings. Microsoft-signed. ^[exiftool.json]
vcruntime140_1.dll 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 44,328 Same as all prior siblings. Microsoft-signed. ^[exiftool.json]
P0fUY3DjdXfI.bat dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919 440 Same as all prior siblings. Writes HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Microsoft Edge Updates Helper. ^[strings.txt]

After dropping the files, the script spawns the BAT with the EXE path as an argument, then spawns the EXE directly via child_process.spawn(..., { shell: true }). ^[strings.txt:54-55]

Template artifact preserved: const dll4Path = path.join(folder, "P0fUY3DjdXfI.bat") is declared on line 21 but never used — the BAT is written via writePositionsToFile(wlist, bat, autorunPath) instead. This dead-variable artifact has been present in every numbered-suffix sibling since the template was introduced. ^[strings.txt:21]

Decompiled Behavior

Not applicable — the sample is a JavaScript source file, not a compiled PE. No Ghidra or radare2 decompilation possible. The entire logic is plaintext Node.js. ^[file.txt]

C2 Infrastructure

None. The dropper is entirely self-contained; no network calls, no download URLs, no callback domains. The malicious act is the deceptive delivery and silent execution of the signed Revo EXE inside a masquerade directory. ^[strings.txt]

Interesting Tidbits

  • Build-counter continuity: Update_23.js fills the gap between Update_22.js (sibling ff3ae2e72f50) and Update_25.js (sibling 1fbaf8ab9f90), confirming the internal build numbering is sequential and this template is actively maintained. ^[strings.txt:4]
  • No payload evolution: Twenty-five builds, zero change to the embedded EXE, DLL2, DLL3, or BAT hashes. The only rotated component is msvcp140.dll. This suggests the builder is a kit where the operator swaps in a fresh VC++ runtime DLL per build while the core payload (RevoSrp.exe) remains static. ^[exiftool.json]
  • Certificate on EXE: DigiCert-signed, valid at time of compilation (Jun 2025). The signature is legitimate — the threat is not the EXE itself but the deceptive delivery mechanism and the registry persistence it installs. ^[exiftool.json]
  • DLL1 certificate parsing issue: rabin2 -I reports signed: false with a warning "Invalid certificate entry" for the msvcp140.dll, yet pefile confirms a non-zero cert directory size. This is likely a rabin2 parsing quirk on Microsoft Authenticode with nested SPC certificates; the DLL is genuine Microsoft VC++ runtime 14.27. ^[exiftool.json]

How To Mess With It (Homelab Replication)

  1. Reproduce the encoder:
    with open('words.txt') as f:
        words = f.read().split()  # 256 words
    with open('payload.exe', 'rb') as f:
        data = f.read()
    encoded = ' '.join(words[b] for b in data)
    
  2. Wrap in Node.js carrier using the writePositionsToFile pattern from any letsdiskusscom sibling.
  3. Verify: Decode the JS back to the original PE and compare SHA-256.
  4. Observe: The resulting .js will be ~15× the size of the payload (poem words are longer than raw bytes) and will have very low Shannon entropy despite large file size — a strong anti-static signal that is ironically easy to detect.

Deployable Signatures

YARA — JS poem-stego dropper (numbered-suffix variant)

rule letsdiskusscom_js_poem_stego_numbered_suffix : script dropper {
    meta:
        description = "Node.js poem-word-list steganography dropper with numbered suffixes (letsdiskusscom cluster)"
        author = "PacketPursuit"
        date = "2026-08-24"
        sha256 = "adc5a0b48efb808930acadd51091509e481512446aac030a367d4577be861eb2"
        family = "letsdiskusscom"
    strings:
        $node1 = "const fs = require('fs');"
        $node2 = "const path = require('path');"
        $node3 = "const { spawn } = require('child_process');"
        $func = /function writePositionsToFile\(listA, listB, outPath\)/
        $wlist = "const wlist ="
        $exe = "const exe ="
        $bat = "const bat ="
        $app_name = "Microsoft Edge Updates Helper"
        $numbered = /gentle\d+ hush\d+/           // numbered-suffix template fingerprint
    condition:
        filesize > 1MB and filesize < 15MB
        and all of ($node*)
        and $func
        and $wlist
        and $exe
        and $bat
        and $app_name
        and $numbered
}

Sigma — BAT-based HKCU Run persistence

title: letsdiskusscom BAT Registry Run Persistence
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        CommandLine|contains|all:
            - 'reg add'
            - 'HKCU\Software\Microsoft\Windows\CurrentVersion\Run'
            - 'Microsoft Edge Updates Helper'
    condition: selection
falsepositives:
    - Unknown
level: high
tags:
    - attack.persistence
    - attack.t1547.001

IOC list

Indicator Type Value Note
Carrier SHA-256 hash adc5a0b48efb808930acadd51091509e481512446aac030a367d4577be861eb2 Update_23.js
Embedded EXE SHA-256 hash 8b94af60bb58bc1629edb3b4f6a86ccff5769bb9b96d8826f06686af2d7fc55f RevoSrp.exe (same across all siblings)
Embedded BAT SHA-256 hash dff20059f161090c76f9f45ac2269f2965bdc96023c78c1072f8d1aa66b06919 Same across all siblings
Staging directory path %ProgramData%\Microsoft Edge Updates Helper P0fUY3DjdXfI\ This sample's suffix
Registry value reg HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Microsoft Edge Updates Helper BAT persistence
Embedded DLL2 SHA-256 hash ff43e813785ee948a937b642b03050bb4b1c6a5e23049646b891a66f65d4c833 vcruntime140.dll
Embedded DLL3 SHA-256 hash 7b8f70dd3bdae110e61823d1ca6fd8955a5617119f5405cdd6b14cad3656dfc7 vcruntime140_1.dll

Behavioral fingerprint

This Node.js script writes four PE files and one BAT file to a %ProgramData% subdirectory named Microsoft Edge Updates Helper <random_suffix>\, then immediately spawns the BAT (passing the EXE path as an argument) followed by spawning the EXE directly via child_process.spawn with shell: true. The BAT adds an HKCU Run key pointing to the EXE. No network traffic is generated by the carrier. The script is 7–11 MB, contains 60 lines with lines exceeding 60,000 characters, and encodes payloads as space-separated English poem words with numbered suffixes.

Detection Signatures

ATT&CK Technique Evidence
T1059.007 Command and Scripting Interpreter: JavaScript Node.js require('fs'), require('child_process') ^[strings.txt]
T1027.002 Obfuscated Files or Information 256-word poem lookup-table with numbered-suffix encoding ^[strings.txt]
T1036.005 Masquerading Microsoft Edge Updates Helper directory name ^[strings.txt]
T1547.001 Boot or Logon Autostart Execution: Registry Run Keys BAT calls reg add HKCU\...\Run with value Microsoft Edge Updates Helper ^[strings.txt]
T1543.003 Create or Modify System Process spawn(..., { shell: true }) executes staged EXE ^[strings.txt]

References

  • letsdiskusscom — Entity page for the cluster (24 prior confirmed siblings)
  • poem-word-list-steganography — Technique page for the 256-word poem encoding
  • registry-run-persistence — Procedure page for the BAT-based Run key
  • natural-language-payload-encoding — Concept page for prose-based payload hiding
  • MalwareBazaar artifact: adc5a0b48efb808930acadd51091509e481512446aac030a367d4577be861eb2

Provenance

  • file.txt — file utility output (file type identification)
  • exiftool.json — ExifTool metadata extraction (file size, line counts, MIME type)
  • strings.txt — Full ASCII string extraction (JavaScript source lines, poem vocabulary, function definitions, file paths)
  • triage.json — Triage pipeline metadata (artifact ID, labels, tier assignment)
  • Decoded payloads verified by re-running the writePositionsToFile decoding logic in Python and confirming SHA-256 hashes match the original cluster payloads for EXE, DLL2, DLL3, and BAT.
  • DLL1 (msvcp140.dll) hash fa77a57e... is novel to this sample and does not appear in any of the 24 prior sibling reports.