API拦截(APIHOOK)技术及应用
常用的APIHook(截取API,或函数钩子)有两种方式:陷阱式、改引入表式。在Windows
9x、WindowsNT/2000这两个系统中的APIHook代码完全不同。就Windows9x而言,16
位DLL与32位DLL的APIHook代码也完全不相同。
APIHOOK入门
APIHook是一项有趣而实用的Windows系统编程技术,应用领域十分广泛,屏幕取词、
内码转换、屏幕翻译、中文平台、网络防火墙、串口红外通信或Internet通信的监视等,都
涉及到了此项技术。
APIHook就是钩住API,钩就是绕弯的意思,即让API函数的调用先绕一个弯路,在
它执行之前,先做一些“预处理”,这样我们就可以监视或定制某个Win32API的调用,以
实现一些特殊的功能。至于具体可以实现些什么样的功能,就取决于程序设计者的想象力了。
在很多情况下,想监视或改变某个应用程序的一些特定的操作,但是该应用程序却没
有提供相应的接口,而又几乎不可能得到其源代码。因为大多数Windows应用程序的操作
很大程度上依赖于API,所以可以采用APIHook的方式来试图监视和改变应用程序的行为。
常用的APIHook有两种方式:陷阱式和改引入表式。APIHook的运行平台有三种:
Windows9x的16位DLL、Windows9x的32位DLL和WindowsNT/2000的32位DLL。
其关系如表7-1所示。
表7-1APIHook的方式
方式16位Windows9x32位Windows9x
WindowsNT/2000
陷阱式√―√
改引入表式×Ο√
其中,×表示不能实现;Ο表示只对指定模块有效,对整个进程或整个操作系统无效;―
表示在VC下可以实现,在C++Builder/Delphi下很难实现;√表示可以实现。
表7-2列出了两种方式各自的优缺点。
方式优点缺点
陷阱式可以Hook所有函数要避免“重入”问题
改引入表式易于实现系统API有时候会漏网
陷井式APIHOOK
原理
WindowsNT/2000陷阱式APIHook的工作原理如图1所示。其工作过程如下:
(1)加载陷阱式APIHook时,需要定位至被截函数处(图中是BF501234),写入一
条跳转指令(JmpXXXX,二进制代码为E9XXXX),表示所有程序调用被截函数时都自动
跳转到自定义函数。
(2)自定义函数必须与被截函数有相同的参数及调用方式,否则会造成堆栈出错。在
自定义函数中(见图1(b)的④)必须把“JmpXXXX”暂时恢复为原来的指令,并调用被截函
数(图中的BF501234),最后把被截函数原来的指令再次改为“JmpXXXX”。
(3)卸载陷阱式APIHook时,需要把“JmpXXXX”恢复为原来的指令。
由于以上过程像个陷阱,因此称为“陷阱式”。
地址执行顺序地址执行顺序
0000
4F0012004F001200③
自定义函数自定义函数
④
⑧
当前指令①当前指令①
⑤⑨
BF501234②BF501234②⑤
被截函数被截函数
③⑥
④⑦
FFFFFFFFFFFFFFFF
(a)设陷阱之前(b)设陷阱之后
图1WindowsNT/2000陷阱式APIHook
windows虚拟内存的管理
Win32应用程序“可见”的内存空间是4GB,从0x00000000~0x80000000的2GB是应
用程序的私有空间,在此空间里每个应用程序访问到的数据都不相同;从
0x80000000~0xFFFFFFFF的2GB是公共空间,每个应用程序访问到的数据都基本相同。但
是,WindowsNT/2000有个写时备份(CopyonWrite)的机制,一个应用程序在此空间中写
入数据并不影响到其他进程,操作系统自动申请一块内存(该地址与原地址相同)让应用程
序写。
一般情况下,操作系统是不允许应用程序对0x80000000地址以上2GB的内存进行写操
作的。在Windows9x/NT/2000下,操作系统提供了几个内存Api操作函数VirtualProtectEx、
WriteProcessMemeory和ReadProcessMemeory,用于读写该地址范围的内存。因此我们可以
通过这些函数在内存中动态地修改代码,函数的原型为:
BOOLVirtualProtectEx(
HANDLEhProcess,//要修改内存的进程句柄
LPVOIDlpAddress,//要修改内存的起始地址
DWORDdwSize,//修改内存的字节
DWORDflNewProtect,//修改后的内存属性
PDWORDlpflOldProtect//修改前的内存属性的地址
);
BOOLWriteProcessMemory(
HANDLEhProcess,//要写进程的句柄
pushebp
movebp,esp
„„
ret
callBF501234
pushebp
movebp,esp
„„
ret
pushebp
movebp,esp
„„
ret
callBF501234
jmp4f001200
„„
„„
ret
LPVOIDlpBaAddress,//写内存的起始地址
LPVOIDlpBuffer,//写入数据的地址
DWORDnSize,//要写的字节数
LPDWORDlpNumberOfBytesWritten//实际写入的子节数
);
BOOLReadProcessMemory(
HANDLEhProcess,//要读进程的句柄
LPCVOIDlpBaAddress,//读内存的起始地址
LPVOIDlpBuffer,//读入数据的地址
DWORDnSize,//要读入的字节数
LPDWORDlpNumberOfBytesRead//实际读入的子节数
);
把DLL注入其他进程
还有较重要的一步是把ApiHook所在DLL中的代码注入其它进程中,这可以使用
SetWindowsHookEx设置系统钩子来实现。当创建钩子函数时,就在Windows的指定消息处
理链中插入一个函数,一旦安装成功,钩子就可以监控消息,因此向所有应用程序发送的消
息就会先经过此函数。系统钩子程序必须放在动态连接库DLL中,不能在可执行文件EXE
中完成,因为可执行文件在其他进程(另一个可执行文件)中是不可见的,无法实现系统级
的钩子功能。
对于一个系统钩子来说,系统自动将包含钩子回调函数的DLL映射到受钩子函数影响
的所有进程的地址空间中。在APIHook技术中,使用钩子函数就是为了把当前的DLL映射
到所有进程中去,钩子仅是辅助功能,并不是最终目的。
当DLL注入进程时,它的载入地址是不确定的,可以在DLL的入口代码实现更改函数
入口的功能(即写入JMPXXXX指令)。
通知其它进程卸载
向系统发送配置改变的广播消息
SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
本文发布于:2022-11-27 13:26:10,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/31253.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |