SHA-256:
abeaa63ba93f483c272b28670da91c5eee81aa8153b338da39e88504e6064e86maskgramstealer: abeaa63b — MinGW-w64 PE64 infostealer with runtime API resolution and wallet-seed regex
Executive Summary
A 174 KB PE32+ x64 console binary, sibling to unclassified-pe64-clipper (af6e1f46). Same build fingerprint (MinGW-w64 binutils 2.41), same hardcoded Telegram user ID user_1779580244692, identical wallet regex, and shared screenshot-capture logic. Adds a custom in-memory PE parser + export-hash API resolver (FUN_004069c0) that dynamically resolves FindFirstFileW, FindNextFileW, and other imports at runtime via encoded name tables. Static-only — no CAPE detonation available.
What It Is
- Format: PE32+ x86-64, 7 sections, stripped, unsigned, no exports ^[file.txt] ^[pefile.txt:32-39] ^[rabin2-info.txt]
- Toolchain: MinGW-w64 GCC (LinkerVersion 2.41 / binutils 2.41) ^[pefile.txt:44-46] ^[rabin2-info.txt:17-18]
- Timestamp: 2026-05-25 15:57:41 UTC — fabricated, ingested 2026-06-01 ^[pefile.txt:34]
- IAT (static): KERNEL32.dll + USER32.dll only. Key file-system and injection APIs are runtime-resolved. ^[pefile.txt:228-309]
- Notable static imports:
CreateRemoteThread,WriteProcessMemory,VirtualAllocEx,VirtualProtectEx,OpenProcess^[strings.txt:268-274] - Signing: None ^[rabin2-info.txt]
How It Works
Runtime API Resolution
FUN_004069c0— custom in-memory PE export hash resolver. Parses the on-disk image of a target DLL, hashes export names with a FNV-1a-like routine (hash = hash * 0x21 + byte), then compares against a hardcoded 32-bit seed to locate the desired export RVA. Re-implementsGetProcAddresswithout string equality. ^[ghidra:FUN_004069c0] ^[r2:fcn.004069c0]FUN_00421b00— string decryptor. XOR-like substitution using a 16-byte rolling key (0xd9multiplier +0x39addend) followed by a second LUT pass. Decodes DLL and API names that are later fed toLoadLibraryA/GetProcAddress. ^[ghidra:FUN_00421b00]FUN_004113f0— initialization routine that loadsKERNEL32.dll, decodes ~20 API names viaFUN_00421b00, resolves them withGetProcAddress, and stores pointers in.bssglobals (DAT_00426900,DAT_004267d0, etc.). Confirmed resolved APIs includeFindFirstFileW,FindNextFileW,MultiByteToWideChar,WideCharToMultiByte,GetFileAttributesExW. ^[ghidra:FUN_004113f0]
Collection
- Scans
%DESKTOP%|%DOWNLOADS%|%DOCUMENTS%(and%MUSIC%|%VIDEOS%|%PICTURES%) for files matching*wallet*|*seed*|*mnemonic*|*phrase*|*backup*|*recovery*|*12words*|*24words*. ^[strings.txt:280] ^[strings.txt:285-291] FUN_00411c30splits the wallet regex on|and tests each pattern against discovered filenames. ^[ghidra:FUN_00411c30]- Captures screenshot as
screenshot.jpg. ^[strings.txt:275] - Harvests
MachineGuidfromSOFTWARE\Microsoft\Cryptography. ^[strings.txt:105-109] GetUserNameWfor username enumeration. ^[strings.txt:293]browser:and[BLOB:fragments suggest clipboard/browser data capture. ^[strings.txt:276-277]
Process Injection / Evasion
- Static imports include the full cross-process injection toolkit:
CreateRemoteThread,WriteProcessMemory,VirtualAllocEx,VirtualProtectEx,OpenProcess. ^[strings.txt:268-274] - No anti-VM, anti-debug, or packed sections.
.textentropy normal for uncompressed native code. ^[pefile.txt:91-92,131-132]
C2 / Exfiltration
- Hardcoded Telegram-style identifier
user_1779580244692referenced twice in.rdata. ^[strings.txt:278,294] - Chrome User-Agent string with runtime version substitution (
%d.0.0.0). ^[strings.txt:283] - No static URL, IP, or bot token visible. C2 protocol inferred as Telegram Bot API or HTTPS POST.
Deploy / TTPs
| Technique | ID | Evidence |
|---|---|---|
| Data from Local System | T1005 | %DESKTOP%, %DOWNLOADS%, %DOCUMENTS% enumeration ^[strings.txt:285-291] |
| Screen Capture | T1113 | screenshot.jpg ^[strings.txt:275] |
| Steal Crypto Wallet | T1649 | Wallet seed-phrase regex ^[strings.txt:280] |
| Process Injection | T1055 | CreateRemoteThread, WriteProcessMemory, VirtualAllocEx ^[strings.txt:268-274] |
| Application Layer Protocol: Web Protocols | T1071.001 | Chrome UA; Telegram user ID ^[strings.txt:283,278] |
| System Information Discovery | T1082 | MachineGuid, GetUserNameW, GetComputerNameA ^[strings.txt:105-109], ^[strings.txt:293] |
| Credentials in Files | T1552.001 | Wallet regex file scanning ^[strings.txt:280] |
| Clipboard Data | T1115 | browser: , [BLOB: fragments ^[strings.txt:276-277] |
C2 Infrastructure
| Indicator | Value | Notes |
|---|---|---|
| Telegram user ID | user_1779580244692 |
Hardcoded ^[strings.txt:278,294] |
| User-Agent | Mozilla/5.0 ... Chrome/%d.0.0.0 Safari/537.36 |
Hardcoded ^[strings.txt:283] |
| C2 URL/IP | Not present | Runtime-decoded or absent |
| Bot token | Not present | Not in static artifacts |
Siblings & Attribution
- unclassified-pe64-clipper (
af6e1f4644b2e1e2a9c269d3acbd2faa1ea3facb9b68829c6f6a93a34ddb9c44) — direct sibling: same toolchain, sameuser_1779580244692, same wallet regex, same directory targets, same Chrome UA, same screenshot.jpg. Differences:abeaa63badds the in-memory PE export-hash resolver (FUN_004069c0), whereasaf6e1f46resolves API names with plainGetProcAddressafter XOR-loop decoding. - Family attribution: maskgramstealer (per triage pipeline label). Confidence
medium— no open-source reporting on this name yet; cluster is defined by static overlap.
Interesting Tidbits
- The export-hash resolver (
FUN_004069c0) walks the PE Export Directory manually, hashes every name starting withZw(kernel-mode prefix) to build a sorted lookup table, then binary-searches for the target hash. This is an unusual hybrid: it prepares a table ofZw*exports but the actual search is generic — any hash can be queried. Likely borrowed from a loader or shellcode template. ^[ghidra:FUN_004069c0] entry0starts by zeroing the.bsssection with a rep-stosb-like loop (emulated viawhilezero-write) before calling CRT initializers. Clean startup, no obfuscation in the entry path itself. ^[r2:entry0]- No CAPE detonation. Windows guest unavailable at time of ingestion. All behavior inferred from static and decompilation.
How To Mess With It (Homelab Replication)
Toolchain: MinGW-w64 GCC 13.x, binutils 2.41, target x86_64-w64-mingw32, subsystem CONSOLE.
x86_64-w64-mingw32-gcc -O2 -s -static-libgcc -static-libstdc++ \
stealer.c -o reproducer.exe -lws2_32
Verification: file reproducer.exe → PE32+ executable (console) x86-64 (stripped to external PDB).
Deployable Signatures
YARA — MaskgramStealer
rule MaskgramStealer : infostealer {
meta:
description = "Detects maskgramstealer family by wallet regex and Telegram user ID"
author = "PacketPursuit"
date = "2026-06-01"
sha256 = "abeaa63ba93f483c272b28670da91c5eee81aa8153b338da39e88504e6064e86"
strings:
$wallet_regex = "*wallet*|*seed*|*mnemonic*|*phrase*|*backup*|*recovery*|*12words*|*24words*" ascii wide
$telegram_id = "user_1779580244692" ascii wide
$ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" ascii wide
$screenshot = "screenshot.jpg" ascii wide
$machineguid = "MachineGuid" ascii wide
condition:
uint16(0) == 0x5A4D and
$wallet_regex and
3 of them
}