<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

文章分类

导航

订阅

SEH无法捕捉内核代码的除零异常

在下面这小段代码中,存在一个故意的除零操作,并且使用了Windows操作系统的结构化异常处理(SEH)机制对其进行了保护。

    59: n=1;

    60: m=0;

    61: __try

    62: {

    63:         n=n/m;

    64: }

    65: __except(EXCEPTION_EXECUTE_HANDLER)

    66: {

    67:         DBGOUT(("Caught divide by zero safely."));

    68: }

如果以上代码是包含在用户态程序中的,也就是说在用户态执行,那么这个SEH会起作用,捕捉到这个异常。但是如果这段代码是在内核态中执行,那么这个SEH保护不会起作用。更准确的说,今天的Windows系统(至少是XP,Server 2003)内核会直接调用keBugCheck产生蓝屏,而不会交给异常保护块来处理这个异常。

其详细过程如下,当除零异常发生后,异常处理函数KiTrap00会被执行。这个函数会调用另一个名为Ki386CheckDivideByZeroTrap的内核函数。Ki386CheckDivideByZeroTrap在被调用后,会检查异常是否来源于内核代码,从汇编代码可以清楚的看到这一点:

kd> u nt!Ki386CheckDivideByZeroTrap la
nt!Ki386CheckDivideByZeroTrap:
80607316 6a38            push    38h
80607318 6800565380      push    offset nt!_real+0x78 (80535600)
8060731d e8ffa9f0ff      call    nt!_SEH_prolog (80511d21)
80607322 c745e4940000c0  mov     dword ptr [ebp-1Ch],0C0000094h
80607329 8b4508          mov     eax,dword ptr [ebp+8]
8060732c 83786c08        cmp     dword ptr [eax+6Ch],8
80607330 7508            jne     nt!Ki386CheckDivideByZeroTrap+0x23 (8060733a)
80607332 6a7f            push    7Fh
80607334 e876f3f1ff      call    nt!KeBugCheck (805266af)
80607339 cc              int     3

第4行是把参数1(KTRAP_FRAME结构)赋给EAX。第5行是比较这个结构的6C偏移是否等于8。如果相等,接下来的两行(6、7行)就是调用KeBugCheck产生蓝屏。蓝屏的代码是7F,即UNEXPECTED_KERNEL_MODE_TRAP。
事实上,这里就是Windows内核就是在检查异常是否发生在内核态。6C字段实际上是发生异常时的CS寄存器值,即代码段的段选择子值。8代表了内核代码段的段选择子。以下是KTRAP_FRAME结构在Windows XP系统中的的定义:

kd> dt nt!_KTRAP_FRAME
   +0x000 DbgEbp           : Uint4B
   +0x004 DbgEip           : Uint4B
   +0x008 DbgArgMark       : Uint4B
   +0x00c DbgArgPointer    : Uint4B
   +0x010 TempSegCs        : Uint4B
   +0x014 TempEsp          : Uint4B
   +0x018 Dr0              : Uint4B
   +0x01c Dr1              : Uint4B
   +0x020 Dr2              : Uint4B
   +0x024 Dr3              : Uint4B
   +0x028 Dr6              : Uint4B
   +0x02c Dr7              : Uint4B
   +0x030 SegGs            : Uint4B
   +0x034 SegEs            : Uint4B
   +0x038 SegDs            : Uint4B
   +0x03c Edx              : Uint4B
   +0x040 Ecx              : Uint4B
   +0x044 Eax              : Uint4B
   +0x048 PreviousPreviousMode : Uint4B
   +0x04c ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x050 SegFs            : Uint4B
   +0x054 Edi              : Uint4B
   +0x058 Esi              : Uint4B
   +0x05c Ebx              : Uint4B
   +0x060 Ebp              : Uint4B
   +0x064 ErrCode          : Uint4B
   +0x068 Eip              : Uint4B
   +0x06c SegCs            : Uint4B
   +0x070 EFlags           : Uint4B
   +0x074 HardwareEsp      : Uint4B
   +0x078 HardwareSegSs    : Uint4B
   +0x07c V86Es            : Uint4B
   +0x080 V86Ds            : Uint4B
   +0x084 V86Fs            : Uint4B
   +0x088 V86Gs            : Uint4B
终上,一旦Ki386CheckDivideByZeroTrap检测到除零异常来源于内核代码就会立刻发起蓝屏,根本就进入常规的异常分发流程,因此也就不会执行什么SEH处理器了。

 

posted on 2007年12月14日 23:11 由 Raymond

Powered by Community Server Powered by CnForums.Net