IAT Hook是Ring3层常用的Hook之一,主要思路大家都知道,就是修改IAT中的函数地址。
之前写过讨论IAT的帖子:《PE结构:导入表中的双桥结构》:https://blog.csdn.net/weixin_43742894/article/details/106150321
IAT结构:
struct _IMAGE_THUNK_DATA32{
union {
DWORD ForwarderString; //指向一个转向者字符串的RVA
DWORD Function ; //被输入的函数的内存地址
DWORD Ordinal ; //被输入的API的序数值
DWORD AddressOfData ; //高位为0则指向IMAGE_IMPORT_BY_NAME 结构体二
}u1;
}IMAGE_THUNK_DATA32;
我们重点讨论的就是hook的地址,也就是IAT中的函数地址:Function。
在PE加载过程中,双桥结构断裂之后,IAT中存放的就是函数的真实地址,我们修改这个地址也就是实现了Hook。
函数原本调用流程
原来的调用过程:
call [aaaaa] => IAT[aaaaaa]::bbbbb => xxx.dll::bbbbb
ret后
next code of call [aaaaa] <= next ret of xxx.dll::bbbbb
实现原理及流程
实现原理:
在进行Windows编程的时候,我们会经常使用Windows的API函数。而我们的API函数一般都是写在dll里,导入表里写着加载的dll和函数,代表该模块调用了哪些外部API,模块被加载到内存后, PE加载器会修改该表,地址改成外部API重定位后的真实地址, 我们只要直接把里面的地址改成我们新函数的地址, 就可以完成对相应API的Hook。
实现流程:
1、在Dll里构造Detour函数(也就是我们自己的函数)
2、获取Target函数地址,并找到Target函数所在的IAT的地址
3、保存原始的IAT地址和IAT地址所存储的内容
4、修改IAT地址中的数据(前提:修改内存属性为可写)
5、恢复IAT
如果需要调用原来API函数,可以直接使用保存的API地址,可以就保证了HOOK的有效性
具体实现:
本文以Messagebox为例:
一、在Dll里构造Detour函数
自己的函数参数和返回值要保持与原函数一致。
这一点的目的是为了平衡堆栈。
typedef int(WINAPI *PFN_MessageBoxA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
int WINAPI My_MessageBoxA(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
)
这里面我们主要要实现的俩步
1.我们自己想要实现的功能
2.调用原来的函数
int WINAPI MyMessageBox(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
{
char szHookText[] = "IBinary -> Iat Hook";
if (g_OldPfnMsgA != nullptr)
{
return g_OldPfnMsgA(hWnd, szHookText, lpCaption, uType);//调用以前的
}
return 0