Windows Practice_Dll&Hook_IAT Hook

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表中的函数地址。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值