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***函数中。
Zw函数与Nt函数的分别与联系
最新推荐文章于 2023-06-23 10:16:00 发布