Pipeline Stage 6

Unpacked Content
Scanning

Recursive scanning of emulator output: modified sections + VFS drops

25+Static Unpackers
6UPX Variants
10PECompact Decrypters
8Control Attributes

Engine.Scan.Unpacker @ 0x109C6068 — HandleUnpacker @ 0x10C92DC8

What Gets Unpacked?

After PE emulation, two categories of content are extracted for recursive scanning

Modified PE Sections

During emulation, the malware decrypts or decompresses its payload by overwriting its own PE sections. The engine detects these modifications by comparing each section's current state against the original image.

Detection criteria: - Write ops to executable sections (.text) - Large-scale overwrites (decryption loops) - New code in zero-filled regions - VirtualProtect to PAGE_EXECUTE via VirtualProtectCallback @ 0x10C7B7B0

VFS Dropped Files

Dropper malware writes payloads to disk via CreateFileW/WriteFile. The emulator intercepts these calls and stores the data in a Virtual File System.

VFS string references: "(VFS:%ls#%zd)" @ 0x10B87920 "(VFS:...%ls#%zd)" @ 0x10B8790C "(VFS:#%zd)" @ 0x10B87900 "NDAT_VFS_LINK" @ 0x109811F8 "VFSParams" @ 0x10B76888

Unpack Pipeline Flow

Static unpackers run first, then emulation-based unpacking, then VFS extraction

Emulation Done
HandleUnpacker
Static Unpackers
Modified Sections
VFS Drops
Recursive Scan
Recursive Target: Stage 2 Unpacked content re-enters full pipeline
Depth Limited scan_depth counter prevents infinite recursion

Static Unpackers: 25+ Classes

Format-specific unpackers recognized via RTTI in the binary

UPX Family (6 variants)

UpxwUnpacker @ 0x10C92FA0
Upxw896Unpacker @ 0x10C92FBC
Upxw60Unpacker @ 0x10C92FDC
Upx30LZMAUnpacker @ 0x10C930C4

Petite Family (5 variants)

CPetiteUnpacker @ 0x10C93480
CPetite12-14/21-23 5 version-specific classes

PECompact Family (4 variants)

CPECompact2 @ 0x10C93560
CPECompact2V250 @ 0x10C935E4 (10 decrypters)

Other Unpackers

AspackUnpacker @ 0x10C942B4
FSGUnpacker @ 0x10C94040
ShrinkerUnpacker @ 0x10C932F8
JDPack/PKLite/Area51... 12+ more format-specific

PECompact 2.50: 10 Decrypter Algorithms

The most complex static unpacker, with dedicated decrypter classes for each encryption variant

CRC32CRC32-keyed
CryptGeneric crypto
XORXOR cipher
MsgBoxMessageBox trick
Rnd5Random polymorph
DECADA82DECADA82 algo
Cod1Cod1 algorithm
VerifyCRC verify
InvertBit inversion
WinCryptCryptoAPI
// RTTI from CPECompact2V250Unpacker nested classes: .?AVCVersion20x_21xCRC32Decrypter@...CPECompact2V20x_21xUnpacker@@... .?AVCCryptDecrypter@...Crypt@CPECompact2V250Unpacker@@... .?AVCXorDecrypter@...Xor@CPECompact2V250Unpacker@@... .?AVCMessageBoxDecrypter@...ProcessMessageBox@CPECompact2V250Unpacker@@... .?AVCRnd5Decrypter@...Rnd5Polymorph0@CPECompact2V250Unpacker@@... .?AVCDECADA82Decrypter@...DecryptDECADA82@CPECompact2V250Unpacker@@... .?AVCWincryptDecryptor@...WinCrypt@CPECompact2V250Unpacker@@...

Unpacking Control Attributes

Attributes and NID tokens that configure unpacking behavior

Scan Attributes

force_unpacking @ 0x109852D4
disable_static_unpacking @ 0x10984AE8
dt_continue_after_unpacking @ 0x10984D1C
dt_continue_..._damaged @ 0x10984D38
disable_dropper_rescan @ 0x10984A90

PE-specific Variants

pea_force_unpacking @ 0x10A11570
pea_disable_static_unpacking @ 0x10A110B8
pea_dt_continue_after_unpacking @ 0x10A11A88
pea_dt_continue_..._damaged @ 0x10A11B28
pea_disable_dropper_rescan @ 0x10A11014

NID Control Tokens

VDM database-level controls for the unpacking subsystem

"NID_DT_CONTINUE_AFTER_UNPACKING" @ 0x10980A7C Continue scanning after unpack completes "NID_DT_CONTINUE_AFTER_DAMAGED_UNPACKING" @ 0x10980B5C Continue even if unpacked data is corrupted "NID_DT_DISABLE_STATIC_UNPACKING" @ 0x10980C30 Skip all static unpackers (UPX, PECompact, etc.) "NID_DT_ENABLE_STATIC_UNPACKING" @ 0x10980C50 Re-enable static unpackers if disabled

Error Handling

"Failed to unpack %s" @ 0x10B6D70C "failed decompress unpacker code" @ 0x10B79514 "failed to copy EP instruction series" @ 0x10B794EC "failed to make jump instruction" @ 0x10B795C8 "too many results to unpack" @ 0x10B54704

HandleUnpacker Entry Point

The main dispatch function for Stage 6, revealed through RTTI analysis

// RTTI reveals function signature: .?AUUnpackContextWrapper@?DJ@??HandleUnpacker@@YA?AW4scanresult_t@@PAUpe_vars_t@@@Z@ @ 0x10C92DC8 // Decoded: scanresult_t HandleUnpacker(pe_vars_t* pe_vars) // Pseudocode (reconstructed): fn HandleUnpacker(pe_vars: &PeVars) -> ScanResult { // Phase 1: Static unpackers if !disabled_static { result = try_static_unpackers(pe_vars); } // Phase 2: Modified section detection for section in pe_vars.sections { if section.was_modified() { recursive_scan(section.data, depth+1); } } // Phase 3: VFS dropped files if !disable_dropper_rescan { for vfs in emu_ctx.vfs.entries() { recursive_scan(vfs.data, depth+1); } } result }

ETW Event

Engine.Scan.Unpacker @ 0x109C6068 — ETW trace event

AMUnpacker

amunpacker @ 0x109C7F34 — anti-malware unpacker subsystem

Recursive Path

Stage 5 (Emu) ↓ Stage 6 (Unpack) ↓ Stage 2 (FRIENDLY) ↓ Stage 3+ (full pipeline) ↓ depth check prevents infinite recursion

XZ Stream Decompression

Specialized decompression path for XZ-compressed payloads

RTTI Classes

// xz_unpack_helper nested classes XZReader @ 0x10C91DB0 XZWriterAdaptor @ 0x10C91E10 XZReaderAdaptor @ 0x10C91E60 Canceler @ 0x10C91AD0 VfoWrapper @ 0x10C91D50 // Top-level decompressor DecompressXZStream via unpackdata_t structure

How It Works

When the emulator or static analysis detects an XZ-compressed stream, the dedicated XZ decompression path handles it separately from the general emulation-based unpacking.

The Canceler class provides timeout support, and the VfoWrapper wraps virtual file objects for decompressed output.

SCAN_REPLY Decompressed data fed back through scan pipeline

Stage 6 Summary

25+Static Unpacker Classes
6UPX Variants
10PECompact Decrypters
5Petite Variants
8Control Attributes
4NID Control Tokens
5Error Strings
1ETW Event

All data from reverse engineering mpengine.dll v1.1.24120.x

← Stage 5 PE Emulation
Stage 7 → Container Extraction