http://hi.baidu.com/453549064/blog/item/9697bace6df9d434f8dc6197.html
Ring3 中的NATIVE API ,和Ring0 的系统调用,都有同名的Zw 和Nt 系列函数,一度让初学者感到迷糊。N 久前的我,也是相当的迷糊。现在就以ZwOpenProcess 和NtOpenProcess 函数为例,详细阐述下他们的分别和联系。
ntdll.dll 导出了NtOpenProcess 和ZwOpenProcess 两个函数,我们记为ntdll!NtOpenProcess 和ntdll!ZwOpenProcess 。仔细看一下,会发现他们的入口点实际上都是一样的,这就是说,ntdll!ZwOpenProcess 仅仅是ntdll!NtOpenProcess 函数的别名而已,实现如下:
ZwOpenProcess
.text:7C92D5FE mov eax, 7Ah ; NtOpenProcess
.text:7C92D603 mov edx, 7FFE0300h
.text:7C92D608 call dword ptr [edx]
.text:7C92D60A retn 10h
7FFE0300h 处是ntdll!KiFastSystemCall 的入口,ntdll!KiFastSystemCall 会保存起当前的栈指针,然后通过引发0x2e 中断,陷入内核。
当触发0x2e 中断后,CPU 将执行环境切换到Ring0 状态,然后去调用内核模块的0x2e 处理例程nt!KiSystemService 。nt!KiSystemService 会在参数检查、栈拷贝等操作之后,根据Ring3 代码传递过来的调用号0x7A ,在SSDT 中查找相应的函数地址,然后调用找到的函数。对于我们的例子来说,这个函数就是内核模块的导出函数nt!NtOpenProcess 。nt!NtOpenProcess 才是真正的打开进程实现函数。但是内核模块也导出了nt!ZwOpenProcess ,这个nt!ZwOpenProcess ,有什么用处呢?会不会像ntdll!ZwOpenProcess 一样,也仅仅是ntdll!NtOpenProcess 的一个别名?实际上,nt!ZwOpenProcess 并不仅仅是nt!NtOpenProcess 一个别名,我们可以看一下nt!ZwOpenProcess 的实现:
kd> u nt!ZwOpenProcess
nt!ZwOpenProcess:
804fede8 mov eax,7Ah
804feded lea edx,[esp+4]
804fedf1 pushfd
804fedf2 push 8
804fedf4 call nt!KiSystemService (8053d891)
804fedf9 ret 10h
与ntdll.ZwOpenProcess 是不是很接近?nt!ZwOpenProcess 也只是让nt!KiSystemService 调用SSDT 中的第0x7A 号函数,他自己本身没有进行任何打开进程的实现。
到这儿,就可以总结一下了:用户空间中的Zw*** 和Nt*** 的实现都是一样的,比如ntdll!ZwOpenProcess 和ntdll!NtOpenProcess 的入口都是0x7C92D5FE ,ntdll!ZwOpenFile 和ntdll!NtOpenFile 的入口都是0f7C92D59E 。内核空间中的Zw 函数,是Nt 函数的一个Stup ,只是mov 系统调用号到eax 中,转而直接调用(注意,没有像ntdll!ZwOpenProcess )nt!KiSystemService 去从SSDT 中找到相应号码的函数再调用之,真正的实现都在Nt*** 函数中。下面是本人画的一个流程图,仅供参考。