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_POINTERS structure 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 uVar9 is.


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_POINTERS structure and passed to a handler.

Most likely:

  • FUN_00401d0a raises 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

Popular posts from this blog

Avoiding detection when injecting a DLL into a game process

Some global variable set, mystery function

FULL REFLECTIVE INJECTION PACK