5.3 定位未公开的API函数
正如我们前边已经提到过的那样,这一章里我们将以一组未公开的Windows API函数为例,实践你的逆向工程技巧。在介绍这组你将要逆向的API函数之前,我先简单说一下我是怎样发现这组API的,以及通常要怎样才能在系统中找到这种未公开的函数或API——无论这些函数或API是操作系统的一部分还是其他的第三方代码库的一部分。
5.3.1节将讲述逆向未公开代码第一步:怎样发现这种未公开的API函数并找到使用这些API函数的代码。
我们要找什么?
一般来说,只有我们有需求的时候才会去找未公开的代码!你需要实现什么功能?究竟哪个软件组件可能会提供这一功能?你需要了解有关这个程序的一些总体信息,这会非常有用。你要知道构成程序的几个关键的可执行模块,并熟悉这些模块之间的接口。二进制模块间的接口可以简单地通过转储来导入导出目录(详见第3章)。
在这个特别的案例中,我决定要找非常有感兴趣的Windows API来剖析,我知道在Windows系统中大多数用户模式下的服务是在NTDLL.DLL中实现的(因为这里是实现Windows本地API的地方),因此我转储了NTDLL.DLL的导出目录,并凭借眼力在这个目录中查找与服务有关的API函数组(主要是根据它们的函数名)。
当然,在某种程度上讲这是一个不太常见的情况,因为在大多数情况下,你不会只是因为这些API没有公开就去搜寻它们(除非你觉得使用未公开的API很酷,或者只是想把这当作一项挑战来做)——一般来说,你都会大致有一个明确的目标。在这种情况下,你可能是想在导出列表中搜索相关的关键词。打个比方,你想找某种专门用于内存分配的API函数。这时,你就应该用诸如memory、alloc之类的关键词来搜索NTDLL.DLL(或者是其他你怀疑可能实现了你要找的API的DLL)的导出表。
一旦你找到了一个未公开的API函数,以及导出这个API的DLL的名称,你就应该找找使用这个API的二进制可执行文件了。寻找调用这个API的可执行程序的目的有两个。首先,它可能会向你提供一些该API的附加信息。其次,它为你提供一个有关怎样使用这个API的“活生生”的例子,以及这个API接收什么输入数据和返回什么输出。如果能在学习怎样使用一个函数的时候,在真实的代码中找到一个使用范例,你会觉得如获至宝。
可以使用好几种方法来定位API函数的代码。最常见的方法是用Numega SoftICE和Microsoft的WinDbg之类的内核模式调试器。内核模式调试器使我们在整个系统范围内寻找某一特定函数的调用变得非常简单,即使你要找的不是内核模式函数也可以。基本思路是:你可以在整个系统范围内设置一个断点,当任何一个进程调用这个函数时系统就会停下来。这就大大简化了你寻找使用特定函数的代码这一过程。从理论上讲,你也可以用用户级的调试器来做类似的工作,比如OllyDbg,但效果要比用内核级模式的调试器差很多,因为用户模式的调试器只能显示当前你正在调试的进程内的调用。






