Int 1的实现过程 (一)

  闲话少说,直奔主题,首先OD载入一个程序,然后执行一下单步(调试器会将TF置1)

  此时,CPU会在基于当前线程上下文的环境中,进入int 1的中断门,也就是KiTrap01

kd> !idt -a

Dumping IDT:

00:	805431a0 nt!KiTrap00
01:	8054331c nt!KiTrap01     // int 1会转到这个函数执行
02:	Task Selector = 0x0058   // NMI  从这里可以看到NMI是通过任务门执行的
03:	80543730 nt!KiTrap03
04:	805438b0 nt!KiTrap04
05:	80543a10 nt!KiTrap05
06:	80543b84 nt!KiTrap06
07:	805441fc nt!KiTrap07
08:	Task Selector = 0x0050  // DF 因为发生DF时,寄存器可能已经出错了,所以需要任务门,加载新的环境
09:	80544600 nt!KiTrap09

  然后我们看下windbg,首先在KiTrap01下断,其次通过OD的单步后,确实已经中断到windbg的KiTrap01处了,其环境也是被调试线程的环境

     看下TSS中ESP0的值

kd> r tr
tr=00000028
kd> dg 28
                                  P Si Gr Pr Lo
Sel    Base     Limit     Type    l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0028 80042000 000020ab TSS32 Busy 0 Nb By P  Nl 0000008b
kd> dd 80042000
80042000  0c458b24 b23b9de0 8b080010 758b0855  //b23b9de0就是ESP0的值 

        intel手册中说到,在转移到中断例程入口前,会先将SS  ESP  EFLAGS  CS  EIP  ErrorCode压入内核栈,所以我们看看ESP0中的值

kd> dd esp
b23b9dcc 00421480 0000001b 00000346 0012ffc0
b23b9ddc 00000023                  //从这里可以得知   SS:23    ESP:12FFC0    EFLAGS:346    CS:1b    EIP:421480

    好了,可以进入正题了,先看下KiTrap01的执行过程

nt!KiTrap01:
8054331c 6a00            push    0                 // ErrorCode
8054331e 66c74424020000  mov     word ptr [esp+2],0
80543325 55              push    ebp
80543326 53              push    ebx
80543327 56              push    esi
80543328 57              push    edi
80543329 0fa0            push    fs
8054332b bb30000000      mov     ebx,30h
80543330 668ee3          mov     fs,bx
80543333 648b1d00000000  mov     ebx,dword ptr fs:[0]
8054333a 53              push    ebx                // ExceptionList
8054333b 83ec04          sub     esp,4               // PreviousPreviousMode
8054333e 50              push    eax
8054333f 51              push    ecx
80543340 52              push    edx
80543341 1e              push    ds
80543342 06              push    es
80543343 0fa8            push    gs
80543345 66b82300        mov     ax,23h
80543349 83ec30          sub     esp,30h             // 到这里_KTRAP_FRAME已经填充一半了,还差30h
8054334c 668ed8          mov     ds,ax
8054334f 668ec0          mov     es,ax
80543352 8bec            mov     ebp,esp
80543354 f744247000000200 test    dword ptr [esp+70h],20000h  // 检测是否是虚拟8086模式
8054335c 7596            jne     nt!V86_kit1_a (805432f4)      // 是虚拟8086模式的话,就发生跳转,这里我们应该继续执行
8054335e fc              cld
8054335f 8b5d60          mov     ebx,dword ptr [ebp+60h]      // 被压入栈的EBP寄存器的值,这里是12FFF0
80543362 8b7d68          mov     edi,dword ptr [ebp+68h]      // 被压入栈中EIP寄存器的值,这里是421480
80543365 89550c          mov     dword ptr [ebp+0Ch],edx    // KiFastSystemCall
80543368 c74508000ddbba  mov     dword ptr [ebp+8],0BADB0D00h // DbgArgMark
8054336f 895d00          mov     dword ptr [ebp],ebx      // DbgEbp
80543372 897d04          mov     dword ptr [ebp+4],edi     // DbgEip

