简单分析int3与int0
前言
int3和int 0的流程如果只是简单分析其实相当类似,唯一的差别就是int 3的dec操作差点给我整蒙了,所以我们先分析int 3
再次之前先来了解一个结构体
_EXCEPTION_RECORD
kd> dt _EXCEPTION_RECORD ntdll!_EXCEPTION_RECORD +0x000 ExceptionCode : Int4B //异常码 +0x004 ExceptionFlags : Uint4B +0x008 ExceptionRecord : Ptr32 _EXCEPTION_RECORD +0x00c ExceptionAddress : Ptr32 Void //异常函数 +0x010 NumberParameters : Uint4B +0x014 ExceptionInformation : [15] Uint4B
源码分析
int 3源码
.text:00407AA1 _KiTrap03 proc near ; DATA XREF: INIT:005ED114↓o .text:00407AA1 .text:00407AA1 var_2 = word ptr -2 .text:00407AA1 arg_4 = dword ptr 8 .text:00407AA1 .text:00407AA1 push 0 .text:00407AA3 mov [esp+4+var_2], 0 .text:00407AAA push ebp .text:00407AAB push ebx .text:00407AAC push esi .text:00407AAD push edi .text:00407AAE push fs .text:00407AB0 mov ebx, 30h ; '0' .text:00407AB5 mov fs, ebx .text:00407AB7 mov ebx, large fs:0 .text:00407ABE push ebx .text:00407ABF sub esp, 4 .text:00407AC2 push eax .text:00407AC3 push ecx .text:00407AC4 push edx .text:00407AC5 push ds .text:00407AC6 push es .text:00407AC7 push gs .text:00407AC9 mov ax, 23h ; '#' .text:00407ACD sub esp, 30h .text:00407AD0 mov ds, eax .text:00407AD2 mov es, eax .text:00407AD4 mov ebp, esp .text:00407AD6 test [esp+_KTRAP_FRAME.EFlags], 20000h .text:00407ADE jnz short V86_kit3_a .text:00407AE0 .text:00407AE0 loc_407AE0: ; CODE XREF: V86_kit3_a+25↑j .text:00407AE0 cld .text:00407AE1 mov ebx, [ebp+_KTRAP_FRAME._Ebp] .text:00407AE4 mov edi, [ebp+_KTRAP_FRAME._Eip] .text:00407AE7 mov [ebp+_KTRAP_FRAME.DbgArgPointer], edx .text:00407AEA mov [ebp+_KTRAP_FRAME.DbgArgMark], 0BADB0D00h .text:00407AF1 mov [ebp+_KTRAP_FRAME.DbgEbp], ebx .text:00407AF4 mov [ebp+_KTRAP_FRAME.DbgEip], edi .text:00407AF7 test large byte ptr fs:50h, 0FFh .text:00407AFF jnz Dr_kit3_a .text:00407B05 .text:00407B05 loc_407B05: ; CODE XREF: Dr_kit3_a+10↑j .text:00407B05 ; Dr_kit3_a+7C↑j .text:00407B05 cmp ds:_PoHiberInProgress, 0 .text:00407B0C jnz short loc_407B15 .text:00407B0E lock inc ds:_KiHardwareTrigger .text:00407B15 .text:00407B15 loc_407B15: ; CODE XREF: _KiTrap03+6B↑j .text:00407B15 mov eax, 0 .text:00407B1A .text:00407B1A loc_407B1A: ; CODE XREF: _KiDebugService+70↑j .text:00407B1A test [ebp+_KTRAP_FRAME.EFlags], 20000h ; 判断虚拟8086 .text:00407B21 jnz short loc_407B4C .text:00407B23 test word ptr [ebp+_KTRAP_FRAME.SegCs], 1 ; 判断是否从3环来 .text:00407B29 jz short loc_407B33 .text:00407B2B cmp word ptr [ebp+_KTRAP_FRAME.SegCs], 1Bh .text:00407B30 jnz short loc_407B4C .text:00407B32 .text:00407B32 loc_407B32: ; CODE XREF: _KiTrap03+BC↓j .text:00407B32 sti .text:00407B33 .text:00407B33 loc_407B33: ; CODE XREF: _KiTrap03+88↑j .text:00407B33 ; _KiTrap03+CF↓j .text:00407B33 mov esi, ecx .text:00407B35 mov edi, edx .text:00407B37 mov edx, eax .text:00407B39 mov ebx, [ebp+_KTRAP_FRAME._Eip] .text:00407B3C dec ebx .text:00407B3D mov ecx, 3 .text:00407B42 mov eax, 80000003h .text:00407B47 call CommonDispatchException .text:00407B4C .text:00407B4C loc_407B4C: ; CODE XREF: _KiTrap03+80↑j .text:00407B4C ; _KiTrap03+8F↑j .text:00407B4C mov ebx, large fs:_KPCR.PrcbData.CurrentThread .text:00407B53 mov ebx, [ebx+_KTHREAD.ApcState.Process] .text:00407B56 cmp dword ptr [ebx+158h], 0 .text:00407B5D jz short loc_407B32 .text:00407B5F push 3 .text:00407B61 call _Ki386VdmReflectException_A@4 ; Ki386VdmReflectException_A(x) .text:00407B66 test ax, 0FFFFh .text:00407B6A jnz Kei386EoiHelper@0 ; Kei386EoiHelper() .text:00407B70 jmp short loc_407B33 .text:00407B70 _KiTrap03 endp
我们发现函数在上述的一顿操作后,这里有个小细节需要说,我们发现ebx在获得了3环的eip后,并且进行了dec减一,原因就是需要找到出中断的(这是陷阱异常的特性),就会对CommonDispatchException进行调用
CommonDispatchException
.text:004073A6 CommonDispatchException proc near ; CODE XREF: _KiTrap00-187↑p .text:004073A6 ; _KiTrap00-17B↑p ... .text:004073A6 .text:004073A6 var_50 = dword ptr -50h .text:004073A6 var_4C = dword ptr -4Ch .text:004073A6 var_48 = dword ptr -48h .text:004073A6 var_44 = dword ptr -44h .text:004073A6 var_40 = dword ptr -40h .text:004073A6 var_3C = byte ptr -3Ch .text:004073A6 .text:004073A6 sub esp, 50h .text:004073A9 mov [esp+_EXCEPTION_RECORD.ExceptionCode], eax .text:004073AC xor eax, eax .text:004073AE mov [esp+_EXCEPTION_RECORD.ExceptionFlags], eax .text:004073B2 mov [esp+_EXCEPTION_RECORD.ExceptionRecord], eax .text:004073B6 mov [esp+_EXCEPTION_RECORD.ExceptionAddress], ebx ; EIP .text:004073BA mov [esp+_EXCEPTION_RECORD.NumberParameters], ecx .text:004073BE cmp ecx, 0 .text:004073C1 jz short loc_4073CF .text:004073C3 lea ebx, [esp+_EXCEPTION_RECORD.ExceptionInformation] .text:004073C7 mov [ebx], edx .text:004073C9 mov [ebx+4], esi .text:004073CC mov [ebx+8], edi .text:004073CF .text:004073CF loc_4073CF: ; CODE XREF: CommonDispatchException+1B↑j .text:004073CF mov ecx, esp .text:004073D1 test [ebp+_KTRAP_FRAME.EFlags], 20000h ; 判断是否为虚拟8086模式 .text:004073D8 jz short loc_4073E1 .text:004073DA mov eax, 0FFFFh .text:004073DF jmp short loc_4073E4 .text:004073E1 ; --------------------------------------------------------------------------- .text:004073E1 .text:004073E1 loc_4073E1: ; CODE XREF: CommonDispatchException+32↑j .text:004073E1 mov eax, [ebp+_KTRAP_FRAME.SegCs] .text:004073E4 .text:004073E4 loc_4073E4: ; CODE XREF: CommonDispatchException+39↑j .text:004073E4 and eax, 1 .text:004073E7 push 1 ; char .text:004073E9 push eax ; int .text:004073EA push ebp ; BugCheckParameter3 .text:004073EB push 0 ; int .text:004073ED push ecx ; ExceptionRecord .text:004073EE call _KiDispatchException@20 ; KiDispatchException(x,x,x,x,x) .text:004073F3 mov esp, ebp .text:004073F5 jmp Kei386EoiHelper@0 ; Kei386EoiHelper() .text:004073F5 CommonDispatchException endp
在进入该函数后,我们可以发先其最终又调用了_KiDispatchException(异常分发函数,这个要到后面几篇回有介绍的)
我们在来看看int 0的差别在哪
int 0
.text:0040750E push 0 .text:00407510 mov [esp+4+var_2], 0 ; 填充TrapFrame .text:00407517 push ebp .text:00407518 push ebx .text:00407519 push esi .text:0040751A push edi .text:0040751B push fs .text:0040751D mov ebx, 30h ; '0' .text:00407522 mov fs, ebx .text:00407524 assume fs:nothing .text:00407524 mov ebx, large fs:0 .text:0040752B push ebx .text:0040752C sub esp, 4 .text:0040752F push eax .text:00407530 push ecx .text:00407531 push edx .text:00407532 push ds .text:00407533 push es .text:00407534 push gs .text:00407536 mov ax, 23h ; '#' .text:0040753A sub esp, 30h .text:0040753D mov ds, eax ; ds=0x23 .text:0040753F assume ds:nothing .text:0040753F mov es, eax ; es=0x23 .text:00407541 assume es:nothing .text:00407541 mov ebp, esp ; 提升堆栈到_Trap_Frame的0x00偏移处(DbgEbp) .text:00407543 test [esp+_KTRAP_FRAME.EFlags], 20000h ; 判断是否为虚拟8086模式 .text:0040754B jnz short V86_kit0_a .text:0040754D .text:0040754D loc_40754D: ; CODE XREF: V86_kit0_a+25↑j .text:0040754D cld .text:0040754E mov ebx, [ebp+_KTRAP_FRAME._Ebp] .text:00407551 mov edi, [ebp+_KTRAP_FRAME._Eip] .text:00407554 mov [ebp+_KTRAP_FRAME.DbgArgPointer], edx .text:00407557 mov [ebp+_KTRAP_FRAME.DbgArgMark], 0BADB0D00h .text:0040755E mov [ebp+_KTRAP_FRAME.DbgEbp], ebx .text:00407561 mov [ebp+_KTRAP_FRAME.DbgEip], edi .text:00407564 test large byte ptr fs:50h, 0FFh ; 判断内核调试器是否存在,存在则跳转 .text:0040756C jnz Dr_kit0_a .text:00407572 .text:00407572 loc_407572: ; CODE XREF: Dr_kit0_a+10↑j .text:00407572 ; Dr_kit0_a+7C↑j .text:00407572 test [ebp+_KTRAP_FRAME.EFlags], 20000h ; 判断是否为虚拟8086模式 .text:00407579 jnz short loc_4075B8 ; 是则跳转 .text:0040757B test byte ptr [ebp+_KTRAP_FRAME.SegCs], 1 ; 是从3环来的还是0环来的 .text:0040757F jz short loc_407588 ; 是0环则跳转 .text:00407581 cmp word ptr [ebp+_KTRAP_FRAME.SegCs], 1Bh .text:00407586 jnz short loc_4075A5 .text:00407588 .text:00407588 loc_407588: ; CODE XREF: _KiTrap00+71↑j .text:00407588 sti .text:00407589 push ebp .text:0040758A call _Ki386CheckDivideByZeroTrap@4 ; Ki386CheckDivideByZeroTrap(x) .text:0040758F mov ebx, [ebp+68h] .text:00407592 jmp loc_407385 .text:00407597 ; --------------------------------------------------------------------------- .text:00407597 .text:00407597 loc_407597: ; CODE XREF: _KiTrap00+A8↓j .text:00407597 ; _KiTrap00+B9↓j .text:00407597 sti .text:00407598 mov ebx, [ebp+_KTRAP_FRAME._Eip] .text:0040759B mov eax, 0C0000094h ; 异常码 .text:004075A0 jmp loc_407385 .text:004075A5 ; --------------------------------------------------------------------------- .text:004075A5 .text:004075A5 loc_4075A5: ; CODE XREF: _KiTrap00+78↑j .text:004075A5 mov ebx, large fs:_KPCR.PrcbData.CurrentThread .text:004075AC mov ebx, [ebx+_KTHREAD.ApcState.Process] .text:004075AF cmp [ebx+_EPROCESS.VdmObjects], 0 .text:004075B6 jz short loc_407597 .text:004075B8 .text:004075B8 loc_4075B8: ; CODE XREF: _KiTrap00+6B↑j .text:004075B8 push 0 .text:004075BA call _Ki386VdmReflectException_A@4 ; Ki386VdmReflectException_A(x) .text:004075BF or al, al .text:004075C1 jnz Kei386EoiHelper@0 ; Kei386EoiHelper() .text:004075C7 jmp short loc_407597 .text:004075C7 _KiTrap00 endp
我们很容易发现int 0和int 3就是少了哪个dec 指令,其余的流程跟int 3几乎一模一样