Zw函数与Nt函数的分别与联系

Ring3中的NATIVE API,和Ring0的系统调用,都有同名的ZwNt系列函数,一度让初学者感到迷糊。N久前的我,也是相当的迷糊。现在就以ZwOpenProcessNtOpenProcess函数为例,详细阐述下他们的分别和联系。
ntdll.dll导出了NtOpenProcessZwOpenProcess两个函数,我们记为ntdll!NtOpenProcessntdll!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!KiSystemServicent!KiSystemService会在参数检查、栈拷贝等操作之后,根据Ring3代码传递过来的调用号0x7A,在SSDT中查找相应的函数地址,然后调用找到的函数。对于我们的例子来说,这个函数就是内核模块的导出函数nt!NtOpenProcessnt!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!ZwOpenProcessntdll!NtOpenProcess的入口都是0x7C92D5FEntdll!ZwOpenFilentdll!NtOpenFile的入口都是0f7C92D59E。内核空间中的Zw函数,是Nt函数的一个Stup,只是mov系统调用号到eax中,转而直接调用(注意,没有像ntdll!ZwOpenProcessnt!KiSystemService去从SSDT中找到相应号码的函数再调用之,真正的实现都在Nt***函数中。下面是本人画的一个流程图,仅供参考。

 

你可能感兴趣的:(c,api)