familyus0fileconfidencemediumpemalware-familycrypterloaderanti-vmevasionreflective-pe-loaderc2gcleaner
SHA-256: 796a371d25a0a76a03f74fddd75c3774077d1329b7a27366a1bf9c6dfecd882c

us0file: 796a371d — MSVC 14.50 x64 encrypted-overlay dropper, GDCRYPT custom loader framework

Executive Summary

PE32+ x64 dropper/loader with a 608 KB encrypted overlay (82 % of file) and a custom decryption/mapping stub branded GDCRYPT!kernel32. Heavy anti-sandbox gating (QPC timing, RAM, CPU count, path checks) before reading its own overlay, decrypting the inner payload, and mapping it reflectively via direct ntdll primitives. Distributed via the gcleaner multi-payload bundler pipeline. Static-only analysis; CAPE skipped due to no Windows guest.

What It Is

  • SHA-256: 796a371d25a0a76a03f74fddd75c3774077d1329b7a27366a1bf9c6dfecd882c
  • Size: 744,566 bytes (727 KB on disk) ^[file.txt]
  • Format: PE32+ executable (GUI) x86-64, 6 sections ^[file.txt]
  • Timestamp: Stomped to Tue Jul 3 06:17:46 2007 UTC — falsified ^[pefile.txt:38]
  • Linker: MSVC 14.50 (Visual Studio 2019/2022 era) ^[exiftool.json]
  • Signed: Unsigned ^[rabin2-info.txt]
  • Overlay: 608,374 bytes appended at file offset 0x21400 (high entropy, encrypted) ^[terminal: python overlay check]
  • Distribution label: dropped-by-gcleaner / us0.file via OpenCTI ^[metadata.json]

How It Works

On execution, the stub enters a hardening routine at fcn.1400013f0 ^[r2:fcn.1400013f0] that performs a cascade of environment checks before touching the payload:

  1. QPC frequency/counter timing gate — Calls QueryPerformanceFrequency, QueryPerformanceCounter, Sleep(25), then measures elapsed time. If the ratio is outside a hardcoded threshold, aborts. ^[r2:fcn.1400013f0]
  2. Uptime gate — GetTickCount64 must return > 0x8f21 (~36 seconds) or the binary exits. Defeats fresh-snapshot sandboxes. ^[r2:fcn.1400013f0]
  3. RAM gate — GlobalMemoryStatusEx must report ≥ 256 MB or abort. ^[r2:fcn.1400013f0]
  4. CPU count gate — GetSystemInfo checks processor count; single-processor systems abort. ^[r2:fcn.1400013f0]
  5. Path gate — Converts its own module path to uppercase, then checks for PROGRAMDATA, PROGRAM FILES, or \WINDOWS\. If any match, aborts. This ensures it only runs from user-writable paths such as %TEMP%. ^[r2:fcn.1400013f0] ^[strings.txt:159-162]

If all gates pass, the stub creates a mutex (unnamed), releases it, then enters a jittered Sleep loop based on GetTickCount modulo arithmetic before proceeding to payload extraction.

Payload Extraction & Reflective Mapping

The inner payload lives in the 608 KB overlay. The stub reads its own file via CreateFileA/GetFileSize/ReadFile ^[r2:fcn.1400013f0] (xref to GetFileSize at 0x1400018e0), decrypts the overlay in memory, and maps it reflectively. Evidence for reflective mapping:

  • Direct ntdll imports resolved at runtime: NtAllocateVirtualMemory, NtProtectVirtualMemory, NtFreeVirtualMemory, RtlAddFunctionTable ^[strings.txt:156-159]
  • VirtualAlloc / VirtualProtect / CreateProcessA in the standard IAT ^[r2:list_imports]
  • FlushInstructionCache — typical after self-modifying or injected code ^[r2:list_imports]
  • GetProcAddress / LoadLibraryA — dynamic API resolution for payload dependencies ^[r2:list_imports]

