您的位置:首页 > 运维架构 > 网站架构

[转载]Windows系统调用架构分析—也谈KiFastCallEntry函数地址的获取

2015-02-02 20:59 423 查看
原文地址:点击打开链接



为什么要写这篇文章

1. 因为最近在学习《软件调试》这本书,看到书中的某个调试历程中讲了Windows的系统调用的实现机制,其中讲到了从Ring3跳转到Ring0之后直接进入了KiFastCallEntry这个函数。

2. 碰巧前天又在网上看到了一篇老文章介绍xxx安全卫士对Windows系统调用的Hook,主要就是Hook到这个函数

3. 刚刚做完毕业设计,对使用中断来实现系统调用的方式记忆犹新。

以上原因导致我最近眼前总是出现系统调用这个词,脑海中总是出现系统调用的实现方式,所以决定写篇文章清理一下思维。本文所有举例如无明确指明,均是在Windows XP SP3系统中获得。

本文的目的是探索一下Windows目前的系统调用的实现架构,介绍一种中规中矩的获取KiFastCallEntry函数地址的方法,但是在介绍之前还是要把该解释的解释清除。


Windows API和系统调用的关系

肯定会有人说Windows API就是系统调用,系统调用就是Windwos API,是这样的么?负责任的说:不是这样的!

先从广义上来说,Windows API是对于整个Windows操作系统自身的程序代码之外的应用程序来说的,而系统调用是Windows内核对于非内核程序代码之外的Windows系统程序代码来说的。也就是说系统调用要比Windows API低一个层次。一个Windows API是一个函数,这个函数可能会使用系统调用,请注意是可能,因为并不是所有的API都需要进入内核去完成这个API的功能。


Windows内核实现文件和应用层文件

在一个安装完成的Windows操作系统中可见并有效的内核实现文件是

C:\Windows\System32\ntoskrnl.exe

C:\Windows\System32\ntkrnlpa.exe

请注意有两个内核文件,其中第二个比第一个的名字少了os多了个pa,省去的os没有任何意义,但是多出来的pa所代表的意思是PAE(物理地址扩展),这是X86CPU的一个硬件特性,Windows启动之后根据当前系统设置是否开启了PAE特性会自动选择把其中一个作为内核加载到内存中。

为什么加了这么多限定词,因为ntoskrnl.exe这个文件名并不一定是这个文件的真实名称,可以从文件属性中看到

ntoskrnl.exe原始文件名为可能为ntoskrnl.exe或者ntkrnlmp.exe

ntkrnlpa.exe原始文件名为可能为ntkrnlpa.exe或者ntkrpamp.exe

可以发现其中的不同之处就是mp,mp就是Multi-processor(多处理器,也可以理解为多核,因为IA-32架构对多核处理器的编程和多处理器的编程是相似的机制)。为什么会出现这中情况呢?因为这完全是由计算机硬件的不同配置导致的。当安装Windows操作系统的时候,Windows安装程序会自动检测机器的CPU特性,根据CPU的核心数来确定使用哪一套内核。如果是单核心就只复制ntkrnlpa.exe和ntoskrnl.exe到系统目录下,如果是多核心就复制ntkrnlpamp.exe和ntoskrnlmp.exe到系统目录下,所以如果你有一台单核心CPU的机器,有一天你换了双核的CPU却没有重新安装操作系统,那么你就不会在看到熟悉的Windows启动画面了。类似这两个文件的还有一个文件C:\Windows\System32\hal.dll,这是Windows的硬件抽象层程序文件,这个就不做具体介绍了。额外补充一个不同的硬件配置所需要的文件列表:

Standard PC

hal.dll

ntkrnlpa.exe

ntoskrnl.exe

Advanced Configuration and Power Interface (ACPI) PC

halacpi.dll---->hal.dll

ntkrnlpa.exe

ntoskrnl.exe

ACPI Uniprocessor PC

halaacpi.dll--->hal.dll

ntkrnlpa.exe

ntoskrnl.exe

MPS Uniprocessor PC

halapic.dll---->hal.dll

ntkrnlpa.exe

ntoskrnl.exe

ACPI Multiprocessor PC

halmacpi.dll--->hal.dll

ntkrpamp.exe--->ntkrnlpa.exe

ntkrnlmp.exe---->ntoskrnl.exe

Compag SystemPro Multiprocessor or 100% Compatible

halsp.dll---->hal.dll

ntkrpamp.exe--->ntkrnlpa.exe

ntkrnlmp.exe--->ntoskrnl.exe

MPS Multiprocessor PC

halmps.dll----->hal.dll

ntkrpamp.exe----->ntkrnlpa.exe

ntkrnlmp.exe--->ntoskrnl.exe

Silicon Graphics Visual Workstation

halsp.dll---->hal.dll

ntkrpamp.exe----->ntkrnlpa.exe

ntkrnlmp.exe---->ntoskrnl.exe

不论什么配置,一旦系统安装完成后,对我们来说可见的内核文件就只有两个ntoskrnl.exe和ntkrnlpa.exe。这两个文件中的代码就是运行于RING0下的内核代码,他们里面所包含了真正的系统调用的代码。我们用Dependency Walker看一下:

#define IA32_SYSENTER_CS 174H
2. #define IA32_SYSENTER_ESP 175H
3. #define IA32_SYSENTER_EIP 176H
4.
5. ULONG GetAddressOfKiFastCallEntry()
6. {
7.     ULONG dwAddress = 0;
8.     __asm
9.     {
10.         jmp func_main
11. vgdtr:
12.         _emit 0x00
13.         _emit 0x00
14.         _emit 0x00
15.         _emit 0x00
16.         _emit 0x00
17.         _emit 0x00
18.         _emit 0x00
19.         _emit 0x00
20.
21. func_main:
22.         push eax
23.         push ebx
24.         push ecx
25.         push edx
26.         mov ecx, 0x174
27.         rdmsr
28.         mov ebx, eax        //Selector offset
29.
30.         sgdt vgdtr
31.         mov edx, vgdtr
32.         add edx, 0x02
33.         mov eax, [edx]      //GDT base
34.         add ebx, eax        //Selector base
35.
36.         mov edx, ebx
37.         add edx, 0x07
38.         mov eax, [edx]
39.         shl eax, 24;
40.         mov edx, ebx
41.         add edx, 0x02
42.         mov ecx, [edx]
43.         and ecx, 0x00FFFFFF
44.         add eax, ecx        //Address CodeSegment
45.         mov ebx, eax
46.
47.         mov ecx, 0x176
48.         rdmsr
49.         add eax, ebx
50.
51.         mov dwAddress, eax
52.
53.         pop edx
54.         pop ecx
55.         pop ebx
56.         pop eax
57.     }
58.
59.     return dwAddress;
60. }


View Code

测试用驱动代码及结果如下图:



(P21)



(P22)

这个结果和我们用Windbg查看得到的是一样的。

这篇文章写的有点长,而且知识有点砸碎希望各位看过之后能理解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: