已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
五、NT系统服务及其分发
5.1从应用程序的API调用到硬件
下面以一个很简单的例子,描述应用程序调用一个API到最终执行(完成和硬件相关动作)的过程,来介绍系统服务的作用:
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesWritten
);
当将参数入栈的动作完成后,程序执行的是call WriteProcessMemory指令,但此时并不会直接跳转到该函数的地址,而是在PE结构中的IAT(输入表)中对应的桩代码,在桩代码中再通过JMP指令转移到对应的地址(在应用程序加载的Kernel32.dll中),。关于PE结构不是本文的内容。
Kernel32.dll中的 WriteProcessMemory()只是对参数作出了一些处理,就直接调用Ntdll.dll中的NtWriteVirtualMemory(),这个函数被称为存根函数(有时又称为Native API),它只是简单地填写了系统服务的调用号,随后将控制权转交给KiIntSystemCall()或者KiFastSystemCall()(具体选择哪个取决于CPU情况,Nt系统有巧妙的机制保证作出正确的选择,这里不作介绍),随后KiXXSystemCall()进入内核模式,内核模式中的KiSystemService()通过NtWriteVirtualMemory()填写的调用好查系统服务表(SSDT或者SSDT_Shadow,具体是哪张取决于调用者的线程类型,详细情况在下面几节介绍),查到内核中的NtWriteVirtualMemory()的地址,在NtWriteVirtualMemory()中,完成具体的操作(检查一下参数和执行环境,再向目标进程的指定位置写入指定内容……)。随后通过KiServiceExit()返回用户模式。
如果是一个需要使用其它硬件的API(比如需要写入硬盘),内核中又会将需要请求传给相关驱动程序。
Windows NT通过系统服务的机制,使得用户层的应用程序可以调用系统服务将对硬件的直接请求转交给系统。这样既不会限制应用程序的功能,又可以保障系统的安全(应用程序无法直接操作硬件)。
图5-1描述了调用过程
5-1.png
另外需要指出的是,在用户层中调用系统服务不一定要通过系统DLL,完全可以自行调用(参考后面几节内容)。但Windows提供的系统服务接口可能会发生变化,而系统DLL提供的API是统一的,所以通过系统DLL调用系统服务可以更好地保障版本兼容性。
5.2系统调用过程
5.2.1进入内核模式
要实现具体的和硬件相关的操作,必须进入具有执行相关指令权限的内核模式。IA32架构下可以通过门机制来完成用户模式(在Windows下是RING3)到内核模式(Windows下是RING0)的切换。Windows NT使用“中断门”来实现这一过程。
如果读者对第四章还有映象,应该会记得IDT中的0x2e项为system service calls,即系统服务调用。在调试中也可以发现Int 0x2e中断的处理例程为nt!KiSystemService,即系统服务分发函数。所以,Windows NT正是通过Int 0x2e中断来调用系统服务。
调用者除了需要执行指令调用系统服务外,还需要提供服务号(在Windows NT中,服务号存储在EAX寄存器中),另外还需要在栈中存入相关参数。随后,系统会在中断处理例程中完成寄存器的存储与切换,内核栈-用户栈的切换和相关参数的拷贝工作。
Intel从Pentium II处理器开始提供快速系统服务调用功能,可以使用sysenter指令替代int 0x2e,两者所作的事情相同,但sysenter速度更快。
5.2.2系统服务的分发
在通过中断进入内核模式后,需要进行系统服务分发,即将控制权转移到指定的系统服务处理函数。Windows NT使用了名为系统服务表(SSDT)的数据结构储存各个服务存储函数的地址,其为KSERVICE_TABLE_DESCRIPTOR 结构数组,该结构定义如下:

