Pipeline Stage 5

PE Emulation

x86/x64/ARM CPU emulator with 198 WinAPI handlers

0WinAPI Handlers
0Virtual DLLs
67FPU Exports
5MInstruction Budget

RTTI: .?AVx86_IL_emulator@@ @ 0x10C748CC — .?AVIL_emulator@@ @ 0x10C74B6C

Emulator Architecture

Three CPU architectures, one unified emulation framework

RTTI Class Hierarchy

IL_emulator (abstract base) @ 0x10C74B6C │ ├── x86_IL_emulator │ @ 0x10C748CC32-bit x86 + FPU + SSE │ ├── x86_64_IL_emulator64-bit extension (from sig types) │ └── ARM_IL_emulator @ 0x10C921C8 ARM 32-bit instructions
SSE_convert @ 0x10267CF0 SSE conversion export

Supporting Classes

vdll_data_t @ 0x10C7C940
VirtualProtectCallback @ 0x10C7B7B0
PEUnpacker @ 0x10C7F6D4
UnpackerContext @ 0x10C79618
UnpackerData @ 0x10C852A4
VirtualAllocation @ 0x10C7B360 (Ref_count_obj2)

Virtual Memory Layout

Synthetic address space for emulated PE execution

0x00010000 Stack — ESP initialized, grows downward
0x00020000 TEB / PEB — Thread & Process Environment Blocks (synthetic)
0x00030000 LDR Data — Loader structures, module linked list
0x00400000 PE Image — Scanned file mapped at ImageBase
0x10000000 Heap — VirtualAlloc / malloc allocations
0x70000000 VDLLs — 973 virtual DLLs (kernel32, ntdll, user32, ...)
0x7FFE0000 Trampolines — API handler dispatch stubs
0xDEADBEEF Stop Sentinel — Execution terminates at this address

FPU Emulation: 67 Exports

Full x87 floating-point emulation via real exported functions from mpengine.dll

Arithmetic

FPU_fadd @ 0x10266C50 FADD FPU_fsub @ 0x10266ED0 FSUB FPU_fmul @ 0x102670D0 FMUL FPU_fdiv @ 0x10266FD0 FDIV FPU_fsqrt @ 0x10267570 FSQRT FPU_fabs @ 0x10267340 FABS FPU_fchs @ 0x102672D0 FCHS

Transcendental

FPU_fsin @ 0x10267650 FSIN FPU_fcos @ 0x102676C0 FCOS FPU_fptan @ 0x10267500 FPTAN FPU_fpatan @ 0x10267950 FPATAN FPU_f2xm1 @ 0x10267490 2^x-1 FPU_fyl2x @ 0x10267730 y*log2(x)

Load / Store

FPU_fld_single @ 0x10266450 32-bit FPU_fld_double @ 0x102664C0 64-bit FPU_fld_ext @ 0x10266530 80-bit FPU_fild_s16 @ 0x102665A0 16-bit int FPU_fild_s32 @ 0x10266610 32-bit int FPU_fild_s64 @ 0x10266680 64-bit int FPU_fbld @ 0x102666F0 BCD load

Constants

FPU_fld1 @ 0x102679E0 1.0 FPU_fldpi @ 0x10267B30 pi FPU_fldl2e @ 0x10267AC0 log2(e) FPU_fldln2 @ 0x10267C10 ln(2) FPU_fldz @ 0x10267C80 0.0

198 Emulated WinAPI Handlers

Intercepted API calls provide behavioral telemetry and controlled execution

API Handler Flow

Emulated code @ 0x00400000+ │ │ CALL [IAT entry] ▼ VDLL stub @ 0x70000000+ │ │ JMP [trampoline] ▼ Trampoline @ 0x7FFE0000+ │ │ Host-side dispatchNative handler in mpengine.dll 1. Read params from emu stack 2. Simulate API behavior 3. Record in API log 4. Write return to EAX 5. Return to emulator

Selected API Strings

