WINDOWS系统调用 和 SYSENTER系统服务调用过程

Windows 2K通过2Eh中断来实现系统调用的,但是在XP后使用SysEnter来实现系统调用了,同时2Eh中断还是保存着的。不管是2EH中断还是SYSENTER,Windows对所有的系统调用都会生成下面的KTRAP_FRAME堆栈框架。

 

 

KTRAP_FRAME框架结构图

 

用户态下使用2EH中断时,CPU会自动产生0x78和0x74 以保存用户态下的堆栈和指针;若直接是从系统层调用2EH,则CPU是不会自动保存堆栈的,所以需要程序自己保存。

SYSTENTER只能是从RING3(用户态)到RING0(系统态)。和2EH中断不同,CPU执行SYSENTER是不会自动在堆栈中保存数据的。所以为了2EH时堆栈情况一致,需要处理程序模拟保存一些数据。

2EH和SYSENTER的堆栈一致后,下面真正的系统调用时一样的,最后返回时根据调用的不同返回情况也不同。

 

 

==========================================================================================

SYSENTER系统服务调用过程


以NtReadFile调用为例。

一.NtDll.Dll中,NtReadFile过程如下:
ntdll!NtReadFile:
7c92d9b0 b8b7000000      mov     eax,0B7h
7c92d9b5 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
7c92d9ba ff12            call    dword ptr [edx]
7c92d9bc c22400          ret     24h

 

二.0x7ffe0300地址存放0x7c92e4f0,反汇编它:
ntdll!KiFastSystemCall:
7c92e4f0 8bd4          mov     edx,esp
7c92e4f2 0f34          sysenter

因为SYSENTER执行时,CPU并不会向CALL一样保存返回地址和状态信息,所以需要这样一个“桩”(STUB)段,通过它来保存返回信息。同样的,下面的(五)就是利用这里保存的返回信息返回值NtReadFile中。

这里的KiFastSystemCall和(五)中的SystemCallReturn 都是保存在 _KUSER_SHARED_DATA结构中。用户态下的0X7FFE0000和系统态下的0XFFDF0000同时指向它。结构如下:

nt!_KUSER_SHARED_DATA
   +0x000 TickCountLow     : Uint4B
   +0x004 TickCountMultiplier : Uint4B
   +0x008 InterruptTime    : _KSYSTEM_TIME
   +0x014 SystemTime       : _KSYSTEM_TIME
   +0x020 TimeZoneBias     : _KSYSTEM_TIME
   +0x02c ImageNumberLow   : Uint2B
   +0x02e ImageNumberHigh  : Uint2B
   +0x030 NtSystemRoot     : [260] Uint2B
   +0x238 MaxStackTraceDepth : Uint4B
   +0x23c CryptoExponent   : Uint4B
   +0x240 TimeZoneId       : Uint4B
   +0x244 Reserved2        : [8] Uint4B
   +0x264 NtProductType    : _NT_PRODUCT_TYPE
   +0x268 ProductTypeIsValid : UChar
   +0x26c NtMajorVersion   : Uint4B
   +0x270 NtMinorVersion   : Uint4B
   +0x274 ProcessorFeatures : [64] UChar
   +0x2b4 Reserved1        : Uint4B
   +0x2b8 Reserved3        : Uint4B
   +0x2bc TimeSlip         : Uint4B
   +0x2c0 AlternativeArchitecture : _ALTERNATIVE_ARCHITECTURE_TYPE
   +0x2c8 SystemExpirationDate : _LARGE_INTEGER
   +0x2d0 SuiteMask        : Uint4B
   +0x2d4 KdDebuggerEnabled : UChar
   +0x2d5 NXSupportPolicy  : UChar
   +0x2d8 ActiveConsoleId  : Uint4B
   +0x2dc DismountCount    : Uint4B
   +0x2e0 ComPlusPackage   : Uint4B
   +0x2e4 LastSystemRITEventTickCount : Uint4B
   +0x2e8 NumberOfPhysicalPages : Uint4B
   +0x2ec SafeBootMode     : UChar
   +0x2f0 TraceLogging     : Uint4B
   +0x2f8 TestRetInstruction : Uint8B
   +0x300 SystemCall       : Uint4B
   +0x304 SystemCallReturn : Uint4B
   +0x308 SystemCallPad    : [3] Uint8B
   +0x320 TickCount        : _KSYSTEM_TIME
   +0x320 TickCountQuad    : Uint8B
   +0x330 Cookie           : Uint4B

 

