IATHOOK详细讲解

0x01 HOOK函数的编写

有一定的格式要求

直接直接hook MessageBoxA

函数格式


int WINAPI NewMessageBox(
				  HWND hWnd,          // handle to owner window
				  LPCTSTR lpText,     // text in message box
				  LPCTSTR lpCaption,  // message box title
				  UINT uType          // message box style
		)
{
	//拿到原来的MessageBox
	typedef int (WINAPI *pfMessageBox)(HWND,  LPCTSTR, LPCTSTR, UINT);
	pfMessageBox myMessageBox = NULL;
	myMessageBox  = (pfMessageBox)GetProcAddress(LoadLibrary("User32.DLL"),"MessageBoxA");
	//监测数据
	OutputDebugStringF("hWnd:%08X,lpText:%s,lpCaption:%s,uType:%d ",hWnd,lpText,lpCaption,uType);
	
	//继续执行MessageBox
	myMessageBox(hWnd,"www.gyarmy.com","流沙",uType);

	myMessageBox(hWnd,lpText,lpCaption,uType);
	return 0;
}


0x02 IAT表的遍历

由于导入表的复杂性, 每次遍历导入表,我都是到处找资料, 导入表, 有一个INT表和一个IAT表, 每次使用,都需要看看一张图

导入表.png


这里主要用来配合理解导入表的结构

需要理解PE的运行载入过程

IAT表是载入PE后进行修复得到的, 我们直接修改 IAT表中的数据即可

代码如下;


BOOL ImportDirectoryHOOK(DWORD imagebase,DWORD pOldAddr,DWORD pNewAddr)
{

	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_SECTION_HEADER pSectionHeader_ADD = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	//Header信息
	pDosHeader = (PIMAGE_DOS_HEADER)imagebase;
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)imagebase+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+pPEHeader->SizeOfOptionalHeader);
	pDataDirectory = pOptionHeader->DataDirectory;

	//确定导入表
	IMAGE_DATA_DIRECTORY pImportDirectory = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
	
	DWORD ImportVirtualAddress = pImportDirectory.VirtualAddress;
	PIMAGE_IMPORT_DESCRIPTOR pImp = NULL;
	pImp = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)imagebase + ImportVirtualAddress);
	PIMAGE_THUNK_DATA pOrgThunk, pFirstThunk;

	//遍历IAT表
	while (NULL != pImp->FirstThunk) {
		pImp->Name += imagebase;
		OutputDebugStringF("DLL: %s", pImp->Name);
		//FARPROC fpFun;
		HINSTANCE hInstance = LoadLibraryA((LPCSTR)pImp->Name);
		if (NULL == hInstance) {
			OutputDebugStringF("Load library %s failed, error: %d\n", pImp->Name, GetLastError());
			return FALSE;
		}
		pOrgThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->OriginalFirstThunk);
		pFirstThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->FirstThunk);
		
		while (NULL != *(DWORD *)pFirstThunk) {
			if(pOldAddr == *((PDWORD)pFirstThunk))
			{
				OutputDebugStringF("11111111111");
				*((PDWORD)pFirstThunk)= pNewAddr;
				break;
			}
			++pFirstThunk;
			++pOrgThunk;
		}
		FreeLibrary(hInstance);
		++pImp;
	}
	return TRUE;
}


0x03 最后贴上主程序的代码,关键在于思路的理解!


// 20180202_05.cpp : Defines the entry point for the application.

//

#include "stdafx.h"
#include "PEOperate.h"
#include "DebugTool.h"
#include <windows.h>
#include <stdio.h>

BOOL ImportDirectoryHOOK(DWORD imagebase,DWORD pOldAddr,DWORD pNewAddr)
{

	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_SECTION_HEADER pSectionHeader_ADD = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	//Header信息
	pDosHeader = (PIMAGE_DOS_HEADER)imagebase;
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)imagebase+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+pPEHeader->SizeOfOptionalHeader);
	pDataDirectory = pOptionHeader->DataDirectory;

	//确定导入表
	IMAGE_DATA_DIRECTORY pImportDirectory = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
	
	DWORD ImportVirtualAddress = pImportDirectory.VirtualAddress;
	PIMAGE_IMPORT_DESCRIPTOR pImp = NULL;
	pImp = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)imagebase + ImportVirtualAddress);
	PIMAGE_THUNK_DATA pOrgThunk, pFirstThunk;

	//遍历IAT表
	while (NULL != pImp->FirstThunk) {
		pImp->Name += imagebase;
		OutputDebugStringF("DLL: %s", pImp->Name);
		//FARPROC fpFun;
		HINSTANCE hInstance = LoadLibraryA((LPCSTR)pImp->Name);
		if (NULL == hInstance) {
			OutputDebugStringF("Load library %s failed, error: %d\n", pImp->Name, GetLastError());
			return FALSE;
		}
		pOrgThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->OriginalFirstThunk);
		pFirstThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->FirstThunk);
		
		while (NULL != *(DWORD *)pFirstThunk) {
			if(pOldAddr == *((PDWORD)pFirstThunk))
			{
				OutputDebugStringF("11111111111");
				*((PDWORD)pFirstThunk)= pNewAddr;
				break;
			}
			++pFirstThunk;
			++pOrgThunk;
		}
		FreeLibrary(hInstance);
		++pImp;
	}
	return TRUE;
}

int WINAPI NewMessageBox(
				  HWND hWnd,          // handle to owner window
				  LPCTSTR lpText,     // text in message box
				  LPCTSTR lpCaption,  // message box title
				  UINT uType          // message box style
		)
{
	//拿到原来的MessageBox
	typedef int (WINAPI *pfMessageBox)(HWND,  LPCTSTR, LPCTSTR, UINT);
	pfMessageBox myMessageBox = NULL;
	myMessageBox  = (pfMessageBox)GetProcAddress(LoadLibrary("User32.DLL"),"MessageBoxA");
	//监测数据
	OutputDebugStringF("hWnd:%08X,lpText:%s,lpCaption:%s,uType:%d ",hWnd,lpText,lpCaption,uType);
	
	//继续执行MessageBox
	myMessageBox(hWnd,"www.gyarmy.com","流沙",uType);

	myMessageBox(hWnd,lpText,lpCaption,uType);
	return 0;
}

VOID TestIATHook()
{
	//定位MessageBox
	typedef int (WINAPI *pfMessageBox)(HWND,  LPCTSTR, LPCTSTR, UINT);
	pfMessageBox myMessageBox = NULL;
	myMessageBox  = (pfMessageBox)GetProcAddress(LoadLibrary("User32.DLL"),"MessageBoxA");
	OutputDebugStringF("myMessageBox: %08X",myMessageBox);
	//myMessageBox(0,"111","222",MB_OK);

	DWORD pOldArr = (DWORD)myMessageBox;

	//定位导入表
	HMODULE hModule = GetModuleHandle(NULL);
	DWORD ImageBase = (DWORD)hModule;
	DWORD pNewAddr = (DWORD)NewMessageBox;
	//对IAT表进行HOOK
	ImportDirectoryHOOK(ImageBase,pOldArr,pNewAddr);
}


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	// TODO: Place code here.
	TestIATHook();
	MessageBox(0,0,0,0);
	return 0;
}


项目源代码下载地址:

IATHook.rar

原文链接: IATHOOK详细讲解 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://gyarmy.com/post-393.html )

发表评论

0则评论给“IATHOOK详细讲解”