Windows 9x,NT和2000下的API 欺骗技术

英文原文:API Spying Techniques for Windows 9x, NT and 2000

链接地址:http://www.internals.com/articles/apispy/apispy.htm


通过API欺骗技术可以对应用软件和操作系统内部结构进行深入的探索。遗憾的是,无论是SDK(标准应用开发包)还是DDK(驱动程序开发包)都没有提供任何的文档或者例子来展示API Spy的功能。通过这篇文章将会尝试以这个位线索展示一些Windows应用层下的API HOOK技术。


这里有一些前提,在你坐下来去编写API欺骗程序的时候需要说明。首先,你需要确定只是对单一的API进行欺骗,还是对系统内的所有API进行欺骗。在不同的情形下,有效的步骤是不一样的。例如:假设需要编写一个应用程序拦截一个指定的进程。显然,需要一个方法监视进程的建立和终止,这个方法是受到限制的。第一个类型是对系统内的CreateProcess函数(事实上,Ansi和Unicode版本通用)进行拦截。每当一个应用程序区调用这个函数去创建一个新的进程之前,都会执行你的拦截函数,并作出一些必要的操作。


另一种类型是开发应用程序可能调用一些简单的API的监控程序。一个好的例子就是NuMega公司的BoundsChecker工具-一个可以分析API调用,并完成内存泄露和其他一些潜伏的BUG。


不论是是使用单个API的拦截还是对系统内的API进行监控,都必须选择若干API HOOK技术的一种或者几种。这篇文章通过几个部分展示了Windows下的API拦截技术,致力于展示这项技术有利和不利的一面。


DLL欺骗

这是到目前为止在Windows下API HOOK最简单的技术。举一个相关的例子,一个扫瞄电子邮件病毒的反病毒软件。一个明显的目的是这个应用程序需要挂载Winsock下的I/O函数,来完成电子邮件客户端和服务端的数据传输。


这个方法可以很容易的建立一个欺骗的DLL来完成这项任务,它包含了每一个在Winsock库中I/O函数的导出形式。如果欺骗DLL和Winsock库中的函数(wsock32.dll)拥有一样的导出函数并且和邮件应用程序放在同一个目录下,那么这种拦截机制会自动运行。当目标应用程序试图加载Winsock库时,这个欺骗DLL就替代系统那个DLL进行加载。所有的Winsock函数都会调用欺骗DLL内的导出函数。经过这些必要操作之后,这个欺骗DLL简单的把发送给Winsock的调用劫持到自己的函数内。


可能这个例子用于API HOOK显得有点简单,但是也有一个问题。虽然容易进行操作,不过还是有一个主要的缺点-在欺骗DLL里监视本地的操作,并且需要创建200多个导出函数。这是一个非常枯燥的过程,并且也一次完成,因为其中的一些函数没有足够的说明文档。


如果想要看看这方面技术的例子,可以参考Matt Pietrek's的WinInet工具,出版在1994年12月的MSJ专栏。


修改IAT

如果过去研究过API HOOK,那么可能听说过修改地址输入表IAT。这方面的优势和实现简单使的这项技术在Windows API HOOK中使用的非常普遍。


这个技术依赖在Windows PE文件格式下的32位可执行文件和DLL。对于PE文件而言,程序由很多段组成。例如:.text段保存了应用程序编译过后的代码,而.rsrc段则存储了一些资源,例如对话框,位图和工具条。


在Windows PE的所有段中,.idata段对于API HOOK特别有用。在这个段中,有一个指定的表(众所周知的地址导入表IAT),其中保存着文件偏移到被执行代码引用的输入函数名。当Windows加载可知可执行文件到内存时,来修改这个偏移,修改函数到达正确的地址。


为什么修改IAT从一开始就陷入困难?Windows可执行文件和DLL加载到内存后经常重新转移(因为冲突)。这使得不可能在可执行代码输入函数中预先设置目标调用的地址。为了确保调用能够成功的到达目标地址,在一个可执行映像加载进内存后需要Windows定位并且修改每一个调用到输入函数。显然,如此大量的工作在新进程和DLL初始化的时候要做会减慢系统速度,让使用者建立一个概念认为Windows是一个反应迟钝的操作系统。


目前Windows的可执行文件和DLLs调用输入函数传递到IAT用一个间接的JMP指令。事实是入口函数调用是"消耗",通过一个位置节省了Windows在内存传输可执行文件映像的麻烦,寻找修改的调用指令。