The GDCRYPT!kernel32 marker at .rdata offset 0x145d0 (RVA 0x153d0) ^[terminal: python pefile scan] strongly suggests the decryption stub belongs to a custom crypter/loader framework the author calls GDCRYPT. A second occurrence tGDCRYPT! appears nearby ^[r2:list_strings].

Payload Naming Convention

The string %s%s.exe at RVA 0x153a0 ^[strings.txt:163] implies the inner payload is written to disk with a two-part filename (e.g., <dir><name>.exe), likely under %TEMP% after decryption.

.NET Fallback Indicator

mscoree.dll and CorExitProcess appear in strings ^[strings.txt:231], suggesting the inner payload may be a .NET assembly and the loader handles CLR bootstrap if reflection fails.

Decompiled Behavior

Radare2 analysis (level 3) recovered 532 functions. Entry point entry0 at 0x140001d90 ^[r2:entry0] delegates to fcn.140001de0 (initialisation) and fcn.1400013f0 (main payload orchestrator). The latter is the most interesting surface — it contains all anti-sandbox gates, overlay read logic, and the jittered sleep loop. A call-table dispatch at fcn.140013b00 (goto loc_rax) ^[r2:fcn.140013b00] is used for indirect function calls, a common anti-static-analysis pattern in custom loaders.

Notable function call chain from entry:

  • entry0 → fcn.140001de0 (init) → fcn.140002290 / fcn.140002950 → fcn.140007e34 → back to entry0
  • entry0 → fcn.1400013f0 (main) → GetFileSize, GetTempPathA, GetModuleFileNameA, CreateMutexA, Sleep, CreateFileA, etc.

C2 Infrastructure

No hardcoded C2 recovered statically. Network indicators are expected to be embedded inside the encrypted overlay and resolved at runtime by the inner payload. The loader itself has no WS2_32, WinHTTP, or WinInet imports. Distribution is via the gcleaner pipeline.

Interesting Tidbits

  • Stomped timestamp: The PE timestamp claims 2007, but the linker version (14.50) is circa 2019–2022. Classic anti-forensics. ^[pefile.txt:38] ^[exiftool.json]
  • GDCRYPT branding: The GDCRYPT!kernel32 marker is unique in this corpus. Suggests a private or small-batch crypter, not a commodity builder. ^[strings.txt:154]
  • Base36-like charset: bcdfghjklmnpqrstvwxyz0123456789 — a 32-character alphabet omitting vowels and uppercase. Possibly used for filename generation or a keyed encoding layer. ^[strings.txt:155]
  • No .rsrc section: Unlike many dropper families in this corpus, there are no embedded icons, manifests, or RCData payloads. The entire malicious content is in the overlay.
  • Six sections only: Clean MSVC layout (.text, .rdata, .data, .pdata, .fptable, .reloc). No packed or packed-like section names. ^[pefile.txt:79-199]

How To Mess With It (Homelab Replication)

Goal: Reproduce an encrypted-overlay dropper with anti-sandbox gates.

  1. Compile a 64-bit MSVC C++ stub (VS 2022, /MT, x64 Release).
  2. Implement QueryPerformanceCounter timing gate with Sleep(25) and ratio check.
  3. Add GlobalMemoryStatusEx ≥ 256 MB, GetSystemInfo processor count ≥ 2, and GetTickCount64 > 36 s gates.
  4. Check GetModuleFileNameA path for PROGRAMDATA, PROGRAM FILES, WINDOWS substrings (case-insensitive).
  5. Read own PE file from disk starting at the overlay offset (PointerToRawData + SizeOfRawData of last section).
  6. Decrypt with AES-256-CBC (key can be embedded obfuscated in .rdata).
  7. Map decrypted payload with VirtualAlloc + VirtualProtect (RX), or use NtAllocateVirtualMemory for stealth.
  8. Transfer execution via ((void(*)())ptr)() or CreateProcessA with CREATE_SUSPENDED for hollowing.

