Windows API的系统调用过程通过KiFastSystemCall或int 2e进入内核,本文仅对XP上的KiFastSystemCall进行浅析。

  以ntdll!ZwCreateProcessEx为例:



  Eax中保存系统调用号,此处ZwCreateProcessEx的为30h;Edx是SharedUserData!SystemCallStub的地址,里面保存着KiFastSystemCall的地址。SharedUserData总是存放在0x7ffe0000处,其偏移0x300处正是SystemCall。





  证实下0x7ffe0300处是否真保存着KiFastSystemCall的地址:



  Sysenter时eax中保存着系统调用号,edx中保存着用户空间线程栈栈顶地址即保存着ZwCreateProcessEx中call KiFastSystemCall的返回地址,那么edx+4保存着call ZwCreateProcessEx的返回地址,edx+8为ZwCreateProcessEx的第一个参数,以此类推。

  Sysenter将会从MSR寄存器组中加载cs:eip和ss:esp令cs=IA32_SYSENTER_CS、eip=IA32_SYSENTER_EIP、ss=IA32_SYSENTER_CS+8、esp=IA32_SYSENTER_ESP,这些值均在系统初始化时固定下来。

代码:
0: kd> u 7c92e514
ntdll!KiFastSystemCallRet:
7c92e514 c3              ret    ; 与call dword ptr [edx]相对应 lkd> rdmsr 174
msr[174] = 00000000`00000008  ; cs=0x0008 ss=0x0010
lkd> rdmsr 175
msr[175] = 00000000`f78b3000  ; esp=0xf78b3000 DPC Stack
lkd> rdmsr 176
msr[176] = 00000000`804de89f  ; eip=0x804de89f KiFastCallEntry
sysenter切换堆栈时是从用户栈切换到DPC栈,这是因为MSR寄存器中的值是操作系统安排好的固定的值,它与具体的线程上下文无关,所以需要在DPC栈中再切换到线程的内核栈。 nt!KiFastCallEntry:
804de89f b923000000      mov     ecx,23h  ; KGDT_R3_DATA 0x23 = 0x20 + 011b(CPL Ring3)
804de8a4 6a30            push    30h    ; KGDT_R0_PCR  0x30 = 0x30 + 000b(CPL Ring0), DPC Stack
804de8a6 0fa1            pop     fs      ; DPC Stack
804de8a8 8ed9            mov     ds,cx
804de8aa 8ec1            mov     es,cx
804de8ac 648b0d40000000  mov     ecx,dword ptr fs:[40h]    ; fs Base:ffdff000 Limit:1fff Data RW, KPCR 0x40处为TSS Ptr32 _KTSS
804de8b3 8b6104          mov     esp,dword ptr [ecx+4]    ; KTSS 0x4处为Esp0 Uint4B, Ring0下的esp
804de8b6 6a23            push    23h      ; 此时已在内核堆栈, Ring3下的ss, KTRAP_FRAME.HardwareSegSs
804de8b8 52              push    edx      ; Ring3下的esp, KTRAP_FRAME.HardwareEsp
804de8b9 9c              pushfd    ; eflags  ; KTRAP_FRAME.EFlags
804de8ba 6a02            push    2
804de8bc 83c208          add     edx,8          ; Ring3堆栈的参数
804de8bf 9d              popfd              ; 初始eflags为2, 即各位清零
804de8c0 804c240102      or      byte ptr [esp+1],2    ; 4字节eflags第二个字节的IF中断允许位置1
804de8c5 6a1b            push    1Bh          ; KGDT_R3_CODE 0x1B = 0x18 + 011b(CPL Ring3), KTRAP_FRAME.SegCs
804de8c7 ff350403dfff    push    dword ptr ds:[0FFDF0304h]    ; KTRAP_FRAME.EIP, 0x7ffe0000与0xffdf000映射到同一块物理内存, 0xffdf0304处存放的是KiFastSystemCallRet
804de8cd 6a00            push    0    ; KTRAP_FRAME.ErrCode
; 以下四个寄存器从Ring3到Ring0没修改过, 直接保存
804de8cf 55              push    ebp  ; KTRAP_FRAME.Ebp
804de8d0 53              push    ebx  ; KTRAP_FRAME.Ebx
804de8d1 56              push    esi  ; KTRAP_FRAME.Esi
804de8d2 57              push    edi  ; KTRAP_FRAME.Edi
804de8d3 648b1d1c000000  mov     ebx,dword ptr fs:[1Ch]    ; 指向自己的指针, 头部即是TIB
804de8da 6a3b            push    3Bh  ; KTRAP_FRAME.SegFs, fs Base:00000000 Limit:fff Data RW, Ring3
804de8dc 8bb324010000    mov     esi,dword ptr [ebx+124h]  ; KPCR.SelfPcr->PrcbData.CurrentThead Ptr32 _KTHREAD
804de8e2 ff33            push    dword ptr [ebx]      ; KTRAP_FRAME.ExceptionList, TIB的头部即是ExceptionList
804de8e4 c703ffffffff    mov     dword ptr [ebx],0FFFFFFFFh
804de8ea 8b6e18          mov     ebp,dword ptr [esi+18h]  ; KTHREAD.InitialStack Ptr32 Void
804de8ed 6a01            push    1    ; KTRAP_FRAME.PreviousPreviousMode
804de8ef 83ec48          sub     esp,48h    ; 预留KTRAP_FRAME中Eax到DbgEbp的空间
804de8f2 81ed9c020000    sub     ebp,29Ch    ; ...
804de8f8 c6864001000001  mov     byte ptr [esi+140h],1    ; KTHREAD.PreviousMode
804de8ff 3bec            cmp     ebp,esp
804de901 0f8565ffffff    jne     nt!KiFastCallEntry2+0x25 (804de86c)
804de907 83652c00        and     dword ptr [ebp+2Ch],0    ; KTRAP_FRAME第12个(0x2C/4+1)参数Dr7
804de90b f6462cff        test    byte ptr [esi+2Ch],0FFh  ; KTHREAD.DebugActive
804de90f 89ae34010000    mov     dword ptr [esi+134h],ebp  ; KTHREAD.TrapFrame Ptr32 _KTRAP_FRAME
804de915 0f8535feffff    jne     nt!Dr_FastCallDrSave (804de750)  ; if(KTHREAD.DebugActive != 0) ...
804de91b 8b5d60          mov     ebx,dword ptr [ebp+60h]
804de91e 8b7d68          mov     edi,dword ptr [ebp+68h]
804de921 89550c          mov     dword ptr [ebp+0Ch],edx    ; 将Ring3参数地址赋给KTRAP_FRAME.DbgArgPointer
804de924 c74508000ddbba  mov     dword ptr [ebp+8],0BADB0D00h  ; KTRAP_FRAME.DbgArgMark = 0xBADB0D00
804de92b 895d00          mov     dword ptr [ebp],ebx      ; KTRAP_FRAME.DbgEbp = KTRAP_FRAME.Ebp
804de92e 897d04          mov     dword ptr [ebp+4],edi      ; KTRAP_FRAME.DbgEip = KTRAP_FRAME.Eip
804de931 fb              sti
; 当调用KeServiceDescriptorTableShadow中的系统服务时, eax是系统调用号再加0x1000
804de932 8bf8            mov     edi,eax
804de934 c1ef08          shr     edi,8
804de937 83e730          and     edi,30h
804de93a 8bcf            mov     ecx,edi
; 经过以上4条指令后, 若ecx为0则为调用KeServiceDescriptorTable中的系统服务, 否则ecx为0x10调用KeServiceDescriptorTableShadow中的系统服务
804de93c 03bee0000000    add     edi,dword ptr [esi+0E0h]    ; edi = KTHREAD.ServiceTable + 0x00或0x10
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)    ; KeServiceDescriptorTable
804de957 648b0d18000000  mov     ecx,dword ptr fs:[18h]    ; _NT_TIB地址, 这里也是_TEB的地址了?
804de95e 33db            xor     ebx,ebx
804de960 0b99700f0000    or      ebx,dword ptr [ecx+0F70h]  ; TEB.GdiBatchCount
804de966 740a            je      nt!KiFastCallEntry+0xcf (804de972)    ; KeServiceDescriptorTable
804de968 52              push    edx  ; Ring3参数地址
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]    ; KeServiceDescriptorTable直接跳转到这来, ++KPCR.KPRCB.KeSystemCalls
804de979 8bf2            mov     esi,edx
804de97b 8b5f0c          mov     ebx,dword ptr [edi+0Ch]  ; SSDT参数表的地址
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    ; 参数以DWORD大小拷贝
804de98d 8bfc            mov     edi,esp
804de98f 3b35d48e5680    cmp     esi,dword ptr [nt!MmUserProbeAddress (80568ed4)]
804de995 0f83a8010000    jae     nt!KiSystemCallExit2+0x9f (804deb43)    ; 若参数地址超过用户空间地址(0x7fff0000)
804de99b f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
804de99d ffd3            call    ebx    ; 调用!
804de99f 8be5            mov     esp,ebp  ; 恢复堆栈到只有KTRAP_FRAME时
804de9a1 648b0d24010000  mov     ecx,dword ptr fs:[124h]
804de9a8 8b553c          mov     edx,dword ptr [ebp+3Ch]
804de9ab 899134010000    mov     dword ptr [ecx+134h],edx    ; KPCR.KPRCB.CurrentThread->TrapFrame = KTRAP_FRAME.Edx nt!KiServiceExit:
804de9b1 fa              cli
804de9b2 f7457000000200  test    dword ptr [ebp+70h],20000h        ; eflags是否是Virtual-8086 Mode
804de9b9 7506            jne     nt!KiServiceExit+0x10 (804de9c1)    ; 非Virtual-8086 Mode则跳
804de9bb f6456c01        test    byte ptr [ebp+6Ch],1
804de9bf 7456            je      nt!KiServiceExit+0x66 (804dea17)    ; KTRAP_FRAME.SegCs, CPL为Ring0则跳
804de9c1 648b1d24010000  mov     ebx,dword ptr fs:[124h]        ; 非Virtual-8086 Mode, 以及下面的交付APC, 跳到这来
804de9c8 c6432e00        mov     byte ptr [ebx+2Eh],0          ; KPCR.KPRCB.CurrentThread->Alerted = 0
804de9cc 807b4a00        cmp     byte ptr [ebx+4Ah],0
804de9d0 7445            je      nt!KiServiceExit+0x66 (804dea17)    ; if(KPCR.KPRCB.CurrentThread->ApcState.UserApcPending == 0)跳
804de9d2 8bdd            mov     ebx,ebp
804de9d4 894344          mov     dword ptr [ebx+44h],eax    ; KTRAP_FRAME.Eax, 系统调用号
804de9d7 c743503b000000  mov     dword ptr [ebx+50h],3Bh    ; KTRAP_FRAME.SegFs = 0x3B
804de9de c7433823000000  mov     dword ptr [ebx+38h],23h    ; KTRAP_FRAME.SegDs = KGDT_R3_DATA
804de9e5 c7433423000000  mov     dword ptr [ebx+34h],23h    ; KTRAP_FRAME.SegEs = KGDT_R3_DATA
804de9ec c7433000000000  mov     dword ptr [ebx+30h],0      ; KTRAP_FRAME.SegGs = 0
804de9f3 b901000000      mov     ecx,1
804de9f8 ff152c904d80    call    dword ptr [nt!_imp_KfRaiseIrql (804d902c)]    ; 提升IRQL
804de9fe 50              push    eax
804de9ff fb              sti
804dea00 53              push    ebx  ; PKTRAP_FRAME
804dea01 6a00            push    0    ; Reserved
804dea03 6a01            push    1    ; UserMode
804dea05 e8f7f3ffff      call    nt!KiDeliverApc (804dde01)    ; 交付APC
804dea0a 59              pop     ecx  ; 原来的IRQL
804dea0b ff1530904d80    call    dword ptr [nt!_imp_KfLowerIrql (804d9030)]    ; 降回原来的IRQL
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]    ; KTRAP_FRAME.SegCs CPL为Ring0, 以及无用户APC等待处理, 跳到这来
804dea1b 648b1d50000000  mov     ebx,dword ptr fs:[50h]
804dea22 64891500000000  mov     dword ptr fs:[0],edx      ; KPCR.NtTib.Exception = KTRAP_FRAME.ExceptionList
804dea29 8b4c2448        mov     ecx,dword ptr [esp+48h]
804dea2d 648b3524010000  mov     esi,dword ptr fs:[124h]
804dea34 888e40010000    mov     byte ptr [esi+140h],cl      ; KPCR.KPRCB.CurrentThread->PreviousMode = KTRAP_FRAME.PreviousPreviousMode
804dea3a f7c3ff000000    test    ebx,0FFh
804dea40 7579            jne     nt!KiSystemCallExit2+0x17 (804deabb)    ; if(KPCR.DebugActive != 0) ...
804dea42 f744247000000200 test    dword ptr [esp+70h],20000h
804dea4a 0f8506090000    jne     nt!Kei386EoiHelper+0x12c (804df356)    ; 非Virtual-8086 Mode则跳 ;;;;;;;;;;;;;;;;;;;;;;;;;nt!Kei386EoiHelper+0x12c;;;;;;;;;;;;;;;;;;;;;;;;;
nt!Kei386EoiHelper+0x12c
804df356 83c43c          add     esp,3Ch    ; 指向KTRAP_FRAME.Edx
804df359 5a              pop     edx
804df35a 59              pop     ecx
804df35b 58              pop     eax
804df35c 8d6554          lea     esp,[ebp+54h]  ; 指向KTRAP_FRAME.Edi
804df35f 5f              pop     edi
804df360 5e              pop     esi
804df361 5b              pop     ebx
804df362 5d              pop     ebp
804df363 66817c24088000  cmp     word ptr [esp+8],80h
804df36a 7706            ja      nt!Kei386EoiHelper+0x148 (804df372)    ; if(KTRAP_FRAME.SegCs > 0x80), 则跳. 0x80后的GDT不能用于cs
804df36c 83c404          add     esp,4      ; 指向KTRAP_FRAME.Eip
804df36f cf              iretd    ; pop KTRAP_FRAME.Eip, KTRAP_FRAME.SegCs, KTRAP_FRAME.EFlags

对XP上的KiFastSystemCall进行浅析的更多相关文章

  1. windows XP上实现python2.7.5和python3.4.3共存

    windows XP上实现python2.7.5和python3.4.3共存过程记录: 1. 首先安装python2.7.5和python3.4.3,两个版本安装顺序不分前后; 2. 检查系统环境变量 ...

  2. 解决msi文件在XP上安装未完成(提示安装程序被中断,未能安装app。需要重新启动该安装程序进行重试)的问题。

    如图所示,我利用Visual Studio 2015制作了一个小程序.基于.Net 4.0.用VS的Install扩展,新建Install项目进行打包.打包为.msi文件.该安装文件在已经安装了 .N ...

  3. cefsharp在xp上运行

    今天遇到一个坑.也是自己英语不足的体现.在xp上运行cefsharp.wpf. 查询了各种资料.按照说明一步一步的操作,都没有解决xp上运行cefsharp.wpf. 而且在xp上调试都不知道错误在哪 ...

  4. 【转】VS2012编译出来的程序,在XP上运行,出现“.exe 不是有效的 win32 应用程序” “not a valid win32 application”

    原文网址:http://www.cnblogs.com/Dageking/archive/2013/05/15/3079394.html VS2012编译出来的程序,在XP上运行,出现“.exe 不是 ...

  5. win7 64位如何共享XP上的打印机?

    这个问题看似很简单,但是一旦你遇到了,就会发觉不是想象的那么简单. 除了网上能搜到的一些设置之外,这里还有几个诀窍: 1.首先你必须准备你的打印机的64位驱动程序 2.你在win7上必须采用添加本地打 ...

  6. vs2012+ winform+.net4.0发布如何在xp上运行

    今天在英文版vs2013打包发布4.0(非4.0 client)的winform时,遇到了在xp上无法运行的情况,.net framework 4.0在xp上已安装.在打包前,winform工程,即菜 ...

  7. 发布Qt Quick桌面应用程序的方法(使得planets在XP上运行)

    发布Qt Quick桌面应用程序的方法 Qt是一款优秀的跨平台开发框架,它可以在桌面.移动平台以及嵌入式平台上运行.目前Qt 5介绍程序发布的文章帖子比较少.大家又非常想要知道如何发布Qt应用程序,于 ...

  8. C# 全局Hook在xp上不回调

    最近做了个捕捉全局鼠标,获取目标窗体内的控件文本信息,点击的按钮信息.用的全局钩子.在win10上运行正常,部署到xp系统上就没有反应.查了些资料,解决了此问题. 原本安装钩子的写法如下: Nativ ...

  9. 在XP上安装WinPython最新版本

    2015年3月30日星期一 16:01:47     晴 WinPython 新版本不再支持Windows XP平台,会出现错误提示WindowsError 127. 按照官网论坛上的解决方案(htt ...

随机推荐

  1. Python匹马行天下之运算符

    什么事运算符? 本章节主要说明Python的运算符.举个简单的例子 4 +5 = 9 . 例子中,4 和 5 被称为操作数,"+" 称为运算符. Python语言支持以下类型的运算 ...

  2. 【POJ】2492 A Bug's Life

    题目链接:http://poj.org/problem?id=2492 题意:给你n个虫子,m组实验.让你帮科学家找一下有没有虫子是同性恋. 题解:假设x是一个性别,x+n为另一个性别.如果在同性的集 ...

  3. Python+Django+SAE系列教程6-----本地配置Django

    前五章.我们介绍了Python的语法,本章開始介绍Django. Python的Web框架有非常多,有Django.web2py.tornado.web.py等.我们这里选 则Django.至于这些框 ...

  4. 解决OCX 在 非开发电脑上注册出错的问题

    这几天遇到一个问题,就是在我自己电脑上开发的OCX 放在其他电脑上居然注册失败,管理员运行也不行,老是会蹦出这样的错误,最后呢终于让我找到一个线索就是在开发电脑上可以安装,在无开发环境上很大概率安装失 ...

  5. "_CMTimeGetSeconds", referenced from:

    CMTime is defined in the CoreMedia.framework. Add that framework to your project.

  6. 【学术篇】SPOJ QTREE 树链剖分

    发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能 ...

  7. HLS 视频加密小记

    我是在ubuntu中,安装好了 ffmpeg 加密用的 key(生成一个encrypt2.key文件) openssl rand 16 > encrypt2.key 另一个是 iv(生成一段字符 ...

  8. Scala 方法与函数简单记录

    /** * Scala 方法与函数 * Scala 有方法与函数,二者在语义上的区别很小.Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量.换句话来说在类中定义的函数即是方法 */ o ...

  9. python2与python3编码

    #coding:utf8#一#1.在python2中,默认以ASCII编码chcp 936import sysprint sys.getdefaultencoding()# ascii#str:byt ...

  10. SQL Server 添加数据库没有权限等

    { 在安装好sql 后 第一次需要用windows 方式登陆 1.创建一个宁外一个登陆名登陆 在安全->登陆名 2.给此登陆属性的服务器角色添加sysadmin权限 //尽情享受!!! }