VirtualAlloc @ 0x10C6B4F6
VirtualProtect @ 0x10C6BA2A
VirtualProtectEx @ 0x10C6CE14
CreateFileW @ 0x10C6B562
CreateFileMappingW @ 0x10C6B710
LoadLibraryA @ 0x10C6B78E
LoadLibraryW @ 0x10C6BDA8
LoadLibraryExW @ 0x10C6B458

Execution Engine

Fetch-decode-execute loop with 5M instruction budget in ~1,000 instruction batches

fn emulate_main_loop(ctx: &mut EmuContext) { let mut insn_count: u32 = 0; let max_insns = 5_000_000; // DBVAR let batch = 1_000; loop { // Execute batch of ~1,000 instructions execute_batch(ctx, batch); insn_count += batch; // Stop sentinel check if ctx.regs.eip == 0xDEADBEEF { break; } // Budget exhausted if insn_count >= max_insns { // "abort: execution limit met" // @ 0x109334D8 break; } // API trampoline dispatch if ctx.regs.eip >= 0x7FFE0000 { handle_api_call(ctx); } // FPU routing if ctx.optype == FPU_RM { execute_fpu(ctx); } } }

Execution Limits

5M Instruction Budget
"abort: execution limit met (%u instructions)" @ 0x109334D8 "Infinite loop detected (more that %d instructions executed)" @ 0x10983320

Re-emulation

"reemulate" @ 0x10981878 "MpReemulate" @ 0x10B76A08

Behavioral Recording

FOP, TUNNEL, and THREAD signatures capture runtime behavior patterns

FOP Signatures

First Opcode Profile — captures first N unique opcode sequences from entry point. Architecture-independent behavioral fingerprint.

SIGNATURE_TYPE_FOP @ 0x10986C44 SIGNATURE_TYPE_FOP64 @ 0x109871BC SIGNATURE_TYPE_FOPEX @ 0x10986514 SIGNATURE_TYPE_FOPEX64 @ 0x10986C70 SIGNATURE_TYPE_VBFOP @ 0x10986074 SIGNATURE_TYPE_MSILFOP @ 0x10986BCC
0 FOP Rules in VDM

TUNNEL Signatures

Detect code-flow patterns between entry point and first API call. The "tunnel" is the decryption/unpacking stub.

SIGNATURE_TYPE_TUNNEL_X86 @ 0x109860A4 SIGNATURE_TYPE_TUNNEL_X64 @ 0x10986344 SIGNATURE_TYPE_TUNNEL_ARM @ 0x10986460 SIGNATURE_TYPE_TUNNEL_ARM64 @ 0x1098713C
4 Architecture Variants

THREAD Signatures

Detect multi-threaded behavior patterns during emulation. Thread creation and synchronization profiles.

SIGNATURE_TYPE_THREAD_X86 @ 0x109860F4 SIGNATURE_TYPE_THREAD_X64 @ 0x1098703C SIGNATURE_TYPE_THREAD_ARM @ 0x10986B00 SIGNATURE_TYPE_THREAD_ARM64 @ 0x10986B58
4 Architecture Variants

Virtual DLL System

973 VDLLs (750 x86 + 195 x64 + 18 ARM + 10 MSIL) mapped at 0x70000000+ provide realistic API stubs

Import Resolution Flow

// PE imports "kernel32!VirtualAlloc" 1. Find kernel32.dll in 973 VDLL list 2. Resolve VirtualAlloc from VDLL exports 3. Patch IAT entry → VDLL stub address 4. VDLL stub jumps to trampoline 5. Trampoline dispatches to native handler // Symbolic info for resolution: "SIGNATURE_TYPE_VDLL_SYMINFO" @ 0x1098614C

VDLL Control Strings

isvdllbase @ 0x109819CC
isvdllimage @ 0x109819D8
reads_vdll_code @ 0x10985924
dynmem_reads_vdll_code @ 0x10984F48
verbose_vdll_reads @ 0x10985DE8
NDAT_VFS_LINK @ 0x109811F8

Emulation Control

Attributes and NID tokens that control emulation behavior

Scan Attributes

"force_unpacking" @ 0x109852D4 "disable_static_unpacking" @ 0x10984AE8 "dt_continue_after_unpacking" @ 0x10984D1C "dt_continue_after_unpacking_damaged" @ 0x10984D38 "pea_force_unpacking" @ 0x10A11570 "pea_disable_static_unpacking" @ 0x10A110B8

NID Control Tokens

"NID_DT_CONTINUE_AFTER_UNPACKING" @ 0x10980A7C "NID_DT_CONTINUE_AFTER_DAMAGED_UNPACKING" @ 0x10980B5C "NID_DT_DISABLE_STATIC_UNPACKING" @ 0x10980C30 "NID_DT_ENABLE_STATIC_UNPACKING" @ 0x10980C50 "NID_DT_SKIP_UNIMPLEMENTED_OPCODES" @ 0x10980A9C "NID_DT_DISABLE_MICROCODE" @ 0x10980C8C "NID_DT_ENABLE_MICROCODE" @ 0x10980CA8 "NID_DISABLE_THREAD_API_LIMITS" @ 0x10980CDC

Exception Handling & Process Environment

Full SEH/VEH/x64 exception dispatch plus realistic TEB/PEB environment to defeat sandbox detection

Exception Handling (3 modes)

VEH Vectored Exception Handlers checked first (AddVectoredExceptionHandler)
SEH (x86) Walk chain from TEB[0x00] (FS:[0]). Up to 32 frames. Return sentinel 0xDEADC0DE
x64 Table RUNTIME_FUNCTION binary search + UNWIND_INFO with UNW_FLAG_EHANDLER

CryptAPI & BCrypt

CryptAPI AcquireContext, CreateHash, DeriveKey, Decrypt/Encrypt (RC4, AES-CBC/ECB)
BCrypt OpenAlgorithmProvider, GenerateSymmetricKey (AES, RC4, SHA-256)

TEB/PEB Fake Environment

// Defeats sandbox detection: PEB.BeingDebugged = 0 PEB.NtGlobalFlag = 0 PEB.ImageBaseAddress = loaded PE base PEB.Ldr = PEB_LDR_DATA // Fake process parameters: ComputerName: HAL9TH UserName: JohnDoe ImagePath: C:\Users\JohnDoe\ Desktop\target.exe CurrentDir: C:\Windows\System32\ SystemRoot: C:\Windows
3 Module Lists InLoadOrder, InMemoryOrder, InInitializationOrder — populated with target PE + VDLLs

VFS: Virtual File System

Files written by emulated code are captured and scanned in Stage 6

// Emulated malware calls: CreateFileW(L"C:\\payload.exe", ...); WriteFile(hFile, decrypted_data, size, ...); CloseHandle(hFile); // Emulator intercepts and routes to VFS: // Data stored in virtual filesystem // Filename tracked for context // After emulation completes (Stage 6): for vfs_entry in emu_ctx.vfs.entries() { // "(VFS:%ls#%zd)" @ 0x10B87920 recursive_scan(vfs_entry.data, depth + 1); } // VFS string references: "NDAT_VFS_LINK" @ 0x109811F8 "VFSParams" @ 0x10B76888 "(VFS:%ls#%zd)" @ 0x10B87920 "(VFS:...%ls#%zd)" @ 0x10B8790C "(VFS:#%zd)" @ 0x10B87900

Why VFS Matters

Many malware samples are droppers — their only purpose is to decrypt and write the real payload to disk. The VFS captures these dropped files before they touch the real filesystem.

Stage 6 Unpacked Content scans VFS drops
disable_dropper_rescan @ 0x10984A90 — can skip VFS scan

Stage 5 Summary

0WinAPI Handlers
0Virtual DLLs
67FPU Exports
5MInstruction Budget
0FOP Rules
3CPU Architectures
0PE Attributes
8NID Control Tokens

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

← Stage 4 Attribute Collection
Stage 6 → Unpacked Content