API欺骗怎么开始呢?Windows IAT重定向机制提供了一个很好的方法拦截API调用。通过用记录例程指定的地址重写一个指定的IAT入口,一个API拦截器能获得控制在原函数被处理机执行之前。


显然,还有其他的棘手的问题,比如拦截器的请求记录代码在内存中被执行。这些问题在下面的资源中将会讨论。


Matt Pietrek's的书"Windows 95 System Programming Secrets"包含了一个APISpy32的拦截器的源代码。这个工具最初出版是在1995年12月MSJ作为文件的一部分。一个新版本已经发布在了Matt's的网站上http://www.wheaty.net/


修改API

这是我最喜爱的挂接API函数的技术。它有天生的优点在于能够跟踪来自一个应用程序不同的位置API调用,同时要求修改只是一个单一的位置--API函数本身。


有很多方法可以用在这里。一个方法就是重定位目标API的第一个字节用断点(int3).任何调用这个函数将会产生一个异常,如果它作为一个目标进程的调试模块将会报告给你的拦截器。不幸的是,这个方法有很多问题存在。首先,Windows异常将会降低系统性能。其次的问题是涉及到Windows调用API。当一个调用器关闭的时候,它会关闭在它控制之下的所有应用程序。显然,上述行为完全不能满足你的系统范围的拦截器的需求,它必须能终止它自己在目标程序结束之前。


另一个可能的方法是修改目标应用程序用一个CPU控制传输指定(a CALL or a JMP).再一次,这有很多的问题有解决。首先,这个修改可能溢出在指令函数的结尾。如果目标API小于5个字节的话这就会发生(CALL和JMP都是5个字节长),另一个是需要经常在修改和还原之间切换拦截函数的版本。这意味着当你记录例程受到CPU控制的时候,必须保存拦截器到它先前未挂载的状态。这个请求允许API拦截发送调用到最初的函数没有记录例程产生循环。注意在CPU执行以前函数的这段时间,其他调用这个函数的例程可以从系统的其他地方传送过来。因为函数在这个期间处于无挂载状态,所以API拦截器将不会拦截这些调用。一个好的API拦截器可以利用更好的技术克服这些限制。注意下面的是些内容得到实现这个技术的更好方法。


在这种情况下,API拦截器在目标函数开始的位置放置一个JMP跳转指令,但没有在函数中设置5个字节作为内存缓冲。精确的字节数被拷贝到stub可能改变通过函数头出现的指令。5个字节没有在指令边界之内,这有必要拷贝附加的字节直到有足够的空间为Jmp指令插入。注意控制传输指定(JMPs and CALLs)需要在拷贝期间被修改以确保它们在stub执行的时候传输控制内存的正确位置。显然,执行这样一个汇编分析要反汇编的软件,前面我已经提及了,这不是一件简单的事。如果你没有被这个复杂的技术吓住并打算在你的应用程序中使用,你可能需要看一下Detours的源代码--一个API拦截库,它被Microsoft研究部的一个成员开发出来。


代码注入

懂得如何注入一块代码到另一个进程的地址空间是一件事,但是执行API拦截时间也是一个关键因素。注入在错误的时刻你的拦截器可能错过目标应用程序的调用API。这个问题尤其暴露在拦截系统范围的API时,在那样的情况下,拦截器需要在进程执行之后立刻注入它的监视DLL到进程地址空间,但是在调用拦截器的时候需要权限。最好方法就是监视CreateProcess函数的调用,当这个调用检测出来的时候,拦截器的记录例程用修改的dwCreateionFlags参数传递控制到原来的CreateProcess函数,修改的参数的值是CREATE_SUSPENDED。这样确保目标进程开始了,但是处于挂起的状态,拦截器这时能用监视DLL注入目标进程地址空间并且用ResumeThread API函数让目标进程运行起来。


其他在Windows下监视进程执行的方法在下面的段中,不幸的是,因为他们是异步类型,所以它们不容易在合适的时间注入监视代码到进程地址空间。



PS:只是翻译了一部分,更多的链接和内容,请查看原文地址。文档也是比较老的,最近需要用到部分这个地方的知识去理解HOOK,所以找了经典的文档,自己简单翻译,后面参考了看雪论坛的翻译,完全达不到信达雅的境界,但是还是希望能给他人以帮助。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值