WindowsHook

WindowsHook

以MessageBox为例演示两种方法

修改入口点

获取原函数地址

需定义

FARPROC pfOldMsgBoxW;  //指向函数的远指针
//获取原API入口地址
HMODULE hModule = LoadLibrary(L"User32.dll");
pfOldMsgBoxW = GetProcAddress(hModule, "MessageBoxW");

创建新函数

注意传参与返回值应与原函数一致。

int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
	printf("FUCK YOU VIRTUALPROTECT!\n");
	return 0;
}

保存原函数的前5字节

// 将原API的入口前5个字节代码保存到OldCode[]
_asm
{
	lea edi, OldCode		//获取OldCode数组的地址,放到edi
	mov esi, pfOldMsgBoxW	        //获取原API入口地址,放到esi
	cld				//方向标志位,为以下两条指令做准备
	movsd				//复制原API入口前4个字节到OldCode数组
	movsb				//复制原API入口第5个字节到OldCode数组
}

保存新函数的前4字节

注意将NewCode[0]设置为0xe9

//获取MyMessageBoxW的相对地址,为Jmp做准备
//int nAddr= UserFunAddr – SysFunAddr - (我们定制的这条指令的大小);
//Jmp nAddr;
//(我们定制的这条指令的大小), 这里是5,5个字节嘛
_asm
{
	lea eax, MyMessageBoxW			//获取我们的MyMessageBoxW函数地址
	mov ebx, pfOldMsgBoxW			//原系统API函数地址
	sub eax, ebx				//int nAddr = UserFunAddr - SysFunAddr
	sub eax, 5				//nAddr = nAddr - 5
	mov dword ptr[NewCode + 1], eax         //将算出的地址nAddr保存到NewCode后面4个字节
	//注:一个函数地址占4个字节
}

创建HookOn与HookOff函数

//开启钩子的函数
void HookOn()
{
	DWORD dwTemp = 0;
	DWORD dwOldProtect;
	DWORD dwPid = GetCurrentProcessId();
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);

	//修改API函数入口前5个字节为jmp xxxxxx
	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, PAGE_READWRITE, &dwOldProtect);
	WriteProcessMemory(hProcess, pfOldMsgBoxW, NewCode, 5, 0);
	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, dwOldProtect, &dwTemp);
}
//关闭钩子的函数
void HookOff()
{
	DWORD dwTemp = 0;
	DWORD dwOldProtect;
	DWORD dwPid = GetCurrentProcessId();
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);

	//恢复API函数入口前5个字节
	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, PAGE_READWRITE, &dwOldProtect);
	WriteProcessMemory(hProcess, pfOldMsgBoxW, OldCode, 5, 0);
	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, dwOldProtect, &dwTemp);
}

完整代码

#include <iostream>
#include <Windows.h>

using namespace std;

FARPROC pfOldMsgBoxW;
BYTE NewCode[5] = {0xe9}, OldCode[5];

void HookOn()
{
	DWORD dwTemp = 0;
	DWORD dwOldProtect;
	DWORD dwPid = GetCurrentProcessId();
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);

	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, PAGE_READWRITE, &dwOldProtect);
	WriteProcessMemory(hProcess, pfOldMsgBoxW, NewCode, 5, 0);
	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, dwOldProtect, &dwTemp);
}

void HookOff()
{
	DWORD dwTemp = 0;
	DWORD dwOldProtect;
	DWORD dwPid = GetCurrentProcessId();
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);

	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, PAGE_READWRITE, &dwOldProtect);
	WriteProcessMemory(hProcess, pfOldMsgBoxW, OldCode, 5, 0);
	VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, dwOldProtect, &dwTemp);
}

int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
	printf("FUCK YOU VIRTUALPROTECT!\n");
	return 0;
}

