Crash handler
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
void FUN_00401d32(void)
{
code *pcVar1;
uint uVar2;
undefined4 extraout_ECX;
undefined4 extraout_ECX_00;
undefined4 uVar3;
undefined4 extraout_EDX;
undefined4 unaff_EBX;
undefined4 unaff_EBP;
undefined4 unaff_ESI;
undefined4 unaff_EDI;
undefined2 in_ES;
undefined2 in_CS;
undefined2 in_SS;
undefined2 in_DS;
undefined2 in_FS;
undefined2 in_GS;
byte bVar4;
byte bVar5;
byte in_AF;
byte bVar6;
byte bVar7;
byte in_TF;
byte in_IF;
byte bVar8;
byte in_NT;
byte in_AC;
byte in_VIF;
byte in_VIP;
byte in_ID;
undefined8 uVar9;
undefined4 unaff_retaddr;
uVar2 = IsProcessorFeaturePresent(0x17);
uVar9 = CONCAT44(extraout_EDX,uVar2);
bVar4 = 0;
bVar8 = 0;
bVar7 = (int)uVar2 < 0;
bVar6 = uVar2 == 0;
bVar5 = (POPCOUNT(uVar2 & 0xff) & 1U) == 0;
uVar3 = extraout_ECX;
if (!(bool)bVar6) {
pcVar1 = (code *)swi(0x29);
uVar9 = (*pcVar1)();
uVar3 = extraout_ECX_00;
}
_DAT_00411940 = (undefined4)((ulonglong)uVar9 >> 0x20);
_DAT_00411948 = (undefined4)uVar9;
_DAT_00411958 =
(uint)(in_NT & 1) * 0x4000 | (uint)(bVar8 & 1) * 0x800 | (uint)(in_IF & 1) * 0x200 |
(uint)(in_TF & 1) * 0x100 | (uint)(bVar7 & 1) * 0x80 | (uint)(bVar6 & 1) * 0x40 |
(uint)(in_AF & 1) * 0x10 | (uint)(bVar5 & 1) * 4 | (uint)(bVar4 & 1) |
(uint)(in_ID & 1) * 0x200000 | (uint)(in_VIP & 1) * 0x100000 | (uint)(in_VIF & 1) * 0x80000 |
(uint)(in_AC & 1) * 0x40000;
_DAT_0041195c = &stack0x00000004;
_DAT_00411898 = 0x10001;
_DAT_00411848 = 0xc0000409;
_DAT_0041184c = 1;
_DAT_00411858 = 1;
DAT_0041185c = 2;
_DAT_00411854 = unaff_retaddr;
_DAT_00411924 = in_GS;
_DAT_00411928 = in_FS;
_DAT_0041192c = in_ES;
_DAT_00411930 = in_DS;
_DAT_00411934 = unaff_EDI;
_DAT_00411938 = unaff_ESI;
_DAT_0041193c = unaff_EBX;
_DAT_00411944 = uVar3;
_DAT_0041194c = unaff_EBP;
DAT_00411950 = unaff_retaddr;
_DAT_00411954 = in_CS;
_DAT_00411960 = in_SS;
FUN_00401d0a((_EXCEPTION_POINTERS *)&PTR_DAT_0040b228);
return;
}
🔥 Whoa. This is definitely the big red button.
FUN_00401d32() is not just some throwaway — it's a deliberate crash generator, and one that does it in a very elaborate, low-level way. This is a custom structured exception trigger likely designed to:
-
Signal stack corruption (like from buffer overflows)
-
Feed a manually-constructed
_EXCEPTION_POINTERSstructure into a handler -
Provide Windows Error Reporting (WER) or crash diagnostics with a detailed context
Let's break it down.
🧠 What Is This Function?
✅ It's a manually-triggered structured exception thrower.
-
Equivalent to:
RaiseException(0xC0000409, EXCEPTION_NONCONTINUABLE, ...); -
With a hand-crafted
EXCEPTION_RECORD+CONTEXT
🔥 Breakdown: What's It Doing?
1. Check Processor Feature & Optional Fast-Fail
uVar2 = IsProcessorFeaturePresent(0x17); // PF_XMMI64_INSTRUCTIONS_AVAILABLE (SSE2) if (uVar2 != 0) { // Execute INT 0x29 (Fast Fail) pcVar1 = (code *)swi(0x29); uVar9 = (*pcVar1)(); } -
If SSE2 is supported, it does a fast fail (via
int 0x29) -
This would immediately crash the program in release mode
But the rest of the function continues even if this doesn't crash, probably for emulation/debugger-resistance.
2. Populate Global Crash Context
_DAT_00411940 = high 32 bits of uVar9; _DAT_00411948 = low 32 bits of uVar9; -
Saving crash timestamp or fault info, depending on what
uVar9is.
3. Set up an emulated EFLAGS register
_DAT_00411958 = flags bitfield -
Reconstructs EFLAGS-style bitmask from scattered input flags.
-
Some bits:
TF,IF,AF,ID,AC,VIF,VIP,NT, etc. -
Used in the emulated context (maybe for WER or dump processing)
4. Fill in fake exception and context data
_DAT_00411898 = 0x10001; // CONTEXT struct marker _DAT_00411848 = 0xC0000409; // STATUS_STACK_BUFFER_OVERRUN _DAT_0041184c = 1; // ExceptionFlags = non-continuable _DAT_00411858 = 1; // Num parameters? DAT_0041185c = 2; // Possibly exception type? -
This mimics what a real buffer overrun or stack corruption would trigger.
_DAT_00411854 = return address _DAT_00411924..._DAT_00411960 = segment registers, general purpose, etc. -
Full context is assembled like a real exception frame.
5. Trigger custom crash handler
FUN_00401d0a((_EXCEPTION_POINTERS *)&PTR_DAT_0040b228); -
Finally, this function is handed a fully-faked
_EXCEPTION_POINTERSstructure and passed to a handler.
Most likely:
-
FUN_00401d0araises a custom exception -
Or logs it
-
Or hands it off to Windows Error Reporting / custom telemetry
💀 What Does This Achieve?
| Goal | Why |
|---|---|
| Custom crash with full state | Helps identify memory corruption |
| Avoids relying on Windows SEH | Works in weird contexts (e.g. early runtime) |
| Can fool emulators or debuggers | Complex behavior to mask intent |
| Diagnostic depth | Could be part of telemetry or crash upload logic |
| Anti-exploit marker | Specifically uses 0xC0000409, a known security-related exception code |
✅ TL;DR
FUN_00401d32() is the CRT's nuclear option — it:
-
Builds its own
EXCEPTION_RECORD+CONTEXT -
Sets exception code:
STATUS_STACK_BUFFER_OVERRUN (0xC0000409) -
May crash immediately with
int 0x29(fast fail) -
Otherwise, hands everything to a crash handler via
FUN_00401d0a()
Used as the final step when a stack corruption is detected (i.e. guard cookie mismatch).
If you'd like, we can now examine FUN_00401d0a() to complete the whole crash path. Want to drop it in?
Comments
Post a Comment