1. 程式人生 > 實用技巧 >IAT HOOK 簡單實現

IAT HOOK 簡單實現

注意的事項:

1、操作部分在IAT表中

2、HOOK函式中需要用函式指標接收,因為此時IAT已經被HOOK,如果直接return 原函式,其實會造成棧溢位,因為此時的原函式已經被HOOK了,會造成類似的遞迴操作

3、最後HOOK完,需要進行 解除安裝HOOK 操作

4、如果debug的時候發現IAT表中是能寫進去的,但是發現寫入異常,則可能跟物理頁的屬性有關,需要進行VirtualProtect設定

#include<Windows.h>
#include<cstdio>


DWORD dwMessagebox = (DWORD)GetProcAddress(LoadLibrary("user32.dll"), "MessageBoxA");

int WINAPI MyMessageBox(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType){
	typedef int(WINAPI *PMyMessageBox)(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);

	printf("Hook Messagebox Param: hWnd: %x, lpText: %s, lpCation: %s, uType: %x", hWnd, lpText, lpCaption, uType);

	PMyMessageBox MyMessageBox = (PMyMessageBox)dwMessagebox;
	return MyMessageBox(0, TEXT("It's My Hook Messagebox!"), 0, 0);
}


void InstallIatHook(DWORD dwOldFunction, DWORD dwNewFunction)
{

	HMODULE hModule = GetModuleHandle(NULL);

	// load pe
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_IMPORT_DESCRIPTOR pIMPORT_DESCRIPTOR = NULL;
	PIMAGE_IMPORT_BY_NAME pImage_IMPORT_BY_NAME = NULL;

	PDWORD OriginalFirstThunk = NULL;
	PDWORD FirstThunk = NULL;
	PIMAGE_THUNK_DATA pImageThunkData = NULL;

	DWORD Original = 0;

	pDosHeader = (PIMAGE_DOS_HEADER)hModule;
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + sizeof(IMAGE_OPTIONAL_HEADER32));
	
	pIMPORT_DESCRIPTOR = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hModule + pOptionHeader->DataDirectory[1].VirtualAddress);

	DWORD dwOldProtect; // 記憶體頁屬性
	BOOL bFlag = TRUE;
	//這裡可以進行while操作,這裡while的判斷依據為pIMPORT_DESCRIPTOR個數
	while (pIMPORT_DESCRIPTOR->FirstThunk && bFlag) {
		FirstThunk = (PDWORD)((DWORD)hModule + (DWORD)pIMPORT_DESCRIPTOR->FirstThunk);
		while (*FirstThunk) {
			if (*FirstThunk == dwOldFunction)
			{
				VirtualProtect((LPVOID)FirstThunk, 0x4, PAGE_READWRITE, &dwOldProtect);
				*FirstThunk = dwNewFunction;
				bFlag = FALSE;
				break;
			}
		
			FirstThunk++;
		}

		// 進行遍歷操作
		pIMPORT_DESCRIPTOR++;
	}

}

void UninstallIatHook(DWORD dwOldFunction, DWORD dwNewFunction)
{
	HMODULE hModule = GetModuleHandle(NULL);

	// load pe
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_IMPORT_DESCRIPTOR pIMPORT_DESCRIPTOR = NULL;
	PIMAGE_IMPORT_BY_NAME pImage_IMPORT_BY_NAME = NULL;

	PDWORD OriginalFirstThunk = NULL;
	PDWORD FirstThunk = NULL;
	PIMAGE_THUNK_DATA pImageThunkData = NULL;

	DWORD Original = 0;

	pDosHeader = (PIMAGE_DOS_HEADER)hModule;
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + sizeof(IMAGE_OPTIONAL_HEADER32));

	pIMPORT_DESCRIPTOR = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hModule + pOptionHeader->DataDirectory[1].VirtualAddress);

	BOOL bFlag = TRUE;
	//這裡可以進行while操作,這裡while的判斷依據為pIMPORT_DESCRIPTOR個數
	while (pIMPORT_DESCRIPTOR->FirstThunk && bFlag) {
		FirstThunk = (PDWORD)((DWORD)hModule + (DWORD)pIMPORT_DESCRIPTOR->FirstThunk);
		while (*FirstThunk) {
			if (*FirstThunk == dwOldFunction)
			{
				*FirstThunk = dwNewFunction;
				bFlag = FALSE;
				break;
			}

			FirstThunk++;
		}

		// 進行遍歷操作
		pIMPORT_DESCRIPTOR++;
	}
}

int main(int argc, char* argv[]){
	InstallIatHook(dwMessagebox, (DWORD)MyMessageBox);
	MessageBox(0, 0, 0, 0);
	UninstallIatHook((DWORD)MyMessageBox, dwMessagebox);
	MessageBox(0, 0, 0, 0);

	return 0;
}