familyunclassified-js-cjk-stego-dropperconfidencehigh
SHA-256: 0de6482c69377a127b91aa9c28d24981b656be44a9181a83c5b014a933987216

Report: RFQ rfq_pdf.js — CJK-Steganography JScript Dropper

Build / RE

Outer Stage — JScript Polyglot (UTF-16 LE)

The carrier file is a 1,027,966-byte JScript source saved as UTF-16 LE with CRLF line terminators ^[file.txt], making it appear as Unicode text to casual inspection and causing CAPE to skip detonation (not a supported binary class). The social-engineering lure is a request-for-quotation PDF masquerade (RFQ rfq_pdf.js) — a double-extension attack exploiting Windows "Hide extensions for known file types." ^[metadata.json]

The script is not obfuscated with javascript-obfuscator or any commercial tool. Instead, the author has hand-rolled a CJK Unified Ideographs steganography engine that encodes a raw PE payload inside Unicode character literals assigned to nested JavaScript object properties.

Key structural observations from the decoded script ^[strings.txt]:

  • A global object KazakhstanFinallyUnfinishedStopped acts as a lookup table with 74 top-level semantic English keys (e.g., RitchieDetectingNutrientSuffers, FarmingAppellantLawyersHoffmanSpanish).
  • Each top-level key contains between 4 and 8 nested sub-keys, also random semantic English phrases (e.g., FamiliarityDistributionBatteriesHomepageInteraction, BrendanSpeciallyCruises).
  • The leaf value of every nested property is a long CJK character string (e.g., "㑍㑚㒐㐀㐃㐀㐀㐀㐄..."). Each CJK character encodes one payload byte via byte = charcode - 0x3400.
  • An array PostponedChargedOperationalRestrictionsMichaels holds 384 environment-variable names.
  • A second array VerticallyStayingSamuraiRealism holds 384 [top_key, sub_key] pairs.
  • A for loop walks both arrays in lockstep, assigns each decoded CJK block to an environment variable via WScript.Shell.Environment("Process").Item(...), then spawns a PowerShell stage that reads those variables back and reconstructs the inner payload in-memory.

The technique is a custom byte-in-Unicode steganography with semantic English variable/key names used purely as obfuscation — the phrases have no actual meaning in the malware logic.

Inner Stage — .NET Framework 4.8 PE32+ Assembly

Reconstruction of the 384 CJK blocks yields a 385,024-byte PE32+ executable (GUI) x86-64 Mono/.NET assembly ^[reconstructed.bin].

Property Value
TimeDateStamp 0x4ea90170 (2011-10-28 06:10:56 UTC) — likely forged or statically linked library timestamp
Linker 11.27 (Visual Studio 2012 / .NET 4.8 toolchain)
Magic 0x20b (PE32+)
Subsystem 2 (GUI)
Sections .text (382,464 bytes, entropy 2.60), .rsrc (2,048 bytes, entropy 4.11)
EntryPoint 0x0 (typical for .NET assemblies; CLR handles entry)

All observable type and method names are obfuscated with random semantic English phrases (e.g., AspirationsVegetablesUnregisteredDesignatedPartnerships, AuthorizesMercedesPracticed, GrindingNonethelessSubsystemAdherenceAndover) — the same naming convention used in the outer JScript keys. No meaningful namespace, class, or method names survive.

Import surface:

  • URLDownloadToFileW from urlmon.dll ^[strings.txt] — the primary C2 download primitive.
  • OleGetClipboard / OleFlushClipboard — clipboard manipulation.
  • AccessibleObjectFromWindow — potential accessibility/UI automation abuse.
  • AllocHGlobal, Marshal — unmanaged memory allocation.
  • GetCurrentProcess — self-reference.
  • SHA256, ComputeHash, System.Security.Cryptography — hashing/cryptographic operations.
  • Standard .NET Framework 4.8 references: System.Runtime.InteropServices, System.Runtime.CompilerServices, DllImportAttribute, AsyncCallback, BeginInvoke.