Verification: Run in a 1-CPU, 128 MB VM with < 10 s uptime — stub should exit silently. Run on a 4-CPU, 4 GB host from %TEMP% with > 60 s uptime — payload should execute.

Deployable Signatures

YARA Rule

rule us0file_gdcrypt_loader {
    meta:
        description = "us0file / GDCRYPT encrypted-overlay x64 dropper"
        author = "PacketPursuit"
        hash = "796a371d25a0a76a03f74fddd75c3774077d1329b7a27366a1bf9c6dfecd882c"
    strings:
        $gdcrypt = "GDCRYPT!kernel32" ascii wide
        $tgdcrypt = "tGDCRYPT!" ascii wide
        $ntalloc = "NtAllocateVirtualMemory" ascii
        $ntprotect = "NtProtectVirtualMemory" ascii
        $charset = "bcdfghjklmnpqrstvwxyz0123456789" ascii
        $fmt = "%s%s.exe" ascii
        $mscoree = "mscoree.dll" ascii
    condition:
        uint16(0) == 0x5A4D and
        uint32(uint32(0x3C)) == 0x00004550 and
        uint16(uint32(0x3C)+0x18) == 0x20B and // PE32+
        3 of ($gdcrypt, $ntalloc, $ntprotect, $charset, $fmt, $mscoree)
}

Behavioral Hunt Query (Sigma-like)

A process matching this fingerprint should be flagged:

  • 64-bit PE with no .rsrc section and ≥ 500 KB overlay
  • Calls CreateFileA on its own module path within 5 seconds of launch
  • Calls GlobalMemoryStatusEx, GetSystemInfo, QueryPerformanceCounter, and Sleep(25) in sequence
  • Calls NtAllocateVirtualMemory or VirtualAlloc with MEM_COMMIT | MEM_RESERVE and PAGE_EXECUTE_READ shortly after file read

IOC List

Indicator Value
SHA-256 796a371d25a0a76a03f74fddd75c3774077d1329b7a27366a1bf9c6dfecd882c
ssdeep 12288:T5SlDfoAncPEnE6IvCq+pyJhvurwFavepkB9pWD2S9IXwLIodlRx:TgxcP/JhJlurkpwpWDFIodDx ^[triage.json]
Family label (OpenCTI) us0.file / dropped-by-gcleaner
Loader marker GDCRYPT!kernel32
Filename pattern %s%s.exe (two-part concatenation)
Expected staging path %TEMP% (path-gated against system directories)

Detection Signatures

ATT&CK Technique Evidence Source
T1055 — Process Injection NtAllocateVirtualMemory, NtProtectVirtualMemory, CreateProcessA, FlushInstructionCache ^[r2:list_imports]
T1620 — Reflective Code Loading Custom overlay read → decrypt → VirtualProtect → indirect dispatch Static inference from entry chain ^[r2:entry0]
T1497.001 — Virtualization/Sandbox Evasion RAM < 256 MB, CPU count, path checks ^[r2:fcn.1400013f0]
T1497.003 — Time Based Evasion QPC timing gate, GetTickCount64 uptime > 36 s ^[r2:fcn.1400013f0]
T1106 — Native API Direct ntdll primitive strings ^[strings.txt:156-159]
T1564.003 — Hide Artifacts 608 KB encrypted overlay concealing payload ^[terminal: python overlay check]

References

  • Artifact ID: f0822e14-f2df-4b0b-897c-1f1740918101 ^[metadata.json]
  • OpenCTI labels: dropped-by-gcleaner, us0.file ^[triage.json]
  • Related entity: gcleaner — distribution infrastructure
  • Related concept: reflective-pe-loader — runtime payload mapping pattern

Provenance

Analysis based on static outputs generated by triage pipeline on 2026-05-29: file, exiftool, pefile, strings, rabin2, binwalk, triage.json, metadata.json. Radare2 analysis level 3 performed during deep-dive on 2026-08-26. CAPE detonation skipped — no Windows guest available. Floss and capa errored during triage (signature path missing).