拦截API调用来隐藏
要理解Win32 API HOOK,就需要从操作系统谈起了。
操作系统:为了实现扩展性,大多会提供各种接口用于应用程序开发使用(现在很多软件也提供了开发接口,SREng也有哦~)。作为Windows操作系统也不例外。Windows操作系统大致上可以划分为用户模式和核心模式两类。用户模式又可以划分为几个子系统:Win32子系统,POSIX、OS/2子系统等。
关于子系统的介绍,请参阅《Windows Internals 4th》,这里不做解释。由Win32子系统提供的函数被成为Win32 API。通过Win32 API,可以实现大多数Windows操作系统的基本功能,包括:文件的复制、查找、进程的创建、枚举、注册表的创建、枚举、修改等等最常用的功能。
MSDN Library或者Windows Platform SDK里面提供了所有公开的Win32 API的解释。具体可以参考 http://msdn.microsoft.com/一种不是很准确的对Win32 API的解释是:正是通过Win32 API的调用,绝大多数应用程序实现了他的所有功能(如:Microsoft Office、各种输入法、各种即时聊天工具、各种杀毒软件、各种流氓软件清除工具等等)。
实际上,基本上所有运行在Windows之上的应用程序都会不可避免的使用到Win32 API,因为创建进程、创建线程是必定会调用到Win32 API的。不过也有一些程序是例外的:比如Native应用程序(如:chkdsk.exe 磁盘扫描工具,SMSS.EXE Windows Session 管理器)等。
由于Win32 API构成了应用程序的基础,有的时候,为了能够在这个API被调用之前进行一些特殊的操作,比如参数验证等,会对这个API进行HOOK,被HOOK的Win32 API的调用顺序将变成下图虚线的部分;下图实线的部分表示正常的调用。
举一个最简单的例子:在Windows里面获取操作系统版本号的一个方法是调用GetVersion() 或GetVersionEx() 函数,这个函数是由Kernel32.DLL提供的。利用这个函数的返回值,可以返回系统里面版本号,例如,一个应用程序可以根据不同的操作系统在代码里面实现不同的功能,以SREng的插件扩充功能为例,我允许插件里面限制插件支持的最低Windows版本,如果不符合条件,那么插件管理器就不加载插件。而判定依据就是利用上述的API 函数完成的。
但是,微软在Windows XP里面引入一种叫做兼容模式的东西,当一个进程工作在兼容模式下面,微软会对一些常见的Win32 API函数进行HOOK操作,修改函数的返回值。
还是以兼容模式为例,兼容模式的修改可以通过修改文件的属性完成:
上图是Windows Vista下SREng.EXE文件的属性,可以发现一个叫做兼容模式的选项,当选中这个选项以后再运行SREng.EXE,会发现SREng.EXE对操作系统版本的检测出现了不正确的现象:
出现上述现象的原因就是由于Windows的兼容模式对SREng使用的判断操作系统版本的函数GetVersion()和GetVersionEx()函数进行了HOOK操作,修改了函数的返回值。下图是SREng 2.4 版本显示的在Windows Vista操作系统下,以Windows XP Pro SP2兼容模式下运行的SREng进程空间里面,一些被HOOK的Win32 API函数,可以发现,用于判断操作系统版本的函数GetVersion()和GetVersionEx()也在其中。
本章小结:由于有API挂接拦截的存在,Win32 API 调用者在调用Win32 API的时候就有可能发生下面的一些情况:
调用参数被修改 Win32 API返回结果被修改 其他可能正常的软件可以利用这个技术来验证参数,或者说可以利用这个技术来做一些测试相关的工作,但是对于计算机病毒来说,也可以利用这个技术来实现用户模式下文件、进程、注册表项的隐藏或修改原本需要返回的正确的值为错误来欺骗用户。