Windows Practice_Dll&Hook_IAT Hook

来源:互联网 发布:金鹏远 知乎 编辑:程序博客网 时间:2024/06/15 07:11

PE结构

PE结构时Windows中一个比较大的结构体,它的整个结构体图如下所示:
这里写图片描述

给MessageBoxW函数挂钩我们自己的函数

就是我们挂钩之后,调用MessageBoxW函数后,会进入到我们自己的函数中执行我们自己的代码。挂钩还原之后,还可以正常的调用MessageBoxW函数,这就是这个测试程序的功能。

// IATHookDemo.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <Windows.h>#include <DbgHelp.h>#pragma comment(lib, "Dbghelp")DWORD g_dwOldFunc, g_dwNewFunc;// 写到DLL中typedef int (WINAPI *MESSAGEBOXW_FUNC)(_In_opt_ HWND hWnd, _In_opt_ LPCTSTR lpText, _In_opt_ LPCTSTR lpCaption, _In_ UINT uType);BOOL ResetHook(DWORD dwOldFunc, DWORD dwNewFunc){    BOOL bRet = FALSE;    HANDLE hMod = GetModuleHandle(nullptr);    IMAGE_DOS_HEADER *pDosHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(hMod);    IMAGE_OPTIONAL_HEADER *pOptHeader = reinterpret_cast<IMAGE_OPTIONAL_HEADER *>(reinterpret_cast<BYTE *>(hMod) + pDosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));    IMAGE_IMPORT_DESCRIPTOR *pImportDesc = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR *>(static_cast<BYTE *>(hMod) + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);    while (pImportDesc->FirstThunk)    {        char *strDllName = reinterpret_cast<char *>(static_cast<BYTE *>(hMod) + pImportDesc->Name);        if (strcmp(strDllName, "USER32.dll") == 0)        {            break;        }        ++pImportDesc;    }    if (pImportDesc->FirstThunk)    {        IMAGE_THUNK_DATA *pThunkData = reinterpret_cast<IMAGE_THUNK_DATA *>(static_cast<BYTE *>(hMod) + pImportDesc->FirstThunk);        while (pThunkData->u1.Function)        {            if (pThunkData->u1.Function == dwNewFunc)            {                DWORD *lpAddr = &(pThunkData->u1.Function);                DWORD dwOldProtect;                MEMORY_BASIC_INFORMATION mbi;                VirtualQuery(lpAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION));                VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);                pThunkData->u1.Function = dwOldFunc;                VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, nullptr);                bRet = TRUE;                break;            }        }    }    return bRet;}int WINAPI MyMessageBox(_In_opt_ HWND hWnd, _In_opt_ LPCTSTR lpText, _In_opt_ LPCTSTR lpCaption, _In_ UINT uType){    MESSAGEBOXW_FUNC func = (MESSAGEBOXW_FUNC)g_dwOldFunc;    return func(nullptr, L"成功修改MessageBowW函数", L"提示", MB_OK);}BOOL MySetHook(){    // 使用普通的方式查找要替换的函数地址    BOOL bRet = FALSE;    HANDLE hMod = GetModuleHandle(nullptr);    IMAGE_DOS_HEADER *pDosHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(hMod);    IMAGE_OPTIONAL_HEADER *pOptHeader = reinterpret_cast<IMAGE_OPTIONAL_HEADER *>(reinterpret_cast<BYTE *>(hMod) + pDosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));    IMAGE_IMPORT_DESCRIPTOR *pImportDesc = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR *>(static_cast<BYTE *>(hMod) + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);    while (pImportDesc->FirstThunk)    {        char *strDllName = reinterpret_cast<char *>(static_cast<BYTE *>(hMod) + pImportDesc->Name);        if (strcmp(strDllName, "USER32.dll") == 0)        {            break;        }        ++pImportDesc;    }    if (pImportDesc->FirstThunk)    {        DWORD dwFuncAddr = reinterpret_cast<DWORD>(MessageBoxW);        IMAGE_THUNK_DATA *pThunkData = reinterpret_cast<IMAGE_THUNK_DATA *>(static_cast<BYTE *>(hMod) + pImportDesc->FirstThunk);        while (pThunkData->u1.Function)        {            if (pThunkData->u1.Function == dwFuncAddr)            {                DWORD *lpAddr = &(pThunkData->u1.Function);                DWORD dwOldProtect;                MEMORY_BASIC_INFORMATION mbi;                VirtualQuery(lpAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION));                VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);                g_dwOldFunc = pThunkData->u1.Function;                pThunkData->u1.Function = reinterpret_cast<DWORD>(MyMessageBox);                g_dwNewFunc = pThunkData->u1.Function;                VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, nullptr);                bRet = TRUE;                break;            }        }    }    return bRet;}int main(){    MessageBoxW(nullptr, L"Test", L"Tips", MB_OK);    MySetHook();    MessageBoxW(nullptr, L"Test", L"Tips", MB_OK);    ResetHook(g_dwOldFunc, g_dwNewFunc);    MessageBoxW(nullptr, L"Test", L"Tips", MB_OK);    system("pause");    return 0;}

这个程序一般没有什么问题,但是有一点需要注意,那就是我们在修改程序地址的时候,会出现修改失败,这是因为我们没有写的权限。需要修改这一段内存空间的读写权限,把它改为可读可写的权限,这样才能修改IAT表中的函数地址。