/************************************************************************************************************************************** /*****                  执行完这几个栈操作后,我们看下栈中的值                                   *****
/**************************************************************************************************************************************   kd> dd ebp  其实这里都是KTRAP_FTAME的值   b23b9d64 0012fff0  00421480 badb0d00 7c92e4f4   b23b9d74 7c930208 ffffffff ffffffff 0012fff0   b23b9d84 00000000 80543349 00000008 00000196   b23b9d94 00000000 00000023 00000023 7c92e4f4   b23b9da4 0012ffb0 00000000 00000146 ffffffff   b23b9db4 00000030 7c930208 ffffffff 7ffd8000   b23b9dc4 0012fff0 00000000 00421480 0000001b   b23b9dd4 00000346 0012ffc0 00000023 805470de 80543375 64f60550000000ff test byte ptr fs:[50h],0FFh    // 测试DebugActive 8054337d 0f85edfeffff jne nt!Dr_kit1_a (80543270) 80543383 64833d5400000000 cmp dword ptr fs:[54h],0 8054338b 7561 jne nt!KiTrap01+0xd2 (805433ee) 8054338d 8b4d68 mov ecx,dword ptr [ebp+68h] 80543390 81f920255480 cmp ecx,offset nt!KiFastCallEntry (80542520)   80543396 0f84c4feffff je nt!KiTrap00+0xc0 (80543260) // 测试是不是sysenter指令,如果是的话,不能步过 8054339c f7457000000200 test dword ptr [ebp+70h],20000h 805433a3 7524       jne    nt!KiTrap01+0xad (805433c9) // 检测虚拟8086模式 805433a5 66f7456c0100 test   word ptr [ebp+6Ch],1     805433ab 7408      je    nt!KiTrap01+0x99 (805433b5)   // 检测当前CPL,如果是R3的话,就不发生跳转 805433ad 66837d6c1b   cmp    word ptr [ebp+6Ch],1Bh 805433b2 7515       jne    nt!KiTrap01+0xad (805433c9)     // 如果是R3的话,CS应该是1B,如果不是的话,发生跳转 805433b4 fb         sti 805433b5 816570fffeffff and    dword ptr [ebp+70h],0FFFFFEFFh   //EFLAGS的TF位清零 805433bc 8b5d68 mov    ebx,dword ptr [ebp+68h]     // (ebx)-> faulting instruction 805433bf b804000080 mov   eax,80000004h         // TF异常的错误码 805433c4 e94efcffff jmp   nt!KiExceptionExit+0x16b (80543017)

 

80543017 33c9            xor     ecx,ecx
80543019 e81a000000      call    nt!CommonDispatchException (80543038)  // Never return

 接下来看看CommonDispatchException内部都做了些什么

/**********************************************************************************************
/*****          Set up exception record for raising exception            *****
/**********************************************************************************************
首先来看看EXCEPTION_RECORD
  kd> dt _exception_record
  nt!_EXCEPTION_RECORD
  +0x000 ExceptionCode : Int4B
  +0x004 ExceptionFlags : Uint4B
  +0x008 ExceptionRecord : Ptr32 _EXCEPTION_RECORD
  +0x00c ExceptionAddress : Ptr32 Void
  +0x010 NumberParameters : Uint4B
  +0x014 ExceptionInformation : [15] Uint4B


nt!CommonDispatchException:
80543038 83ec50          sub     esp,50h            // ExceptionRecordLength, allocate exception record
8054303b 890424          mov     dword ptr [esp],eax     // set ExceptionCode           其实也就是上文的80000004h
8054303e 33c0            xor     eax,eax
80543040 89442404        mov     dword ptr [esp+4],eax    // set ExceptionFlags         这里为0
80543044 89442408        mov     dword ptr [esp+8],eax    //  set associated ExceptionRecord 这里为0
80543048 895c240c        mov     dword ptr [esp+0Ch],ebx  //  set ExceptionAddress       其实也就是上文的421480
8054304c 894c2410        mov     dword ptr [esp+10h],ecx  //  set NumberParameters       这里为0
80543050 83f900          cmp     ecx,0
80543053 740c            je      nt!CommonDispatchException+0x29 (80543061)  

//跳到了这里 set up arguments and call _KiDispatchException
80543061 8bcc       mov ecx,esp               //  (ecx)->exception record
80543063 f7457000000200 test dword ptr [ebp+70h],20000h
8054306a 7407       je nt!CommonDispatchException+0x3b (80543073)  // 因为不是虚拟8086模式,所以会发生跳转

//跳转到这里后,就该调用KiDispatchException了
stdCall _KiDispatchException,<ecx, 0, ebp, eax, 1>      //  汇编中的原型
KiDispatchException (                       //  API中的原型
IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN FirstChance
)

80543073 8b456c      mov   eax,dword ptr [ebp+6Ch]   
80543076 83e001      and   eax,1           //  通过CS段选择子,得到被调试程序的CPL, 通过与运算后,得到后面的PreviousMode
80543079 6a01       push  1              //  1 - first chance TRUE
8054307b 50        push  eax            //  eax - PreviousMode
8054307c 55         push  ebp            //  TrapFrame
8054307d 6a00        push  0             //   ExceptionFrame
8054307f 51        push  ecx            //   ExceptionRecord
80543080 e8e1c3fbff    call   nt!KiDispatchException (804ff466)

  

这里再看看我们的KTRAP_FRAME的具体值,这些值能很详细的说明故障信息

kd> dt _ktrap_frame b2bf3d64
nt!_KTRAP_FRAME
   +0x000 DbgEbp           : 0x12fff0
   +0x004 DbgEip           : 0x421480
   +0x008 DbgArgMark       : 0xbadb0d00
   +0x00c DbgArgPointer    : 0x7c92e4f4
   +0x010 TempSegCs        : 0x7c930208
   +0x014 TempEsp          : 0xffffffff
   +0x018 Dr0              : 0xffffffff
   +0x01c Dr1              : 0x12fff0
   +0x020 Dr2              : 0
   +0x024 Dr3              : 0x80543349
   +0x028 Dr6              : 8
   +0x02c Dr7              : 0x196
   +0x030 SegGs            : 0
   +0x034 SegEs            : 0x23
   +0x038 SegDs            : 0x23
   +0x03c Edx              : 0x7c92e4f4
   +0x040 Ecx              : 0x12ffb0
   +0x044 Eax              : 0
   +0x048 PreviousPreviousMode : 0x146
   +0x04c ExceptionList    : 0xffffffff _EXCEPTION_REGISTRATION_RECORD
   +0x050 SegFs            : 0x30
   +0x054 Edi              : 0x7c930208
   +0x058 Esi              : 0xffffffff
   +0x05c Ebx              : 0x7ffd8000
   +0x060 Ebp              : 0x12fff0
   +0x064 ErrCode          : 0
   +0x068 Eip              : 0x421480
   +0x06c SegCs            : 0x1b
   +0x070 EFlags           : 0x246
   +0x074 HardwareEsp      : 0x12ffc0
   +0x078 HardwareSegSs    : 0x23
   +0x07c V86Es            : 0
   +0x080 V86Ds            : 0
   +0x084 V86Fs            : 0
   +0x088 V86Gs            : 0

  

  好了,先分析到这吧,明天分析KiDispatchException这个函数......困了!

                                                              01:08:21

  

  

 
原文地址:https://www.cnblogs.com/testvt/p/5724394.html