typedef struct _KSERVICE_TABLE_DESCRIPTOR {
    PULONG_PTR Base;
    PULONG Count;
    ULONG Limit;
    PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;

需要关心的成员如下:
Base域指向系统服务例程地址数组,Number指向记录参数长度的数组。
Windows NT对于CUI线程的调用请求,使用SSDT进行分发,对于GUI线程则使用SSDT_Shadow进行分发。
SSDT_Shadow中拷贝了基本的SSDT项,还额外增加了一些Windows子系统提供的服务(因为GUI由Windows子系统负责实现)。
Windows NT存在的SSDT数量和系统版本号相关,某些版本有空余的SSDT可供第三方使用,某些版本则没有。
服务分发函数根据EAX寄存器中的服务号,先由其中第12-13位得到表的索引,得到所使用的表的基地址,再由低12位(0-11位)得到系统服务索引,然后通过该索引由Base指向的地址数组得到具体例程地址,并通过Number指向的数组查得参数长度,在从用户栈拷贝指定长度的参数后,调用对应的服务例程。
5.2.4返回用户模式
服务例程在被调用时相关参数以及被拷贝到内核栈中,然后其会尝试完成请求。之间会调用一系列内核中的函数,也可能会向驱动程序传递请求。完成这些后,服务例程会保存好结果,再调用KiSystemExit()返回用户模式。
该函数会完成寄存器的恢复和内核栈-用户栈的切换,最后通过一些机制决定是使用sysexit指令或者是iret指令返回(这取决于进入内核的方式)。
5.3关于API HOOK
在了解了应用程序实现与硬件相关功能的系统服务调用过程后,我们可以参考图5-1来讨论一下API HOOK。
API HOOK是一种很常见的截取应用程序的系统调用的手段,具体请自行搜索。基本原理是在目标指令中插入自己的指令以获得控制权。
从调用顺序来看,常见的API HOOK手段如下:
用户层(RING3)
CALL Address HOOK:直接修改目标程序指令流中调用API的指令中的地址,这种实现方式不常见,因为搜索目标地址很可能要涉及硬编码,并不好用。
IAT HOOK:修改IAT中桩代码的跳转地址,这种方式层一度流行过,不过稍显麻烦,需要对PE结构有所了解。
RING3 Inline HOOK:将跳转代码(跳转到自己处理函数)注入系统DLL中,这种方式比较方便,曾经非常流行。
Native API HOOK:将跳转代码注入Native API 中,这种方式比较“底层”。
SystemCall HOOK:注入对象换成KiXXSystemCall函数。这种方式在Ring3看起来是最“底层”的,但效率很糟糕,因为所有SystemCall过程都要被检查。
绕过用户层API HOOK其实很简单:自己执行Int 0x2e或者sysenter指令调用系统服务就可以,用不着进行任何检测,就可以轻松绕过上述钩子。
内核层(Ring0)HOOK:
SSDT HOOK:
修改SSDT中相关系统服务处理例程的地址,换成自己的函数。这种HOOK方式在Ring0 HOOK刚出现时非常流行。因为SSDT的地址是一个导出变量,SSDT_Shadow的地址也可以在一些地方得到;这种HOOK能捕捉到几乎全部Ring3模式下的请求。
但这种HOOK很容易被检测:在指定版本系统下,这些服务例程地址通常是固定的。
RING 0 Iiline HOOK:在服务例程中注入跳转代码,隐蔽性稍强,但也比较容易检测。
RING 0 Deep Iiline HOOK:修改的位置换成服务例程中较深入的位置,比如某个要实现最终功能必被调用的函数的地址,隐蔽性较强。
另外还有一些涉及驱动的请求可以通过HOOK驱动程序中的各个部位,这不是本文的讨论范围。
六、相关学习资源
本文只是初略地介绍了Windows NT系统中的几个部分,如果想要详细了解Windows NT系统,可以参考下列学习资源:
代码类:
Windows Research Kernel V1.2:这是微软提供的"Windows NT研究内核”,基于Windows NT5.2(Windows Server 2003 SP1),内含大部分内核和执行体的部分的代码,包含32位/64位版本。还提供了一套编译工具,可以在许可协议下自行修改内核并编译、运行。
详细信息请参考:XXXXXXXXXXXXXXXXXXXXXXXX/education/facultyconnection/articles/XXXXXXXXXXXXXXXXXpx?cid=2416&c1=en-us&c2=0
ReactOS:React OS通过反汇编分析Windows运行原理并自行编写代码作为实现。其能提供的代码资源是最完整的。介绍:XXXXXXXXXXXXXXXXXXXXXXX/zh/ReactOS
泄漏版本的Windows NT代码
非法泄漏Windows NT代码并不是值得肯定的行为,但这些泄漏的代码包含着许多未曾公开的内容,作为学习资源,仍是一个不错的选择。
Windows NT 4.0和Windows NT5.0(Windows 2000 SP1)的代码曾经部分泄漏,包含了一部分组件的源码。
WDK,DDK:
微软提供的驱动开发包中包含不少例子,这些例子中的某些和Windows中的驱动程序息息相关,甚至一些头文件中包含着很多函数的声明和数据结构的定义。
书籍类:
《Windows内核原理与实现》,潘爱民著
其以WRK为主,详细地介绍了Windows内部的各种机制和实现过程。另外根据该书的前言,潘爱民博士在写著时得到了阅读Windows源代码的许可。
这本书对很多数据结构和系统中的关键过程作了深入的介绍,非常适合配合WRK使用。
《Windows内核情景分析》毛德操著
以ReactOS源码为参考,相对来讲,本书的内容比较丰富,并不乏深度。但ReactOS并不能完全替代Windows NT源码。
《深入解析Windows操作系统》:戴维.所罗门等著,此书第四版有中文版,最新的第六版介绍了Windows NT6发布以来的很多情况。作者同样得到了阅读Windows源代码的许可。
与《Windows内核原理与实现》相比,这本书介绍的范围更宽一些(涉及到了IA64架构下的情况,甚至有关于WOW64的部分),但不够深入且过于抽象。
个人认为这三本著作各有特点。《Windows内核原理与实现》侧重于深入地讲解Windows NT内核(特别是WRK涉及到部分),与内核中的代码、数据结构息息相关,《Windows内核情景分析》也侧重于代码,但ReactOS虽然没有WRK权威,但也不受WRK涉及到范围限制,不过这本书似乎更侧重从用户层的角度往内核看,偏重那些和用户层关系比较大的部分;个人感觉《Windows内核原理与实现》和,《Windows内核情景分析》可以很好地互补。
至于《深入解析Windows操作系统》,虽然没上述两本深入,但是可以很好的地补充他们没有涉及到的地方(虽然其中部分内容比较冷门,比如和IA64相关的内容。
另外《英特尔® 64 和 IA-32 架构软件开发人员手册》也是需要阅读的参考资料,很多硬件机制只有在这里才能找到详尽、权威的解释,不过很遗憾它没有官方的中文版本,也找不到完整的翻译版(如果您有,请联系我),而且其中含有大量晦涩的技术术语,阅读难度比较大。
文号 / 491431

万流景仰
名片发私信
学术分 8
总主题 411 帖总回复 4593 楼拥有证书:专家 老干部 学者 机友 笔友
注册于 2009-03-15 21:53最后登录 2024-04-26 10:37
主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步

个人简介

CV

文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

插入资源
全部
图片
视频
音频
附件
全部
未使用
已使用
正在上传
空空如也~
上传中..{{f.progress}}%
处理中..
上传失败,点击重试
等待中...
{{f.name}}
空空如也~
(视频){{r.oname}}
{{selectedResourcesId.indexOf(r.rid) + 1}}
处理中..
处理失败
插入表情
我的表情
共享表情
Emoji
上传
注意事项
最大尺寸100px,超过会被压缩。为保证效果,建议上传前自行处理。
建议上传自己DIY的表情,严禁上传侵权内容。
点击重试等待上传{{s.progress}}%处理中...已上传,正在处理中
空空如也~
处理中...
处理失败
加载中...
草稿箱
加载中...
此处只插入正文,如果要使用草稿中的其余内容,请点击继续创作。
{{fromNow(d.toc)}}
{{getDraftInfo(d)}}
标题:{{d.t}}
内容:{{d.c}}
继续创作
删除插入插入
插入公式
评论控制
加载中...
文号:{{pid}}
加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}
ID: {{user.uid}}