0b6a849a68a48f7301c3459a7771378e458e2d5debce9376be350784c61b72b7unclassified-pe32plus: 0b6a849a — 5.9 MB MSVC C++ PE32+ with TLS callbacks, empty C2 footprint
Executive Summary
OpenCTI and MalwareBazaar co-labeled this sample hippamsascom / sunwukong. Structural analysis shows this is a false-positive attribution. The binary diverges from confirmed hippamsascom siblings on every build/RE axis: 12× larger .text, standard populated IAT (not empty), no semantic export obfuscation, no masquerade version info, C++ STL runtime, and a TLS callback array with 8 entries. Static IOCs are absent; no C2 strings, no certificate artifacts, no registry or mutex indicators. CAPE detonation skipped (no Windows guest). Family classification remains unclassified-pe32plus.
What It Is
| Property | Value |
|---|---|
| SHA-256 | 0b6a849a68a48f7301c3459a7771378e458e2d5debce9376be350784c61b72b7 |
| File name | s_folder.exe ^[triage.json] |
| Type | PE32+ executable (GUI) x86-64, 7 sections ^[file.txt] |
| Size | 5,889,536 bytes (^5.6 MB) ^[triage.json] |
| Compiled | Wed May 6 15:42:39 2026 UTC ^[rabin2-info.txt] |
| Linker | MSVC 14.41 (VS 2022) ^[exiftool.json] |
| Language | C++ (MSVC CRT + STL exception framework) ^[strings.txt:1431-1437] ^[rabin2-info.txt] |
| Signed | No ^[rabin2-info.txt] |
| Stripped | No (debug symbol absent, but unwind pdata present) ^[rabin2-info.txt] |
| capa | Failed — missing signature database ^[capa.txt] |
| CAPE | Skipped — no Windows machine available ^[dynamic-analysis.md] |
Section inventory:
| Section | RVA | Raw size | Entropy | Notes |
|---|---|---|---|---|
.text |
0x1000 | 0x4f7200 | 5.32 | 5.2 MB — massive; minimal recoverable strings ^[pefile.txt:77-95] |
.rdata |
0x4f9000 | 0x48400 | 6.03 | Import name table, C++ RTTI, TLS directory ^[pefile.txt:97-115] |
.data |
0x542000 | 0xE00 | 2.01 | Tiny ^[pefile.txt:117-135] |
.pdata |
0x549000 | 0x2400 | 5.67 | Exception unwind data ^[pefile.txt:137-155] |
.fptable |
0x54c000 | 0x200 | 0.00 | Function pointer table (all nulls per raw dump) ^[pefile.txt:157-175] |
.reloc |
0x54d000 | 0x800 | 4.97 | Base relocation data ^[pefile.txt:177-195] |
.rsrc |
0x54e000 | 0x5a800 | 3.42 | 6 icon groups; no RT_VERSION ^[pefile.txt:197-215] |
Key divergence from hippamsascom cluster: confirmed siblings (e.g. 0c9e772d, 9a3c18be) are ~400–500 KB, have empty IATs, semantic-jargon-export-obfuscation, masquerade VS_VERSIONINFO (Emard LLC / Littel LLC), and custom PEB-walking API resolution. This sample has a standard import table, no exports, no masquerade, and a standard MSVC CRT entry. ^[pefile.txt:268-358], ^[sample 0c9e772d/pefile.txt]
How It Works
Static-only inference — no CAPE runtime data, no floss/capa.
-
TLS callbacks fire before CRT main. The PE contains a
IMAGE_DIRECTORY_ENTRY_TLSwithAddressOfCallBacks = 0x1404f9338^[pefile.txt:247-248]. Eight callback entries are present in the array ^[dump_tls.py]. This is a known evasion/anti-debug vector: code executes before analyst breakpoints can be set on CRT main ^[techniques/tls-callback-anti-analysis]. -
Standard MSVC C++ CRT startup. Entry point (
0x1404e8cb4) follows the post-VS-2015 pattern:sub rsp, 0x28→call __security_init_cookie→jmp __scrt_common_main_seh^[r2:entry0]. The latter initializes the CRT heap, exception chain, and locale, then dispatches to the actualmainstub at0x1402effa0with args(argc=0, argv=ImageBase, penv). This is normal toolchain output, not a custom self-loader. -
Minimal static strings despite 5.2 MB .text. Only ~1,500 ASCII strings were recovered ^[strings.txt]. This is extremely low for a binary of this size. Possibilities:
- Heavy string encryption or runtime decoding (common in malware)
- Large statically-linked C++ codebase with few human-readable literals
- Most API names resolved dynamically via
LoadLibraryA/GetProcAddress(both imported in IAT) ^[pefile.txt:279,281]
-
.fptablesection at zero entropy. The 0x200-byte.fptableis all nulls in the on-disk image ^[pefile.txt:157-175]. At runtime this region is RWX (0xC0000040). It may serve as a scratchpad for resolved function pointers or unpacked payload segments. -
No external library strings found. Scans for Qt, Boost, OpenSSL, Python, Chromium, Node.js, game engine, crypto library, and network stack signatures returned negative except a single 2-byte
V8hit (insufficient to claim V8 embedding) ^[check_pe_library.py].
Decompiled Behavior
Entry point (0x1404e8cb4) — disassembly via radare2 ^[r2:entry0]:
sub rsp, 0x28
call fcn.1404e93a0 ; __security_init_cookie
add rsp, 0x28
jmp loc.0x1404e8b40 ; __scrt_common_main_seh
__scrt_common_main_seh sets up IsProcessorFeaturePresent, IsDebuggerPresent, QueryPerformanceCounter, then calls the user main stub at 0x1402effa0 with arguments argc=0, argv=0x140000000, penv=0x140543220 ^[r2:entry0].
The main stub (0x1402effa0) could not be reached for full decompilation within analysis timeouts; the function is inside the 5.2 MB .text morass. radare2 level-2 analysis timed out, and Ghidra remained in queued state throughout. Xrefs from entry0 into .text suggest a monolithic codebase with little modular structure.
Notable imported APIs (standard IAT, only KERNEL32.dll):
IsDebuggerPresent— T1622 debugger detection ^[pefile.txt:299]VirtualProtect— runtime page protection changes ^[pefile.txt:349]LoadLibraryA,GetProcAddress— dynamic API resolution for non-KERNEL32 DLLs ^[pefile.txt:279,281]CreateFileW,WriteFile,FindFirstFileExW,FindNextFileW— filesystem interaction ^[pefile.txt]
No ADVAPI32, USER32, SHELL32, WS2_32, or WININET imports are present in the static IAT. This is unusual for a 5.9 MB binary and reinforces the hypothesis that most higher-level APIs are resolved dynamically at runtime.
C2 Infrastructure
- Static IOCs: None. No domains, IPs, URLs, mutex names, named pipes, or registry keys were recovered from strings, resources, or headers.
- Dynamic inference: Not available — CAPE detonation skipped (no Windows guest) ^[dynamic-analysis.md].
- Conclusion: C2 is either fully runtime-resolved (via dynamic API resolution + encrypted config), or this sample is not primarily network-communicative in its current form. The 5.2 MB
.textcould contain payload logic that only activates under specific conditions.
Interesting Tidbits
- Absent masquerade — every confirmed hippamsascom sibling carries a fabricated VS_VERSIONINFO (company name, product name, original filename). This samples
.rsrchas 6 embedded icons but noRT_VERSIONblock at all ^[pefile.txt:360+], ^[check_pe.py]. - Unsigned — confirmed siblings carry fabricated Authenticode (Emard LLC, Hane Group, Littel LLC intermediate CAs). This sample shows
signed: false^[rabin2-info.txt]. - No exports — hippamsascom employs semantic-jargon-export-obfuscation (330 names → 19 unique RVAs). This sample has a zero-length export directory ^[pefile.txt:219-221].
- C++ exception framework —
std::bad_alloc,std::length_error,std::out_of_range,std::logic_error,std::bad_exception,std::bad_array_new_length,std::exception,std::type_info^[strings.txt:1431-1437]. None of the confirmed hippamsascom siblings show STL runtime strings. - fptable section — unique among corpus samples observed to date. The zero-entropy
RWXscratchpad is empty on disk and writable at runtime ^[pefile.txt:157-175]. - TLS callback count — 8 entries is well above the standard MSVC output (0–2). This is a red flag for anti-analysis logic.
How To Mess With It (Homelab Replication)
Goal: Reproduce a MSVC C++ PE32+ with TLS callbacks and minimal IAT to understand pre-main execution timing.
Toolchain: Visual Studio 2022 (v14.3x), x64 Release, C++17.
Steps:
- Create a new C++ Console App in VS 2022.
- In any
.cpp, add a TLS callback:
#pragma comment(linker, "/INCLUDE:__tls_used")
#pragma data_seg(".tls")
#pragma data_seg(".tls$ZZZ")
#pragma data_seg()
#pragma section(".CRT$XLB", read)
extern "C" __declspec(allocate(".CRT$XLB")) PIMAGE_TLS_CALLBACK TlsCallback =
[](PVOID hModule, DWORD Reason, PVOID Reserved) {
if (Reason == DLL_PROCESS_ATTACH) {
// Pre-main code here
OutputDebugStringA("TLS callback fired\n");
}
};
- Build with
/GSand/guard:cfenabled (defaults in Release). - Verify with
rabin2 -I your.exe— look forhavecode true,canary true,pic true. - Dump TLS callbacks:
python3 -c "import pefile; pe = pefile.PE('your.exe'); print([hex(c) for c in pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks])".
What you will learn: TLS callbacks execute before main() — before most EDR user-mode hooks are in place. Malware uses this gap to set up hooks, decrypt config, or terminate if a debugger is detected.
Deployable Signatures
YARA rule
rule Unclassified_LargeTLS_x64_MinimalStrings
{
meta:
description = "Large x64 MSVC binary with TLS callbacks, minimal IAT, no RT_VERSION"
author = "pp-hermes"
date = "2026-05-31"
hash = "0b6a849a68a48f7301c3459a7771378e458e2d5debce9376be350784c61b72b7"
strings:
$mz = { 4D 5A }
$pe = { 50 45 00 00 64 86 }
$debug = "IsDebuggerPresent"
$vprotect = "VirtualProtect"
$std_ex1 = ".?AVbad_alloc@std@@"
$std_ex2 = ".?AVexception@std@@"
condition:
$mz at 0 and
$pe at (uint32(0x3C) + 4) and
uint16(uint32(0x3C) + 0x14) == 0xF0 and // OptionalHeader64
filesize > 5MB and
filesize < 7MB and
pe.number_of_sections == 7 and
pe.sections[0].name == ".text" and
pe.sections[0].raw_size > 0x4A0000 and // .text > 4.8 MB
pe.sections[5].name == ".reloc" and
pe.sections[6].name == ".rsrc" and
pe.tls_callbacks > 0 and
pe.tls_callbacks == 8 and
for any i in (0..pe.number_of_sections - 1): (
pe.sections[i].name == ".fptable"
) and
all of ($debug, $vprotect) and
2 of ($std_ex*)
}
Sigma rule (Process Creation — heuristic)
title: Suspicious Large PE with TLS Callbacks
description: Detects execution of unusually large x64 PE with pre-main TLS callback count > 2
logsource:
category: process_creation
product: windows
detection:
selection:
ParentImage|contains:
- 'explorer.exe'
- 'cmd.exe'
CommandLine|contains:
- 's_folder.exe'
condition: selection
falsepositives:
- Legitimate large C++ applications with complex TLS init
level: low
Note: The above Sigma is placeholder — the static-only sample provides no process-tree or command-line artifacts. A production rule would need runtime telemetry.
IOC list
| Type | Indicator | Notes |
|---|---|---|
| SHA-256 | 0b6a849a68a48f7301c3459a7771378e458e2d5debce9376be350784c61b72b7 |
Primary |
| SHA-1 | 20240c0bdb53f2432d4de31b048cfb206e729027 |
^[pefile.txt:93] |
| MD5 | 9efc1d267d047b1097273cc38cad7851 |
.text hash ^[pefile.txt:92] |
| File name | s_folder.exe |
On-disk name ^[triage.json] |
| PE timestamp | Wed May 6 15:42:39 2026 UTC |
Likely fabricated ^[pefile.txt:34] |
| Entry point | 0x1404e8cb4 |
CRT startup pattern ^[pefile.txt:50] |
| TLS callbacks | 0x1404f9338 → 8 entries |
Array VA ^[dump_tls.py] |
Behavioral fingerprint statement
This sample is a PE32+ x64 MSVC C++ binary with an unusually large .text section (> 5 MB) and a near-empty ASCII string footprint (≈1,500 recoverable strings). The import table is restricted to KERNEL32.dll (61 functions) with IsDebuggerPresent and VirtualProtect imported explicitly. A .fptable RWX section of 512 bytes is present, along with a TLS callback array containing 8 entries — a count well above standard compiler output. No RT_VERSION resource, no export table, and no Authenticode signature. The entry point follows standard VS-2022 CRT startup via __security_init_cookie → __scrt_common_main_seh → main(0, ImageBase, penv).
Detection Signatures
| Capability / Technique | ATT&CK ID | Evidence | Confidence |
|---|---|---|---|
| Debugger Detection | T1622 | IsDebuggerPresent in IAT ^[pefile.txt:299] |
Static — high |
| Obfuscated Files / Information | T1027 | 5.2 MB .text with minimal strings; potential encrypted payload |
Static — medium |
| Software Packing | T1027.002 | .fptable RWX scratchpad; possible in-memory unpacking |
Static — low |
| Native API | T1106 | LoadLibraryA + GetProcAddress for dynamic resolution ^[pefile.txt:279,281] |
Static — high |
| Process Injection — inferred | T1055 | VirtualProtect + RWX .fptable + large .text suggest in-memory payload staging |
Static — low |
| Evade Detection | T1497 | TLS callbacks (8 entries) execute pre-main / pre-hook | Static — medium |
References
- hippamsascom — cluster this sample was falsely co-labeled with; structural differences documented above
- sunwukong — related cluster sharing build traits with hippamsascom (not this sample)
- semantic-jargon-export-obfuscation — technique present in hippamsascom, absent here
- peb-walking-api-resolution — technique present in hippamsascom, absent here
- tls-callback-anti-analysis — technique page for TLS pre-main execution
- Artifact:
malware-bazaar:0b6a849a68a48f7301c3459a7771378e458e2d5debce9376be350784c61b72b7
Provenance
Static analysis performed by pp-hermes on 2026-05-31. Tools used: file (file type), exiftool (metadata), pefile (PE structure), radare2 v5.9.8 (disassembly/decompilation), python3 + pefile library (PE resource/section / TLS parsing), strings (ASCII string extraction), ssdeep (fuzzy hash comparison). capa v7.0.1 failed due to missing rule signatures. floss failed with argument-parsing error. CAPE detonation skipped (no Windows guest available). Ghidra queued but analysis did not complete within session timeout. All observations are static-only where runtime data is absent.