ac20be185f5e5d931516336e80d7c3fd3adda6519418877de50181acf6986873unclassified-pe32-nfe-loader: ac20be18 — 4 KB MinGW launcher stub for core.dll
Executive Summary
A 4 KB PE32 launcher stub built with MinGW GCC 15.1.0, sharing an exact compilation timestamp with the unclassified-pe32-nfe-loader payload DLL (ded59ec4). Loads core.dll from the same directory and dispatches its MainCall export, gating execution on GetSystemMetrics / GetDesktopWindow values XOR-folded with 0x41. No C2, no persistence, no payload encryption — a pure two-stage loader designed to detach the malicious DLL from the initial dropper fingerprint.
What It Is
| Field | Value |
|---|---|
| SHA-256 | ac20be185f5e5d931516336e80d7c3fd3adda6519418877de50181acf6986873 |
| Filename | jotkyalz.exe ^[triage.json:5] |
| Type | PE32 executable (GUI) Intel 80386, stripped ^[file.txt] |
| Size | 4,096 bytes ^[triage.json:13] |
| Compiler | GCC: (i686-posix-dwarf-rev0, Built by MinGW-Builds project) 15.1.0 ^[strings.txt:14] |
| Linker | 2.44 (PE Optional Header) ^[pefile.txt:51] |
| Compiled | Fri May 15 06:16:29 2026 UTC ^[pefile.txt:39] |
| Base | 0x18000000 ^[rabin2-info.txt] |
| Signed | No ^[rabin2-info.txt:27] |
| PDB | None (stripped to external PDB) ^[file.txt] |
| Sections | .pko, .rdata, .eh_fram, .bss, .idata, .rsrc, .reloc (7 sections) ^[pefile.txt] |
Family ascription: Medium-confidence sibling of ded59ec4 (unclassified-pe32-nfe-loader). Evidence: byte-identical compilation timestamp (0x6A06BA3D), matching MinGW toolchain, shared core.dll/MainCall strings, and complementary functionality (this binary loads the DLL that ded59ec4 implements). ^[pefile.txt:39] ^[/intel/analyses/ded59ec4522cc19e2ae926ba1938452f70d8739d687154b9150141dc79af294c.html]
How It Works
Launcher Logic Flow
- Environment probe. Calls
GetSystemMetrics(0)(screen width in pixels) andGetDesktopWindow()(desktop window handle). ^[r2:entry0] ^[pefile.txt:297] - Anti-sandbox gate. XORs the two results together, stores the value in
.bssat0x18004000, then XORs the stored value with0x41. ^[r2:entry0] - DLL load. Calls
LoadLibraryA("core.dll"). The string lives in.rdataat RVA0x2001. ^[r2:entry0] ^[strings.txt:7] - Export resolution. Calls
GetProcAddress(hMod, "MainCall"). The export-name string is at RVA0x2009. ^[r2:entry0] ^[strings.txt:8] - Dispatch. If
GetProcAddresssucceeds, calls the resolved function pointer withlpCmdLine(or a pointer to.rdatabase if the command line is empty). ^[r2:entry0] - Failure path. If
LoadLibraryAorGetProcAddressfails, callsFreeLibrary(on whatever handle it has) and returns status code2(ENTRY_NOT_FOUND). ^[r2:entry0]
IAT Profile
The binary imports exactly five APIs — the absolute minimum needed for this workflow: ^[pefile.txt:275]
| DLL | API | Use |
|---|---|---|
KERNEL32.dll |
FreeLibrary |
Cleanup on failure |
KERNEL32.dll |
GetProcAddress |
Resolve MainCall export |
KERNEL32.dll |
LoadLibraryA |
Load core.dll |
USER32.dll |
GetDesktopWindow |
Environment probe / gate input |
USER32.dll |
GetSystemMetrics |
Environment probe / gate input |
No network APIs, no file-write APIs, no registry APIs — everything else is delegated to core.dll.
Decompiled Behavior
Entry point (entry0 @ 0x18001060):
push esi
push ebx
sub esp, 0x14
// GetSystemMetrics(0) — screen width
mov dword [esp], 0
call dword [sym.imp.USER32.dll_GetSystemMetrics]
mov esi, eax // esi = screen width
// GetDesktopWindow() — desktop HWND
call dword [sym.imp.USER32.dll_GetDesktopWindow]
// XOR gate: store screen width in .bss, then XOR with desktop handle
mov edx, dword [section..bss]
mov dword [esp], str.core.dll
xor esi, edx
mov dword [section..bss], esi
mov edx, dword [section..bss]
xor eax, edx
mov dword [section..bss], eax
mov eax, dword [section..bss]
xor eax, 0x41
mov dword [section..bss], eax
// LoadLibraryA("core.dll")
call dword [sym.imp.KERNEL32.dll_LoadLibraryA]
mov esi, eax
sub esp, 4
mov eax, 1
test esi, esi
jz fail_path
// GetProcAddress(esi, "MainCall")
lea eax, [str.MainCall]
mov dword [esp+4], eax
mov dword [esp], esi
call dword [sym.imp.KERNEL32.dll_GetProcAddress]
sub esp, 8
test eax, eax
jz fail_path
// Call MainCall with lpCmdLine (or .rdata base if zero)
mov ebx, dword [arg_28h] // lpCmdLine
test ebx, ebx
mov edx, section..rdata
cmove ebx, edx
mov dword [esp], ebx
call eax // dispatch to MainCall
fail_path:
mov dword [esp], esi
call dword [sym.imp.KERNEL32.dll_FreeLibrary]
mov eax, 2
sub esp, 4
Control-flow notes: The gate logic is brittle — .bss is zero-initialized, so GetSystemMetrics(0) ^ 0 yields the raw screen width, then desktop_handle ^ screen_width ^ 0x41 is stored. The result is never used as a branch condition; it is simply written to .bss and the code proceeds regardless. This suggests the gate may be a stub or placeholder (the real gate could live inside core.dll), or the XOR loop is intended as an anti-static obfuscation trick rather than a runtime sandbox guard. ^[r2:entry0]
C2 Infrastructure
None. No network APIs, no URLs, no IPs, no mutexes. The binary is a pure local loader.
Interesting Tidbits
- Build twin: The
TimeDateStampfield (0x6A06BA3D) is byte-identical toded59ec4, indicating these two binaries were produced by the same build invocation (same Makefile / CMake / batch script) on May 15 2026 at 06:16:29 UTC. ^[pefile.txt:39] - Self-description paradox: The
.rdatastring block contains the text "Application launcher v1.0", "Initialization sequence: load -> resolve -> dispatch -> exit", and status-code definitions (OK=0, MODULE_NOT_FOUND=1, ENTRY_NOT_FOUND=2). For a 4 KB stub this is unusually verbose and readable — the author either does not expect static analysis or is testing detection pipelines with obvious keywords. ^[strings.txt:9-13] .pkosection name: The code section is named.pkoinstead of the standard.text. This is not a normal MinGW/GCC default; it was renamed post-link or via a custom linker script. It serves as a minor fingerprint for this build cluster. ^[pefile.txt:84]- High null-padding: File size is exactly 4,096 bytes (one page), yet ~45% is null padding, and
pefilewarns that "Byte 0x00 makes up 64.5% of the file's contents." This is consistent with a minimal object file padded to the nearest alignment boundary. ^[pefile.txt:3] - No TLS, no exceptions, no bound imports: The PE is stripped to the absolute essentials — no debug directory, no bound imports, no load config, no COM descriptor. The only data directory present is imports, resources (XML manifest), and base relocations. ^[pefile.txt:224-273]
How To Mess With It (Homelab Replication)
Toolchain: MinGW-w64 i686-posix-dwarf-rev0 GCC 13.x/15.x with GNU ld 2.44 Target: PE32 executable, Windows GUI subsystem
- Write a minimal C launcher:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShow) {
DWORD sm = GetSystemMetrics(0);
HWND desk = GetDesktopWindow();
DWORD gate = sm ^ (DWORD)desk ^ 0x41;
HMODULE hMod = LoadLibraryA("core.dll");
if (!hMod) return 1;
typedef void (*MainCall_t)(LPCSTR);
MainCall_t MainCall = (MainCall_t)GetProcAddress(hMod, "MainCall");
if (!MainCall) { FreeLibrary(hMod); return 2; }
MainCall(lpCmdLine ? lpCmdLine : "");
FreeLibrary(hMod);
return 0;
}
- Compile with:
i686-w64-mingw32-gcc -mwindows -s -o launcher.exe launcher.c
- Rename
.textto.pkowith a hex editor orobjcopy:
objcopy --rename-section .text=.pko launcher.exe
- Verification: Run
rabin2 -I launcher.exeand confirmlang: c, linker 2.44, 7 sections, and 5 imports matching the profile. Comparessdeepoutput to the sample (expect identical match on a near-clone).
Deployable Signatures
YARA — MinGW Launcher Stub
rule unclassified_pe32_nfe_loader_launcher : loader {
meta:
description = "4 KB MinGW launcher stub loading core.dll / MainCall"
author = "Titus"
date = "2026-06-06"
sha256 = "ac20be185f5e5d931516336e80d7c3fd3adda6519418877de50181acf6986873"
strings:
$s1 = "core.dll" ascii wide
$s2 = "MainCall" ascii wide
$s3 = "Application launcher v1.0" ascii
$s4 = "Initialization sequence: load -> resolve -> dispatch -> exit" ascii
$s5 = "GCC: (i686-posix-dwarf-rev0, Built by MinGW-Builds project) 15.1.0" ascii
$s6 = "Status codes: OK=0, MODULE_NOT_FOUND=1, ENTRY_NOT_FOUND=2" ascii
condition:
uint16(0) == 0x5A4D and
filesize < 8KB and
(pe.imports("KERNEL32.dll", "LoadLibraryA") and
pe.imports("KERNEL32.dll", "GetProcAddress") and
pe.imports("USER32.dll", "GetSystemMetrics") and
pe.imports("USER32.dll", "GetDesktopWindow")) and
3 of ($s*)
}
Sigma — Small PE Loading core.dll
title: MinGW Launcher Stub Loading core.dll
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 7
ImageLoaded|endswith: 'core.dll'
Image|endswith:
- '.exe'
filter:
- ImageSize|lt: 8192
condition: selection and filter
falsepositives:
- Legitimate custom launchers named core.dll (very rare)
level: high
IOC List
| Indicator | Value | Type |
|---|---|---|
| SHA-256 | ac20be185f5e5d931516336e80d7c3fd3adda6519418877de50181acf6986873 |
Hash |
| Filename | jotkyalz.exe |
Filename |
| DLL target | core.dll |
String |
| Export target | MainCall |
String |
| Compiler | MinGW-Builds GCC 15.1.0 i686-posix-dwarf-rev0 | Toolchain |
| Compilation | 0x6A06BA3D (Fri May 15 06:16:29 2026 UTC) |
Timestamp |
| Section name | .pko |
PE section |
Behavioral Fingerprint
This binary is a minimal PE32 (< 8 KB) with exactly five imports: LoadLibraryA, GetProcAddress, FreeLibrary from KERNEL32.dll, and GetDesktopWindow, GetSystemMetrics from USER32.dll. On execution it probes the desktop environment, loads a companion DLL named core.dll, resolves the export MainCall, and transfers control. No file writes, no registry changes, and no network traffic occur from the launcher itself — all behavior is delegated to the loaded DLL.
Detection Signatures
| ATT&CK ID | Technique | Evidence |
|---|---|---|
| T1105 | Ingress Tool Transfer | Loads core.dll as second-stage payload |
| T1129 | Shared Modules | Reflective / standard LoadLibraryA → GetProcAddress → call chain |
| T1497.001 | System Checks | GetSystemMetrics(0) + GetDesktopWindow() probe before payload load |
| T1027.002 | Software Packing | Stripped minimal PE with non-standard .pko section name |
References
- SHA-256:
ac20be185f5e5d931516336e80d7c3fd3adda6519418877de50181acf6986873 - Family: unclassified-pe32-nfe-loader
- Sibling analysis: /intel/analyses/ded59ec4522cc19e2ae926ba1938452f70d8739d687154b9150141dc79af294c.html
- OpenCTI artifact:
382964fc-b02a-49b6-adc6-f24d84833ff1
Provenance
file.txt—filecommand output (PE32 executable)pefile.txt— pefile parser (timestamps, sections, imports, directories)strings.txt—stringsextraction (ASCII/UTF-16 printable strings)rabin2-info.txt— radare2rabin2 -Iheader summaryr2:entry0— radare2 decompilation of entry point at0x18001060exiftool.json— ExifTool PE metadatabinwalk.txt—binwalk -Eentropy scan (no embedded archives)triage.json— Triage pipeline metadata (deep tier, no family attribution)floss.txt— flare-floss run failed (tool invocation error, no decoded strings)capa.txt— flare-capa run failed (missing signature database)- Tool versions: radare2 (latest stable as of 2026-06-06), pefile, binwalk, ExifTool 12.76