IAT Hook

在程序执行前,PE 中的 IAT 表中存储的是指向函数的函数名;当程序真正加载时,操作系统才会将函数地址更新并修改 IAT 表,此时的 IAT 表中存储的是函数的地址。由于 dll 程序加载时,可能存在其加载地址和 ImageBase 不同,而且并不是 dll 中所有的函数都会被使用。因此,指在函数被调用时更新其函数地址,更加高效和安全。

IAT Hook 的思想就是,将 IAT 表中的函数地址进行修改,指向我们自己编写的函数地址。我们在自己编写的函数中再调用被篡改的函数,以实现该程序功能的正常实现。我们可以在自己的函数中实现监控该程序调用被 Hook 的函数的参数、返回值,修改其参数和返回值,以达到特殊的目的。

测试代码如下:

#include <stdio.h>
#include <windows.h>

LPVOID srcFuncAddr;
LPVOID lpImageBuff;
DWORD fileSize;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_FILE_HEADER pPEHeader;
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader;
PIMAGE_DATA_DIRECTORY dataDir;
typedef int (WINAPI *PFUNC)(HWND,LPSTR,LPSTR,UINT);

BOOL GetPEHeader(LPVOID pImageBuffer)
{
	pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
	//判断是否是有效的MZ标志	
	if (*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的PE文件!\n正在退出PE解析...\n");
		//		free(pImageBuffer);
		return FALSE;
	}
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew + 4);
	pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + sizeof(IMAGE_FILE_HEADER));
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pPEHeader->SizeOfOptionalHeader);
	//指向首个目录表, 即导出表
	dataDir = (PIMAGE_DATA_DIRECTORY)((DWORD)pOptionalHeader + 0x60);
	return TRUE;
};

VOID IATHook(LPVOID srcFuncAddr, LPVOID dstFuncAddr, BOOL isSet)
{
	HMODULE hModule;
	PIMAGE_IMPORT_BY_NAME importByName;

	//获取ImageBuffer的信息
	GetPEHeader(lpImageBuff);

	//指向导入表
	dataDir += 1;
	if (dataDir != 0x00)
	{
		PIMAGE_IMPORT_DESCRIPTOR importDir = (PIMAGE_IMPORT_DESCRIPTOR)(dataDir->VirtualAddress + (DWORD)lpImageBuff);

		/*遍历导入表*/
		while (*(DWORD*)importDir != 0x0)
		{
			/*遍历FirstThunk*/
			DWORD* pFirstThunk = (DWORD*)(importDir->FirstThunk + (DWORD)lpImageBuff);

			//判断IAT表是否已经绑定
			BOOL isBind = (importDir->TimeDateStamp == 0) ? FALSE : TRUE;

			while (!isBind)
			{
				//判断FirstThunk是否结束
				if (*pFirstThunk == 0x00)
				{
					break;
				}

				//获取导入表DLL名
				LPSTR lpszNameOfDll = (LPSTR)(importDir->Name + (DWORD)lpImageBuff);
				//加载DLL模块
				hModule = LoadLibraryA(lpszNameOfDll);

				DWORD FirstThunk = *pFirstThunk;
				//判断OriginalFirstThunk是否指向函数名
				if (FirstThunk >> 31 != 0x01)
				{
					if (FirstThunk == (DWORD)srcFuncAddr || FirstThunk == (DWORD)dstFuncAddr)
					{
						//设置Hook
						if (isSet)
						{
							*pFirstThunk = (DWORD)dstFuncAddr;
						}
						//卸载Hook
						else
						{
							//DWORD* FirstThunkOfINT = (DWORD*)(importDir->OriginalFirstThunk + (DWORD)lpImageBuff);
							//importByName = (PIMAGE_IMPORT_BY_NAME)(*FirstThunkOfINT + (DWORD)lpImageBuff);
							//printf("%s\n", (CHAR*)importByName->Name);
							//*pFirstThunk = (DWORD)GetProcAddress(hModule, (CHAR*)importByName->Name);
							*pFirstThunk = (DWORD)srcFuncAddr;
						}
					}
				}
				pFirstThunk++;
			}

			importDir++;
		}

	}

}

int WINAPI MyFuncProc(HWND hWnd,LPSTR lpText,LPSTR lpCaption,UINT uType)
{
	printf("MessageBox参数如下:\n");
	printf("hWnd: %x, lpText: %s, lpCaption: %s, uType: %u\n", hWnd, lpText, lpCaption, uType);
	PFUNC pfunc = (PFUNC)srcFuncAddr;
	pfunc(NULL, "这是被IAT HOOK后的MessageBox!", "提示", MB_OK);
	return 0;
}

int main()
{
	srcFuncAddr = MessageBox;
	//获取PE信息
	lpImageBuff = GetModuleHandle(NULL);

	//设置IAT Hook
	IATHook(srcFuncAddr, MyFuncProc, TRUE);
	MessageBox(NULL, "设置IAT Hook!", "提示", MB_OK);

	//卸载IAT HOOk
	IATHook(srcFuncAddr, MyFuncProc, FALSE);
	MessageBox(NULL, "卸载IAT HOOk!", "提示", MB_OK);
	return 0;
}

效果图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值