人较笨且记性不好,故记录在此.折叠代码打不开请F5.本博中很多是转载收录其他网友的文章(原文地址请见博文末尾),所有权为原作者所有!!!
此博客已不再更新和维护,欢迎关注我的github新博客

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

  首先他们都是微软未公开的函数,之所以未公开主要是因为这些函数大部分功能太强大了,把他们公开会让一些别有用心的人利用。9x下的我不知道,NT(含2000/xp)下你可以参考《Windows NT Native API》,他们中的大部分函数几乎就从来没有变过。而几乎所有从Kenerl.dll中引出的Win32API,都是通过调用的Native API(NTDLL.DLL中导出)实现系统调用的。举一个例子:NtQuerySystemInformation 这个函数就强大到可以查询所有的系统信息,使用时需要用户拥有相当高的访问权限。

in ring3:
lkd> ? ntdll!ZwOpenProcess
Evaluate e­xpression_r: 2089999739 = 7c92dd7b
lkd> ? ntdll!NtOpenProcess
Evaluate e­xpression_r: 2089999739 = 7c92dd7b

  用dependency也可看到。
  可以看到,在ntdll中,ZwOpenProcess和NtOpenProcess其实是同一个函数,只不过拥有两个名称而已。
  也就是说,在ring3环境中,Zw***系列函数和Nt***系列函数无区别。

in ring0:
lkd> u nt!ZwOpenProcess
nt!ZwOpenProcess:
804de044 b87a000000 mov eax,7Ah
804de049 8d542404 lea edx,[esp+4]
804de04d 9c pushfd
804de04e 6a08 push 8
804de050 e8dc150000 call nt!KiSystemService (804df631)
804de055 c21000 ret 10h

lkd> u nt!NtOpenProcess
nt!NtOpenProcess:
80573d06 68c4000000 push 0C4h
80573d0b 6810b44e80 push offset nt!ObWatchHandles+0x25c (804eb410)
80573d10 e826f7f6ff call nt!_SEH_prolog (804e343b)
80573d15 33f6 xor esi,esi
80573d17 8975d4 mov dword ptr [ebp-2Ch],esi
80573d1a 33c0 xor eax,eax
80573d1c 8d7dd8 lea edi,[ebp-28h]
80573d1f ab stos dword ptr es:[edi]

  可以看得出,ZwOpenProcess函数很短,首先把0x7a(NtOpenProcess的服务号)存入eax,然后做一些保存现场的工作即KiSystemService——这个函数根据eax中的service id在SSDT中查找相应的系统服务,然后调用之。

  而NtOpenProcess函数很长(反汇编结果只是一部分),事实上,NtOpenProcess便是真正执行打开进程操作的函数(在r0中通常称为服务,或例程),所以,若在驱动中直接调用Nt系列函数,是不会经过SSDT的,也就不会被SSDT HOOK所拦截。

简单总结如下:
  R3下无论如何调用,均无法绕过SSDT HOOK,R0下调用Nt*可以绕过SSDT HOOK。rtl** 函数是windows ddk提供的编写驱动的函数。


我的总结:

    由以上反汇编Zw***可知,Zw***代码内部是通过SSDT中的对应Nt***索引号查找到真正Nt***执行代码的入口地址。 


  大多数win32的api函数都是包装了这些zwxxx api和ntxxx api实现的。 
     在用户模式下,这两种形式的本机api是相同的,只是ntdll.dll中相同入口点的两个不同符号。   
     在内核模式下,代码依靠ntoskrnl.exe来连接,不再是ntdll.dll。这是,zwxxx的函数入口点含有来自于ntdll.dll的一份拷贝。ntxxx的函数入口点则含有系统服务的实际实现。

 

【参考资料 感谢作者】
1、Nt**、Zw**和Rtl** 开头的函数介绍 

posted on 2012-01-22 17:35  子坞  阅读(3406)  评论(0编辑  收藏  举报