3dc65c75a559b15e60f09abfbdb1d4399cda6dc4134a793930d90e21d4ceebe3esmk-crypter-loader: 3dc65c75 — MinGW-w64 reflective PE loader with nibble-encoded resource payload
Executive Summary
Stripped x64 PE compiled with MinGW-w64 GCC 15.2.0. Internal name "ESMK" via debug string. The binary is a custom crypter/loader: it extracts an encrypted payload from its own .rsrc section (type 0x0a, name 0x65), nibble-decodes it, decrypts it with an algorithm selected from embedded constants, decompresses via LZSS/XZ, and maps the result as a reflective PE image in freshly allocated RWX memory. No C2 or persistence logic lives in the loader stage; the final payload family is unknown statically.
1. Build / RE
Toolchain. MinGW-w64 GCC 15.2.0 (Brecht Sanders build, r7), compiled 2024-04-08 15:44:53 UTC. ^[exiftool.json] ^[rabin2-info.txt:11] ^[strings.txt:280-300] Stripped x64 PE, ASLR/NX-compatible, with external PDB reference. ^[pefile.txt:38-74]
Obfuscation. No commercial packer (UPX, VMProtect, Themida) — the binary is its own loader. Control-flow flattening at fcn.140001f00: a state variable seeded with XOR constant 0x1a83e4a0 drives an 8-case jump table at 0x140001fac. ^[r2:fcn.140001f00] The .rsrc section is 185,856 bytes (raw offset 0x28800) and holds the encrypted secondary payload. ^[pefile.txt:258-264]
Anti-analysis. Byte gate: value at 0x140026043 must equal 0x31; mismatch triggers MessageBoxA("Invalid DOS signature") then aborts. ^[r2:fcn.1400017b0] Anti-debug gate: XORs the VirtualAlloc base with GetCurrentProcessId, GetCurrentThreadId, and GetTickCount, comparing against 0xffff. ^[r2:fcn.1400017b0]
Decryption / Decompression Pipeline. Three-stage transform inferred from strings and decompilation:
- Nibble decode —
"Nibble-decoded: %lu -> %lu bytes"atstrings.txt:244. - Algorithm-selectable decryption —
algorithmIDderived from constants0x6a0f51f7(.data0x140026028) and0x3507a1d7(.data0x140026024), masked with0x1f. ^[r2:fcn.140001f00] - LZSS/XZ decompression —
fcn.140003f20uses the magic constant0xcf1bbcdcbb000000(a variant of the XZ CRC-64 polynomial) and exhibits classic LZSS hash-table + match-length encode/decode loops with0x8080808080808081division shortcut. ^[r2:fcn.140003f20]
Reflective Mapping. fcn.1400017b0 validates the decrypted buffer as a PE (DOS/PE signatures), allocates RWX memory via VirtualAlloc(flAllocationType=0x3000, flProtect=0x4), copies headers and sections with fcn.140002640, processes relocations, resolves imports, calls RtlAddFunctionTable, and transfers control to the payload entry point. ^[r2:fcn.1400017b0] Strings confirm: "ExecuteFile: Starting (reflective)", "Sections mapped: %u", "Calling entry point: 0x%p", "ExecuteFile succeeded, resuming thread...". ^[strings.txt:220-260]
Notable Functions.
fcn.140001f00— CFF resource loader:FindResourceA(0, 0x65, 0x0a)→LockResource→ nibble-decode → decrypt → decompress → hand off to mapper. ^[r2:fcn.140001f00]fcn.1400017b0— Reflective PE mapper. ^[r2:fcn.1400017b0]fcn.140003f20— LZSS/XZ decompressor engine; called via wrapperfcn.140008620/fcn.140008680. ^[r2:fcn.140003f20]
2. Deploy / ATT&CK
Static-only — no CAPE guest available. All TTPs inferred from decompiled control flow and string evidence.
- T1055.012 (Process Injection: Process Hollowing) —
fcn.1400017b0performs reflective in-memory PE mapping:VirtualAlloc+ section copy + import resolution +RtlAddFunctionTable+ entry-point transfer. ^[r2:fcn.1400017b0] - T1027.002 (Obfuscated Files or Information: Software Packing) — Custom nibble encoding + algorithm-selectable encryption + LZSS compression over the
.rsrcpayload. ^[strings.txt:243-257] - T1622 (Debugger Evasion) — Anti-debug fingerprint gate before payload execution. ^[r2:fcn.1400017b0]
- T1497.001 (Virtualization/Sandbox Evasion: System Checks) — Time-based fingerprinting via
GetTickCountmixed with PID/TID. ^[r2:fcn.1400017b0]
Persistence / C2. None in the loader. The final payload is unknown statically.
Attribution. Internal string "ESMK allocated new buffer, freeing old one." at strings.txt:249 gives the family name. OpenCTI tags dropped-by-gcleaner and mix5.file place this in the gcleaner multi-payload distribution cluster, but the MinGW-w64 build and custom crypter are distinct from the Delphi/.NET droppers historically associated with that label. ^[metadata.json] Same distribution-vs-family mismatch seen in prior gcleaner-tagged MSVC builds (e.g. unclassified-pe32-clipper). ^[gcleaner]
Provenance. Static analysis only. All dynamic behaviour inferred from decompiled control flow and string evidence. No CAPE detonation performed.