logo资料库

API hook详解.pdf

第1页 / 共3页
第2页 / 共3页
第3页 / 共3页
资料共3页,全文预览结束
API 拦截(API HOOK)技术及应用 常用的 API Hook(截取 API,或函数钩子)有两种方式:陷阱式、改引入表式。在 Windows 9x、WindowsNT/2000 这两个系统中的 API Hook 代码完全不同。就 Windows 9x 而言,16 位 DLL 与 32 位 DLL 的 API Hook 代码也完全不相同。 API HOOK 入门 API Hook 是一项有趣而实用的 Windows 系统编程技术,应用领域十分广泛,屏幕取词、 内码转换、屏幕翻译、中文平台、网络防火墙、串口红外通信或 Internet 通信的监视等,都 涉及到了此项技术。 API Hook 就是钩住 API,钩就是绕弯的意思,即让 API 函数的调用先绕一个弯路,在 它执行之前,先做一些“预处理”,这样我们就可以监视或定制某个 Win32 API 的调用,以 实现一些特殊的功能。至于具体可以实现些什么样的功能,就取决于程序设计者的想象力了。 在很多情况下,想监视或改变某个应用程序的一些特定的操作,但是该应用程序却没 有提供相应的接口,而又几乎不可能得到其源代码。因为大多数 Windows 应用程序的操作 很大程度上依赖于 API,所以可以采用 API Hook 的方式来试图监视和改变应用程序的行为。 常用的 API Hook 有两种方式:陷阱式和改引入表式。API Hook 的运行平台有三种: Windows 9x 的 16 位 DLL、Windows 9x 的 32 位 DLL 和 Windows NT/2000 的 32 位 DLL。 其关系如表 7-1 所示。 表 7-1 API Hook 的方式 方式 16 位 Windows 9x 32 位 Windows 9x Windows NT/2000 陷阱式 改引入表式 √ × ― Ο √ √ 其中,×表示不能实现;Ο表示只对指定模块有效,对整个进程或整个操作系统无效;― 表示在 VC 下可以实现,在 C++Builder/Delphi 下很难实现;√表示可以实现。 表 7-2 列出了两种方式各自的优缺点。 优点 可以 Hook 所有函数 易于实现 缺点 要避免“重入”问题 系统 API 有时候会漏网 方式 陷阱式 改引入表式 陷井式 API HOOK 原理 Windows NT/2000 陷阱式 API Hook 的工作原理如图 1 所示。其工作过程如下: (1)加载陷阱式 API Hook 时,需要定位至被截函数处(图中是 BF501234),写入一 条跳转指令(Jmp XXXX,二进制代码为 E9XXXX),表示所有程序调用被截函数时都自动 跳转到自定义函数。 (2)自定义函数必须与被截函数有相同的参数及调用方式,否则会造成堆栈出错。在 自定义函数中(见图 1(b)的④)必须把“Jmp XXXX”暂时恢复为原来的指令,并调用被截函 数(图中的 BF501234),最后把被截函数原来的指令再次改为“Jmp XXXX”。 (3)卸载陷阱式 API Hook 时,需要把“Jmp XXXX”恢复为原来的指令。 由于以上过程像个陷阱,因此称为“陷阱式”。
地址 执行顺序 地址 执行顺序 00000000 00000000 4F001200 4F001200 ③ 自定义函数 自定义函数 ④ ⑧ 当前指令 ① 当前指令 ① ⑤ ⑨ BF501234 ② BF501234 ②⑤ 被截函数 被截函数 ③ ⑥ ④ ⑦ FFFFFFFF FFFFFFFF (a)设陷阱之前 (b)设陷阱之后 push ebp mov ebp,esp …… ret call BF501234 push ebp mov ebp,esp …… ret push ebp mov ebp,esp …… ret call BF501234 jmp 4f001200 …… …… ret windows 虚拟内存的管理 图 1 Windows NT/2000 陷阱式 API Hook Win32 应用程序“可见”的内存空间是 4GB,从 0x00000000~0x80000000 的 2GB 是应 用 程 序 的 私 有 空 间 , 在 此 空 间 里 每 个 应 用 程 序 访 问 到 的 数 据 都 不 相 同 ; 从 0x80000000~0xFFFFFFFF 的 2GB 是公共空间,每个应用程序访问到的数据都基本相同。但 是,Windows NT/2000 有个写时备份(Copy on Write)的机制,一个应用程序在此空间中写 入数据并不影响到其他进程,操作系统自动申请一块内存(该地址与原地址相同)让应用程 序写。 一般情况下,操作系统是不允许应用程序对 0x80000000 地址以上 2GB 的内存进行写操 作的。在 Windows 9x/NT/2000 下,操作系统提供了几个内存 Api 操作函数 VirtualProtectEx、 WriteProcessMemeory 和 ReadProcessMemeory,用于读写该地址范围的内存。因此我们可以 通过这些函数在内存中动态地修改代码,函数的原型为: BOOL VirtualProtectEx( HANDLE hProcess, // 要修改内存的进程句柄 LPVOID lpAddress, // 要修改内存的起始地址 DWORD dwSize, // 修改内存的字节 DWORD flNewProtect, // 修改后的内存属性 PDWORD lpflOldProtect // 修改前的内存属性的地址 ); BOOL WriteProcessMemory( HANDLE hProcess, // 要写进程的句柄
LPVOID lpBaseAddress, // 写内存的起始地址 LPVOID lpBuffer, // 写入数据的地址 DWORD nSize, // 要写的字节数 LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 ); BOOL ReadProcessMemory( HANDLE hProcess, // 要读进程的句柄 LPCVOID lpBaseAddress, // 读内存的起始地址 LPVOID lpBuffer, // 读入数据的地址 DWORD nSize, // 要读入的字节数 LPDWORD lpNumberOfBytesRead // 实际读入的子节数 ); 把 DLL 注入其他进程 还有较重要的一步是把 Api Hook 所在 DLL 中的代码注入其它进程中,这可以使用 SetWindowsHookEx 设置系统钩子来实现。当创建钩子函数时,就在 Windows 的指定消息处 理链中插入一个函数,一旦安装成功,钩子就可以监控消息,因此向所有应用程序发送的消 息就会先经过此函数。系统钩子程序必须放在动态连接库 DLL 中,不能在可执行文件 EXE 中完成,因为可执行文件在其他进程(另一个可执行文件)中是不可见的,无法实现系统级 的钩子功能。 对于一个系统钩子来说,系统自动将包含钩子回调函数的 DLL 映射到受钩子函数影响 的所有进程的地址空间中。在 API Hook 技术中,使用钩子函数就是为了把当前的 DLL 映射 到所有进程中去,钩子仅是辅助功能,并不是最终目的。 当 DLL 注入进程时,它的载入地址是不确定的,可以在 DLL 的入口代码实现更改函数 入口的功能(即写入 JMP XXXX 指令)。 通知其它进程卸载 向系统发送配置改变的广播消息 SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
分享到:
收藏