int main()
{
	HMODULE hModule = LoadLibrary(L"User32.dll");
	pfOldMsgBoxW = GetProcAddress(hModule, "MessageBoxW");

	_asm
	{
		lea edi, OldCode
		mov esi, pfOldMsgBoxW
		cld
		movsd
		movsb
	}

	_asm
	{
		lea eax, MyMessageBoxW
		mov ebx, pfOldMsgBoxW
		sub eax, ebx
		sub eax, 5
		mov dword ptr[NewCode + 1], eax
	}

	MessageBoxW(0, L"test", L"test", 0);
	HookOn();
	MessageBoxW(0, L"test", L"test", 0);
	HookOff();
	MessageBoxW(0, L"test", L"test", 0);
	return 0;
}

修改IAT表

获取原函数地址

int OldAddr;
OldAddr = (int)GetProcAddress(LoadLibrary(L"user32.dll"), "MessageBoxA");

创建新函数

int WINAPI NewMessageBox (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    printf("FUCK YOU VIRTUALPROTECT!");
    return 0;
}

遍历IAT表

遍历IAT表寻找原函数的地址,将其改写为新函数的地址

int SetIATHook(int OldAddr, int NewAddr)
{
    DWORD ImageBase = 0;
    DWORD dwTemp;
    PDWORD pFunAddr = 0;
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNtHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
    PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = NULL;

    ImageBase = (DWORD)GetModuleHandle(NULL);
    pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
    pNtHeader = (PIMAGE_NT_HEADERS)(ImageBase + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + sizeof(_IMAGE_FILE_HEADER));
    pDataDirectory = pOptionalHeader->DataDirectory;
    pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)(ImageBase + (pDataDirectory + 1)->VirtualAddress);

    VirtualProtect((LPVOID)ImageBase, 0x20000, 0x40, &dwTemp);

    while (pImportDirectory->FirstThunk != 0 && pImportDirectory->OriginalFirstThunk != 0)
    {
        pFunAddr = (PDWORD)(ImageBase + pImportDirectory->FirstThunk);
        while (*pFunAddr)
        {
            if (OldAddr == *pFunAddr)
            {
                *pFunAddr = NewAddr;
                return 0;
            }
            pFunAddr++;
        }
        pImportDirectory++;
    }
    return 0;
}

完整代码

#include <iostream>
#include <stdio.h>
#include <Windows.h>

using namespace std;

int SetIATHook(int OldAddr, int NewAddr)
{
    DWORD ImageBase = 0;
    DWORD dwTemp;
    PDWORD pFunAddr = 0;
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNtHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
    PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = NULL;

    ImageBase = (DWORD)GetModuleHandle(NULL);
    pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
    pNtHeader = (PIMAGE_NT_HEADERS)(ImageBase + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + sizeof(_IMAGE_FILE_HEADER));
    pDataDirectory = pOptionalHeader->DataDirectory;
    pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)(ImageBase + (pDataDirectory + 1)->VirtualAddress);

    VirtualProtect((LPVOID)ImageBase, 0x20000, 0x40, &dwTemp);

    while (pImportDirectory->FirstThunk != 0 && pImportDirectory->OriginalFirstThunk != 0)
    {
        pFunAddr = (PDWORD)(ImageBase + pImportDirectory->FirstThunk);
        while (*pFunAddr)
        {
            if (OldAddr == *pFunAddr)
            {
                *pFunAddr = NewAddr;
                return 0;
            }
            pFunAddr++;
        }
        pImportDirectory++;
    }
    return 0;
}

int WINAPI NewMessageBox (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    printf("FUCK YOU VIRTUALPROTECT!");
    return 0;
}

int main(int argc, char* argv[])
{
    int OldAddr;
    OldAddr = (int)GetProcAddress(LoadLibrary(L"user32.dll"), "MessageBoxA");
    MessageBoxA(0, "test", "Old", 0);
    SetIATHook(OldAddr, (int)NewMessageBox);
    MessageBoxA(0, "test", "Old", 0);
    return 0;
}
posted @ 2023-03-22 16:30  Clovershrub  阅读(42)  评论(0编辑  收藏  举报