No hardcoded URLs, IPs, or domains were recovered from the reconstructed binary via static string extraction. The C2 endpoint is likely delivered at runtime or embedded in a secondary resource/config block that is itself encrypted.

The .NET assembly does not appear to be packed with ConfuserEx, SmartAssembly, or similar commercial protectors; the obfuscation is limited to name mangling and the outer CJK steganography wrapper. Entropy on .text (2.60) is consistent with unobfuscated IL, not a packed or encrypted payload.

Anti-Analysis

  • UTF-16 LE encoding with very long lines (5,559-character lines) frustrates line-based grep and diff tools. ^[file.txt]
  • CJK steganography hides the PE payload inside Unicode character literals that look like padding or noise to Western-language analysts.
  • Semantic English obfuscation (random dictionary words for all variables, keys, and .NET type names) defeats string-based IOC extraction and symbol-based detection.
  • Environment-variable staging breaks the payload across 384 process-scoped variables, making memory-dump analysis harder.
  • No CAPE detonation because the outer file is typed as JavaScript text, not a PE — the sandbox skipped execution entirely. ^[dynamic-analysis.md]

Deploy / ATT&CK

Technique ID Evidence
User Execution T1204.001 Double-extension JScript lure (RFQ rfq_pdf.js) masquerading as a PDF.
Obfuscated Files or Information T1027.002 Custom CJK Unicode steganography encoding a PE payload inside JavaScript object literals.
Inter-Process Communication via Environment Variables T1134 (analogous) Payload reconstructed from 384 WScript.Shell.Environment("Process") variables.
Ingress Tool Transfer T1105 URLDownloadToFileW import in inner .NET assembly; downloader behavior inferred.
Clipboard Modification T1115 OleGetClipboard / OleFlushClipboard present in .NET assembly.
Cryptographic Hashing T1560.001 SHA256.ComputeHash present; likely used for integrity checking or data transformation.

C2 protocol: Static-only analysis. No network IOCs recovered. The inner .NET assembly imports URLDownloadToFileW from urlmon.dll, indicating an HTTP/HTTPS download stage, but the target URL is not embedded in the binary strings. It may be:

  1. Passed as an argument from the JScript stage (not recovered in this analysis), or
  2. Embedded in an encrypted resource or config block decoded at runtime.

Persistence: None observed statically. The JScript does not write to %APPDATA%\Startup, registry Run keys, or scheduled tasks. The .NET assembly may establish persistence after fetching its final payload, but that behavior requires dynamic execution.

Attribution: No linguistic, cultural, or infrastructure indicators. The semantic English obfuscation is generic (random dictionary words). No reused code signatures, PDB paths, or compiler artifacts link this to a known family. This is a singleton pending cluster confirmation.

Siblings

None confirmed. This is the first observed sample of this technique in the corpus.

IOCs

  • SHA-256 (outer): 0de6482c69377a127b91aa9c28d24981b656be44a9181a83c5b014a933987216
  • SHA-256 (inner .NET): a0ddf0c9be23a7df15c29baa73d957d73f3dacadbc541673b89e9c61024ceb3c
  • MD5 (inner .NET): 99ace247a5da67754991079ce63efa85
  • Filename lure: RFQ rfq_pdf.js
  • Steganography decode key: byte = charcode - 0x3400
  • Environment variable count: 384
  • CJK block count: 384

Recommendations

  1. Sigma / YARA: Hunt for UTF-16 LE JScript files containing large blocks of CJK Unified Ideographs (U+3400–U+4DBF) interleaved with semantic English variable assignments. A regex like KazakhstanFinallyUnfinishedStopped\["[A-Z][a-z]+"\] is family-specific but may be brittle if the author rotates keys.
  2. Memory forensics: Scan process environment blocks for unusually high counts of WScript.Shell-created variables containing Base64 or binary data.
  3. Dynamic: Execute the sample in a JavaScript-capable sandbox (not CAPE) to capture the PowerShell spawn and network traffic from the inner .NET downloader.