第六十三课 IAT HOOK
1.IAT HOOK是什么
其实就是找到IAT表的位置再换成自己定义的函数,只是我们替换的函数需要和原函数的结构保持一直,比如我们要HOOK Messagebox函数,那么我们需要定义一个MyMessagebox函数,他的结构应该与Messagebox保持一致,只是我们函数的功能可以改变
2.IAT HOOK的用处
比原函数多出一些自己想要的操作,举一个最典型的例子,一些杀毒软件经常会在一些函数上面HOOK,做出一些检测监控的操作,监控函数的返回值,参数
3.IAT HOOK的实现代码
#include <windows.h>
#include <stdio.h>
typedef int (WINAPI* pMyMsg)(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
pMyMsg pOldMsg = NULL;
int MyMessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
{
int result = pOldMsg(NULL, "IAT HOOK成功", "IAT HOOK", MB_OK);
return result;
}
HMODULE hModImageBase = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModImageBase;
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)hModImageBase + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + 20);
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);
PIMAGE_DATA_DIRECTORY pDataDirHeader = (PIMAGE_DATA_DIRECTORY)(pOptionalHeader->DataDirectory + 1);
PIMAGE_IMPORT_DESCRIPTOR pImportTbale = (PIMAGE_IMPORT_DESCRIPTOR)(pDataDirHeader->VirtualAddress + (DWORD)hModImageBase);
PIMAGE_THUNK_DATA32 image_thunk_data = (PIMAGE_THUNK_DATA32)pImportTbale->FirstThunk;
void SetIatHook()
{
PVOID pHookAddress = nullptr;
pHookAddress = GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
pOldMsg = (pMyMsg)pHookAddress;
DWORD* pIATaddress;
while (pImportTbale->FirstThunk != NULL)
{
//获取IAT表位置
pIATaddress = (DWORD*)(pImportTbale->FirstThunk + (DWORD)hModImageBase);
//pIATaddress = (DWORD*)(hModImageBase + pImportTbale->FirstThunk);
while (*pIATaddress != NULL)
{
if (*pIATaddress == (DWORD)pOldMsg)
{
DWORD OldProtected;
VirtualProtect((LPVOID)pIATaddress, 0x1000, PAGE_EXECUTE_READWRITE, &OldProtected);
DWORD dwtemp = (DWORD)MyMessageBoxA;
memcpy((LPVOID)pIATaddress, (DWORD*)&dwtemp, 4);
VirtualProtect((LPVOID)pIATaddress, 0x1000, OldProtected, &OldProtected);
}
pIATaddress++;
}
pImportTbale++;
}
}
int main()
{
SetIatHook();
MessageBoxA(NULL, "Hook测试", "标题", MB_OK);
getchar();
}
注意:
1、pIATaddress = (DWORD)(pImportTbale->FirstThunk + (DWORD)hModImageBase);注意获取IAT表位置时把hModImageBase转换成DWORD类型,虽然编译不会报错但是运行时会报错内存无法访问,gpt说可能是由于指针的类型不匹配,导致了错误的内存地址计算,进而引发了内存访问错误
2、命令行程序没有引入user32,所以使用LoadLibrary
3、MyMessageBoxA的编写,需要使用Oldmessagebox的地址,而不是messagebox
4、memcpy((LPVOID)*pIATaddress, (DWORD*)&dwtemp, 4);
VirtualProtect((LPVOID)*pIATaddress, 0x1000, OldProtected, &OldProtected);
这两句我原本写的是这样,其实不应该加
4.课上的两个思考
1、什么时候函数在IAT表里面没有
答:自己手动加载函数loadlibry时
2、定义MyMessagebox时改成这样子可不可以
答:这时候Messagebox已经换成了MyMessagebox,所以变成了死循环
5.IAT HOOK的局限性
有些不能HOOK,比如一些自己写的函数,或者自己手动load的函数,都不存在IAT表,所以都无法HOOK
第六十四课 Inline HOOK
inline HOOK就可以解决上节课IATHOOK的一些局限性,比如在自己写的函数内HOOK
E8 和 E9 后面4字节地址X的转换公式:X = 真正要跳转的地址 - E8这条指令的下一行地址
1.inline hook的一些细节
- E9jmp后面的地址是需要根据一条公式来计算的
- jmp过去后记得把原来两行代码执行了
- 在jmp执行我们自己的代码前需要保存一下所有寄存器,以免我们在自己操作的时候改变了寄存器
- 还要保存标志寄存器
- 在jmp执行自己代码时要自己保证堆栈平衡(自己push自己pop),或者使用E8call
2.代码实现
参考了这位大佬的new函数编写https://github.com/LoveCppp/dishuinixiang/blob/main/win32/win32%E8%BF%9B%E7%A8%8B%E7%9B%91%E6%8E%A7%E9%A1%B9%E7%9B%AE/processmonitoring/processmon/InlineHOOK.cpp
第一版代码:有两处错误
#include <Windows.h>
#include <stdio.h>
typedef int (WINAPI* pMyMsg)(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
pMyMsg pOldMsg = NULL;
PVOID pHookAddress = nullptr;
//定义newmessagebox函数
int WINAPI NewMessagebox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
printf("HOOK成功");
pOldMsg( hWnd,"HOOK成功", "HOOK", MB_OK);
return 0;
}
//定义unhook函数
//定义hook函数
void SetHook()
{
BYTE code[5] = { 0xe9, };
BYTE OldCode[5];
DWORD JmpAddress = (DWORD)NewMessagebox - ((DWORD)pOldMsg + 5);
memcpy(&code[1],&JmpAddress,0x4);
DWORD OldProtected;
VirtualProtect((LPVOID)pOldMsg, 0x1000, PAGE_EXECUTE_READWRITE, &OldProtected);
memcpy(OldCode, (LPVOID)pOldMsg,0x4);
memcpy((LPVOID)pOldMsg,code, 0x5);
VirtualProtect((LPVOID)pOldMsg, 0x1000, OldProtected, &OldProtected);
}
int main()
{
pHookAddress = GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
pOldMsg = (pMyMsg)pHookAddress;
SetHook();
MessageBoxA(NULL, "after hook", "tips", MB_OK);
}
1、memcpy(OldCode, (LPVOID)pOldMsg,0x4);
需要注意我们想要把pOldMsg老函数地址
放到一个字符串数组里面,但是我们这样子的代码就是把函数地址里面的前4个值放到字符串数组OldCode里面,应该改成memcpy(OldCode, (LPVOID)&pOldMsg,0x4);
2、第二我发现这样写NewMessagebox会进入死循环,他没办法执行旧的Messagebox函数
3.最终代码实现
#include <Windows.h>
#include <stdio.h>
typedef int (WINAPI* pMyMsg)(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
//pMyMsg pHookMsg = NULL;
pMyMsg pOldMsg = NULL;
PVOID pHookAddress = nullptr;
//定义newmessagebox函数
//int WINAPI NewMessagebox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
//{
//
// printf("HOOK成功");
// pOldMsg( hWnd,"HOOK成功", "HOOK", MB_OK);
//
// return 0;
//}
typedef struct _regeist
{
DWORD EAX;
DWORD EBX;
DWORD ECX;
DWORD EDX;
DWORD EBP;
DWORD ESP;
DWORD ESI;
DWORD EDI;
}regeist;
regeist reg = { 0 };
DWORD x, y, z;
DWORD RetWriteHookAddr;
_declspec(naked) void NewMessagebox()
{
_asm
{
pushad; //保留寄存器
pushfd; //保留标志寄存器
}
printf("123");
_asm
{
popfd; //还原标志寄存器
popad; //还原寄存器
}
//执行之前覆盖的代码
_asm
{
//77D507EA 8B FF mov edi,edi
//77D507EC 55 push ebp
//77D507ED 8B EC mov ebp,esp
//77D507EF 83 3D BC 14 D7 77 00 cmp dword ptr ds:[77D714BCh],0
//77D507F6 74 24 je 77D5081C
mov edi, edi
push ebp
mov ebp, esp
//执行完后跳转回hook地址
jmp RetWriteHookAddr;
}
}
//定义unhook函数
//定义hook函数
void SetHook()
{
BYTE code[5] = { 0xe9, };
BYTE OldCode[5];
DWORD JmpAddress = (DWORD)NewMessagebox - ((DWORD)pOldMsg + 5);
RetWriteHookAddr = ((DWORD)pOldMsg + 5) ;
memcpy(&code[1],&JmpAddress,0x4);
DWORD OldProtected;
VirtualProtect((LPVOID)pOldMsg, 0x1000, PAGE_EXECUTE_READWRITE, &OldProtected);
memcpy(OldCode, (LPVOID)&pOldMsg,0x4);
memcpy((LPVOID)pOldMsg,code, 0x5);
VirtualProtect((LPVOID)pOldMsg, 0x1000, OldProtected, &OldProtected);
}
int main()
{
pHookAddress = GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
pOldMsg = (pMyMsg)pHookAddress;
SetHook();
MessageBoxA(NULL, "after hook", "tips", MB_OK);
}
标签:pOldMsg,10,LPVOID,win32,HOOK,IAT,PIMAGE,DWORD
From: https://www.cnblogs.com/xiaoxin07/p/18078853