三.显示MSR,因为SYSENTER和SYSEXIT需要它。
lkd> rdmsr 174
msr[174] = 00000000`00000008  ;RING0下CS
lkd> rdmsr 175
msr[175] = 00000000`f78bb000  ;进入RING0后的ESP
lkd> rdmsr 176
msr[176] = 00000000`804de89f  ;进入RING0后的EIP

XP GDT如下,SYSENTER和SYSEXIT用到这些:
0008 00000000 ffffffff Code RE Ac 0 Bg Pg P  Nl 00000c9b ;RING0下CS
0010 00000000 ffffffff Data RW Ac 0 Bg Pg P  Nl 00000c93 ;RING0下SS
0018 00000000 ffffffff Code RE Ac 3 Bg Pg P  Nl 00000cfb ;RING3下CS
0020 00000000 ffffffff Data RW Ac 3 Bg Pg P  Nl 00000cf3 ;RING3下SS

四.进入RING0
反汇编0x804de89f,nt!KiFastCallEntry.
这个过程分成3部分:
1).每次调用都会创建一个_KTRAP_FRAME框架,第一部分就是创建这个框架
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

2).直接调用内核中的服务过程
3).从第一部分中创建的框架_KTRAP_FRAME中,返回至RING3状态

第一部分创建框架
nt!KiFastCallEntry:
804de89f b923000000      mov     ecx,23h
804de8a4 6a30            push    30h
804de8a6 0fa1            pop     fs    ;RING0下 FS=0x30
804de8a8 8ed9            mov     ds,cx ;RING3下 0x20 数据段
804de8aa 8ec1            mov     es,cx ;RING3下 0x20 数据段
804de8ac 648b0d40000000  mov     ecx,dword ptr fs:[40h] ;TSS
804de8b3 8b6104          mov     esp,dword ptr [ecx+4] 
804de8b6 6a23            push    23h
804de8b8 52              push    edx
804de8b9 9c              pushfd
804de8ba 6a02            push    2
804de8bc 83c208          add     edx,8
804de8bf 9d              popfd        ;EFLAGS = 2
804de8c0 804c240102      or      byte ptr [esp+1],2 ;EFLAGS设置。
804de8c5 6a1b            push    1Bh
804de8c7 ff350403dfff    push    dword ptr ds:[0FFDF0304h]
804de8cd 6a00            push    0
804de8cf 55              push    ebp
804de8d0 53              push    ebx
804de8d1 56              push    esi
804de8d2 57              push    edi
804de8d3 648b1d1c000000  mov     ebx,dword ptr fs:[1Ch]
804de8da 6a3b            push    3Bh
804de8dc 8bb324010000    mov     esi,dword ptr [ebx+124h]
804de8e2 ff33            push    dword ptr [ebx]
804de8e4 c703ffffffff    mov     dword ptr [ebx],0FFFFFFFFh
804de8ea 8b6e18          mov     ebp,dword ptr [esi+18h]
804de8ed 6a01            push    1
804de8ef 83ec48          sub     esp,48h
804de8f2 81ed9c020000    sub     ebp,29Ch
804de8f8 c6864001000001  mov     byte ptr [esi+140h],1
804de8ff 3bec            cmp     ebp,esp
804de901 0f8565ffffff    jne     nt!KiFastCallEntry2+0x25 (804de86c)
804de907 83652c00        and     dword ptr [ebp+2Ch],0
804de90b f6462cff        test    byte ptr [esi+2Ch],0FFh
804de90f 89ae34010000    mov     dword ptr [esi+134h],ebp
804de915 0f8535feffff    jne     nt!Dr_FastCallDrSave (804de750)
804de91b 8b5d60          mov     ebx,dword ptr [ebp+60h]
804de91e 8b7d68          mov     edi,dword ptr [ebp+68h]
804de921 89550c          mov     dword ptr [ebp+0Ch],edx
804de924 c74508000ddbba  mov     dword ptr [ebp+8],0BADB0D00h
804de92b 895d00          mov     dword ptr [ebp],ebx
804de92e 897d04          mov     dword ptr [ebp+4],edi
804de931 fb              sti
第一部分执行完后,_KTRAP_FRAME如下图。

第二部分真正的系统调用,此时EAX=系统调用号;EDX=调用参数;ESI=当前线程ETHREAD.
804de932 8bf8            mov     edi,eax
804de934 c1ef08          shr     edi,8
804de937 83e730          and     edi,30h
804de93a 8bcf            mov     ecx,edi
804de93c 03bee0000000    add     edi,dword ptr [esi+0E0h]
804de942 8bd8            mov     ebx,eax
804de944 25ff0f0000      and     eax,0FFFh
804de949 3b4708          cmp     eax,dword ptr [edi+8]
804de94c 0f8330fdffff    jae     nt!KiBBTUnexpectedRange (804de682)
804de952 83f910          cmp     ecx,10h
804de955 751b            jne     nt!KiFastCallEntry+0xcf (804de972)
804de957 648b0d18000000  mov     ecx,dword ptr fs:[18h]
804de95e 33db            xor     ebx,ebx
804de960 0b99700f0000    or      ebx,dword ptr [ecx+0F70h]
804de966 740a            je      nt!KiFastCallEntry+0xcf (804de972)
804de968 52              push    edx
804de969 50              push    eax
804de96a ff1568355680    call    dword ptr [nt!KeGdiFlushUserBatch (80563568)]
804de970 58              pop     eax
804de971 5a              pop     edx
804de972 64ff0538060000  inc     dword ptr fs:[638h]   <--KPRCB.KeSystemCalls增加一个计数
804de979 8bf2            mov     esi,edx
804de97b 8b5f0c          mov     ebx,dword ptr [edi+0Ch]
804de97e 33c9            xor     ecx,ecx
804de980 8a0c18          mov     cl,byte ptr [eax+ebx]
804de983 8b3f            mov     edi,dword ptr [edi]
804de985 8b1c87          mov     ebx,dword ptr [edi+eax*4]
804de988 2be1            sub     esp,ecx
804de98a c1e902          shr     ecx,2
804de98d 8bfc            mov     edi,esp
804de98f 3b35d48e5680    cmp     esi,dword ptr [nt!MmUserProbeAddress (80568ed4)]
804de995 0f83a8010000    jae     nt!KiSystemCallExit2+0x9f (804deb43)
804de99b f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
804de99d ffd3            call    ebx
804de99f 8be5            mov     esp,ebp
804de9a1 648b0d24010000  mov     ecx,dword ptr fs:[124h]
804de9a8 8b553c          mov     edx,dword ptr [ebp+3Ch]
804de9ab 899134010000    mov     dword ptr [ecx+134h],edx

第三部分返回至RING3
nt!KiServiceExit:
804de9b1 fa              cli
<DISPATCH_USER_APC宏>
804de9b2 f7457000000200  test    dword ptr [ebp+70h],20000h
804de9b9 7506            jne     nt!KiServiceExit+0x10 (804de9c1)
804de9bb f6456c01        test    byte ptr [ebp+6Ch],1
804de9bf 7456            je      nt!KiServiceExit+0x66 (804dea17)
804de9c1 648b1d24010000  mov     ebx,dword ptr fs:[124h]
804de9c8 c6432e00        mov     byte ptr [ebx+2Eh],0
804de9cc 807b4a00        cmp     byte ptr [ebx+4Ah],0
804de9d0 7445            je      nt!KiServiceExit+0x66 (804dea17)
804de9d2 8bdd            mov     ebx,ebp
804de9d4 894344          mov     dword ptr [ebx+44h],eax
804de9d7 c743503b000000  mov     dword ptr [ebx+50h],3Bh
804de9de c7433823000000  mov     dword ptr [ebx+38h],23h
804de9e5 c7433423000000  mov     dword ptr [ebx+34h],23h
804de9ec c7433000000000  mov     dword ptr [ebx+30h],0
804de9f3 b901000000      mov     ecx,1
804de9f8 ff152c904d80    call    dword ptr [nt!_imp_KfRaiseIrql (804d902c)]
804de9fe 50              push    eax
804de9ff fb              sti
804dea00 53              push    ebx
804dea01 6a00            push    0
804dea03 6a01            push    1
804dea05 e8f7f3ffff      call    nt!KiDeliverApc (804dde01)
804dea0a 59              pop     ecx
804dea0b ff1530904d80    call    dword ptr [nt!_imp_KfLowerIrql (804d9030)]
804dea11 8b4344          mov     eax,dword ptr [ebx+44h]
804dea14 fa              cli
804dea15 ebaa            jmp     nt!KiServiceExit+0x10 (804de9c1)

804dea17 8b54244c        mov     edx,dword ptr [esp+4Ch]
804dea1b 648b1d50000000  mov     ebx,dword ptr fs:[50h]
804dea22 64891500000000  mov     dword ptr fs:[0],edx

804dea29 8b4c2448        mov     ecx,dword ptr [esp+48h]
804dea2d 648b3524010000  mov     esi,dword ptr fs:[124h]
804dea34 888e40010000    mov     byte ptr [esi+140h],cl

804dea3a f7c3ff000000    test    ebx,0FFh
804dea40 7579            jne     nt!KiSystemCallExit2+0x17 (804deabb)

804dea42 f744247000000200 test    dword ptr [esp+70h],20000h
804dea4a 0f8506090000    jne     nt!KiExceptionExit+0x12c (804df356)

804dea50 66f744246cf8ff  test    word ptr [esp+6Ch],0FFF8h
804dea57 0f84b4000000    je      nt!KiSystemCallExit2+0x6d (804deb11)

804dea5d 66837c246c1b    cmp     word ptr [esp+6Ch],1Bh
804dea63 660fba64246c00  bt      word ptr [esp+6Ch],0
804dea6a f5              cmc
804dea6b 0f878e000000    ja      nt!KiSystemCallExit2+0x5b (804deaff)

804dea71 66837d6c08      cmp     word ptr [ebp+6Ch],8
804dea76 7405            je      nt!KiServiceExit+0xcc (804dea7d)

804dea78 8d6550          lea     esp,[ebp+50h]
804dea7b 0fa1            pop     fs
804dea7d 8d6554          lea     esp,[ebp+54h]
804dea80 5f              pop     edi
804dea81 5e              pop     esi
804dea82 5b              pop     ebx
804dea83 5d              pop     ebp

804dea84 66817c24088000  cmp     word ptr [esp+8],80h
804dea8b 0f87e1080000    ja      nt!KiExceptionExit+0x148 (804df372)
804dea91 83c404          add     esp,4

804dea94 f744240401000000 test    dword ptr [esp+4],1
nt!KiSystemCallExitBranch:
804dea9c 7506            jne     nt!KiSystemCallExit2 (804deaa4)
804dea9e 5a              pop     edx
804dea9f 59              pop     ecx
804deaa0 9d              popfd
804deaa1 ffe2            jmp     edx
nt!KiSystemCallExit:
804deaa3 cf              iretd
nt!KiSystemCallExit2:
804deaa4 f644240901      test    byte ptr [esp+9],1
804deaa9 75f8            jne     nt!KiSystemCallExit (804deaa3)
804deaab 5a              pop     edx
804deaac 83c404          add     esp,4
804deaaf 80642401fd      and     byte ptr [esp+1],0FDh
804deab4 9d              popfd
804deab5 59              pop     ecx
804deab6 fb              sti
804deab7 0f35            sysexit

 

五.返回RING3
0FFDF0304H和7FDF0304H中执行相同的物理地址,其值为:7c92e4f4h,反汇编这个地址:

7c92e4f4 c3              ret

返回至NtReadFile中。至此,整个调用过程结束。


你可能感兴趣的:(WINDOWS系统调用 和 SYSENTER系统服务调用过程)