生活在ring3和ring0的Native API

朋友,你用过Native API函数吗?如果你接触过,也许你知道一个事实:Native API函数名在两个不同的模块里存在重名现象。形象地来说,在Ring3层有一个名字叫NtOpenFile的函数,在Ring0层,也有一个名字叫做 NtOpenFile的函数。他们说处的地方不一样,而且实现也不一样。不仅仅是NtOpenFile,所有的Native API函数都是如此。众所周知重名有可能引起混乱,就像一个家里的双胞胎,本来就难分你我,如果连名字也一样,岂不是神仙也分不清了?但幸运的是,这兄弟 两个从小就被分开来了,而且有专门的法律规定,他们永远不可以在同一个地方相见。这真是妙哉,妙哉!所以即使他们重名的话,也不会有错误发生了。其中哥哥 永远只能呆在Ring0的地方,弟弟永远只能呆在Ring3的地方。有时为了方便,人们也会讨巧地把他们叫成:Ring0的某某,Ring3的某某。
    上面只是一个简单的故事,让我们回到Native API上来。Native API往往功能强大,常常在我们使用了一大堆Win32 API的时候,用一个合适的Native API就能把问题轻松解决。而且更有些时候,在使用Win32函数,永远不能得到合适结果的时候,忽然有好心人告诉你:某一个叫做Native API的地方,有一个函数名叫×××,它能帮你解决问题。哈哈,愁苦顿解!
    如果可能的话,人人都想取得权力,甚至控制权力。Native API也不例外,别人都想拥有它的力量为己所用。在众多的Hook技术中,被尝试得最多的,或许就是Native API吧!比如以前写过进程隐藏的程序,用的方法就是hook函数NtQuerySystemInformation。Native API的功能所以这么强大,究其原因吧,在Ring3的人们眼里,Native API就是Ring3层的底层!
    许多人喜欢举CreateFile的函数,我们也用它来说话,耳熟能详嘛!用户调用Win32函数CreateFile,CreateFile做了一点点 的处理后,最根本的实现却并不亲自做而是调用ZwCreateFile函数,ZwCreateFile也是一样,做了一些处理,最根本的实现也不亲自做而 是继续委托给了NtCreateFile函数。而接力棒到了NtCreateFile之后,在Ring3层它就再也没有后继者了。不想进入烦人的 Ring0层的程序员,这里就已经到达终点了。
    我们试着来分析hook人员的战斗历程吧。最原始的时候,所有的人都很老实,有一些人因为技高一筹发明了Hook技术,世界从此不太平。起先他们只对 CreateFile进行自己的处理,加入自己的一些小聪明并且得意洋洋。很久之后有人不满起来,怒声怒气地骂道:你什么东西,我每秒钟都要用 CreateFile无数次,每次都被你这么捣乱,气死我也!我难道非用CreateFile不可吗?Ring3层里面,我还有ZwCreateFile 可用呢!于是就有人从此用起了ZwCreateFile来,并且也用得很开心。Hook者见此情况非常不爽,心想你以为这样就能逃开我的魔掌了 吗?ZwCreateFile我照样Hook不误!他这么说着,很快就把ZwCreateFile也Hook掉了。过了不久被Hook者发现了此情况又极 其不爽起来了,他们百般寻找,找到了NtCreateFile,发现他更加底层,于是就用起来NtCreateFile来。Hook者紧跟其后,发现 NtCreateFile是ntdll.dll中的函数,就对她研究再三并最终把他也Hook掉了。至此,被Hook者在Ring3层虽掘地三尺,却再也 找不到更底层的函数可以让他们来逃避那把阴险的钩子了。
    对!Ring3层的Native API存在于ntdll.dll模块之中。对它的Hook有好几种成熟的技术,流布于网络之中。我所熟知的一种是遍历所有模块的ITA表,把对应的函数入 口地址该掉。用这种方法的时候,同时要借助Windows消息钩子,因为系统中的模块进进出出的,你要对每一个新加载的模块进行Hook,更改其中的 ITA入口地址。另一种是分析ntdll.dll的PE结构,找到你要Hook的函数的地址,在他的入口处加上你的JMP代码。
    Ring3层这块地方,我们暂时到此一游结束。在进入Ring0层之前,我们回顾一下Native API兄弟俩。我们已经知道他们是永远不能相见的了,但其实他们有联系的途径。要知道他们毕竟是兄弟俩,他们携手完成了一连串艰巨的任务。弟弟在 Ring3层监视一切,然后把消息传入Ring0层的哥哥那里,让他处理。那个在中间传消息的人,叫做SSDT!
    Ring0层中的Native API在哪里呢?在模块ntoskrn.exe(根据OS版本不同,这个名字会不一样)中。SSDT是Ring0层中的一个共有数据结 构,ntoskrn.exe导出了一个变量:KeServiceDescriptorTable,通过这个变量谁都能找到SSDT。SSDT的任务就是负 责Native API哥俩的联络工作——中间人。传递的消息(Native API函数)数量是一定的,大概一百多种。Ring0层中的Native API在之家的门口为这百来种消息分别设置了一个处理机并编了号,SSDT有一张信箱地址表能查到消息对应的号码。如果不出问题的话,一切都能运行得很 好,有条不紊。
    在这一片和谐之中,不和谐的Hook者出现了。正常的秩序注定要被打乱!Hook者是高明的窃贼。他有两种方案实施他的hook。
    第一种是改变SSDT消息地址表。SSDT不是一个很负责人的人,平时就把那张表放在自家门口,谁都可以来参观。参观当然没有问题,可要是遇到Hook者 这样的人,可就惨了。Hook者随身携带着纸笔和橡皮,他首先在消息表上找到自己要动手脚的消息地址(即Native API函数地址),把它用纸笔抄写下来,然后用橡皮把消息表中原来的地址擦掉,写上自己的新的地址。Hook者瞄着四周无人,得心应手地干完一切,然后吹 着口哨走掉了。世界静悄悄,没有人发现发生了什么变化。当SSDT回来的时候,他也无知无觉,他依旧刻板地照着消息表上的地址发送着消息,其中一些,就被 错发进了hook者那里去了,他也放好了自己的处理机在那里等待着。
    第二种更绝,改变Native API函数,也就是改变了Native API放在家门口的处理机的构造。一般的做法是,Hook着在函数的一开始,放置一条JMP指令,让他跳到自己的处理流程中去,然后再回过来执行原函数中的处理。
    这两种方案,到目前位置,都已经变得非常成熟了。反Hook者为此也做了一些措施。比如对第一种改变SSDT地址的下三滥手法,反Hook者往往会预先保 存好一个正确的地址表,每隔一段时间,就从头到尾检查一下SSDT中的地址表是否被篡改了,如果篡改了就改回来。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值