工控安全系统对抗之HOOK技术

一、 实验要求
分别采用IAT Hook和inline Hook技术对系统函数Hook

  1. 利用IAT Hook来挂钩user32.dll中的GetTopWindow函数,实现调用GetTopWindow会弹出提示框
  2. 利用Inline Hook技术实现对user32.dll中的MessageBoxA的Hook,实现弹框前,先Beep一声

提示:
考虑到inline Hook实现对新手较难,可以先使用mhook库或Detours库来实现
二、 源代码

#include "windows.h"

typedef
struct _IATHOOK_DATA 
{
	DWORD	dwValueAddr;	//IAT项中保存函数地址的地址
	DWORD	dwOriginValue;	//原始数据
	DWORD	dwNewValue;		//新的数据
}IATHOOK_DATA, *PIATHOOK_DATA;

DWORD IATHook(CHAR szDllName[], CHAR szFuncName[], PIATHOOK_DATA pIATHookData);
DWORD IATUnHook(PIATHOOK_DATA pIATHookData);

HWND WINAPI MyGetTopWindow(HWND hWnd);

IATHOOK_DATA	IATHookData;

int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
	IATHookData.dwNewValue = (DWORD)MyGetTopWindow;
	IATHook("user32.dll", "GetTopWindow", &IATHookData);
	GetTopWindow(NULL);
	return	0;
}

typedef
HWND (WINAPI *GETTOPWINDOW)(HWND hWnd);
HWND WINAPI MyGetTopWindow(HWND hWnd)
{
	GETTOPWINDOW	OriginGetTopWindow = (GETTOPWINDOW)IATHookData.dwOriginValue;
	Beep(300, 100);
	MessageBoxA(NULL, "GetTopWindow哦", "3170706006", MB_OK);
	
	return	OriginGetTopWindow(hWnd);
}


/************************************************************************/
/* 
功能:利用修改导入函数表中地址来hook函数
参数:szDllName-导入函数的dll名,szFuncName-函数名,pIATHookData-hook使用的数据
原理:通过判断IMAGE_THUNK_DATA中函数名来得到对应IAT中地址,修改导入函数表中函数地址
*/
/************************************************************************/
DWORD IATHook(CHAR szDllName[], CHAR szFuncName[], PIATHOOK_DATA pIATHookData)
{
	DWORD						dwBaseAddr;
	PIMAGE_DOS_HEADER			pDosHeader;
	PIMAGE_NT_HEADERS			pNtHeader;
	PIMAGE_OPTIONAL_HEADER		pOptHeaer;
	PIMAGE_THUNK_DATA			pThunk, pIAT;
	PIMAGE_IMPORT_DESCRIPTOR	pImportDes;
	DWORD						dwIndex;
	DWORD						dwOriginProtect;

	if (NULL == szDllName || NULL == szFuncName || NULL == pIATHookData)
	{
		return	ERROR_INVALID_PARAMETER;
	}

	//获取当前文件的基址
	dwBaseAddr = (DWORD)GetModuleHandle(NULL);
	if (NULL == dwBaseAddr)
	{
		return	GetLastError();
	}
	
	//从头计算得到引入表的地址
	pDosHeader = (PIMAGE_DOS_HEADER)dwBaseAddr;
	pNtHeader = (PIMAGE_NT_HEADERS)(dwBaseAddr + pDosHeader->e_lfanew);
	pOptHeaer = &(pNtHeader->OptionalHeader);

	pImportDes = (PIMAGE_IMPORT_DESCRIPTOR)(dwBaseAddr + pOptHeaer->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

	while (pImportDes->FirstThunk)
	{
		//判断是否是对应模块
		if (_stricmp((CHAR*)(dwBaseAddr+pImportDes->Name), szDllName))
		{
			pImportDes ++;
			continue;
		}

		//当PE文件被装载到内存时,PE装载器将查找IMAGE_THUNK_DATA 和 IMAGE_IMPORT_BY_NAME 这些结构数组,
		//以此决定引入函数的地址。然后用引入函数真实地址来替代由FirstThunk指向的 IMAGE_THUNK_DATA 数组里的元素值
		//若 OriginalFirstThunk 为0,就改用FirstThunk值。有些连接器生成PE文件时会置OriginalFirstThunk值为0,这应该算是个bug。
		pIAT = (PIMAGE_THUNK_DATA)(dwBaseAddr + pImportDes->FirstThunk);
		if (pImportDes->OriginalFirstThunk)
		{
			pThunk = (PIMAGE_THUNK_DATA)(dwBaseAddr + pImportDes->OriginalFirstThunk);
		}
		else
		{
			pThunk = pIAT;
		}

		dwIndex = 0;
		
		do 
		{
			//有些情况下一些函数仅由序数引出,对应该函数的 IMAGE_THUNK_DATA 值
			//的低位字指示函数序数,而最高二进位 (MSB)设为1。
			//32位时IMAGE_ORDINAL_FLAG = 0x80000000h。
			dwIndex = *(DWORD*)pThunk;
			if (dwIndex != 0)
			{
				if ((dwIndex & IMAGE_ORDINAL_FLAG) == 0)
				{
					//得到函数名,继续向后跳2字节
					if (strcmp((PCHAR)(dwBaseAddr + dwIndex + 2), szFuncName) == 0)
					{
						//找到了,先保存原始数据
						pIATHookData->dwValueAddr = (DWORD)pIAT;
						pIATHookData->dwOriginValue = *(DWORD*)pIAT;
						
						//修改IAT
						VirtualProtect(pIAT, 4, PAGE_EXECUTE_READWRITE, &dwOriginProtect);
						*(DWORD*)pIAT = pIATHookData->dwNewValue;
						VirtualProtect(pIAT, 4, dwOriginProtect, &dwOriginProtect);
						return	0;
					}
				}
			}
			//换下一个
			pThunk ++;
			pIAT ++;
		} while (1);
		//取下一模块
		pImportDes ++;
	}
	return	0;
}

/************************************************************************/
/* 
功能:修股
参数:
原理:
*/
/************************************************************************/
DWORD IATUnHook(PIATHOOK_DATA pIATHookData)
{
	DWORD	dwOriginProtect;

	VirtualProtect((PVOID)pIATHookData->dwValueAddr, 4, PAGE_EXECUTE_READWRITE, &dwOriginProtect);
	*(DWORD*)pIATHookData->dwValueAddr = pIATHookData->dwOriginValue;
	VirtualProtect((PVOID)pIATHookData->dwValueAddr, 4, dwOriginProtect, &dwOriginProtect);
	return	0;
}

三、 程序运行
然后电脑会滴的响一声
在这里插入图片描述

四、总结
通过本次实验,明白了利用IAT Hook来挂钩user32.dll中的GetTopWindow函数,实现调用GetTopWindow会弹出提示框,学会利用Inline Hook技术实现对user32.dll中的MessageBoxA的Hook,实现弹框前,先Beep一声

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值