概述:Hook注入的模版函数,以 Hook loadlibrary 为例

主要是创建了 __InlineHOOK_Base 用于实现函数的注入。

由于程序在创建和执行时会使用 LoadLibrary 函数。 因此需要在调用是时先 unhook 在

Hook模版

以下两个宏定义即可完成函数的hook

/*
    C/C++ HOOK API(原理深入剖析之-LoadLibraryA)_c++ loadlibrarya-CSDN博客: 
    https://blog.csdn.net/masefee/article/details/4566121
*/
#include <iostream>
#include <Windows.h>
using namespace std;
 
#pragma warning( disable: 4309 )
#pragma warning( disable: 4311 )
 
typedef HMODULE(WINAPI* HOOKAPI)(IN LPCSTR);
#define MYHOOKMETHOD(__fun) HMODULE WINAPI __fun
#define DECLARE_REGISTER( __0bj, __lawfunc, __newfunc ) Inline_Hook< HOOKAPI, 1 > __Obj( __lawfunc, __newfunc )
 
struct __InlineHOOK_Base
{
    DWORD _argsBytes;
    void* _lawFunc;
    void* _newFunc;
    char  _lawByteCode[16];
    char  _newByteCode[16];
 
    bool unhook(void)
    {
        // It's hooked.
        if (memcmp(_newByteCode, _lawFunc, 16) == 0)
        {
            DWORD dwOldFlag;
            VirtualProtect(_lawFunc, 8, PAGE_EXECUTE_READWRITE, &dwOldFlag);
            memcpy(_lawFunc, _lawByteCode, 16);
            VirtualProtect(_lawFunc, 8, dwOldFlag, &dwOldFlag);
            return true;
        }
 
        return false;
    }
 
    bool hook(void)
    {
        // It's saved.
        if (memcmp(_lawByteCode, _lawFunc, 16) == 0)
        {
            DWORD dwOldFlag;
            VirtualProtect(_lawFunc, 8, PAGE_EXECUTE_READWRITE, &dwOldFlag);
            memcpy(_lawFunc, _newByteCode, 16);
            VirtualProtect(_lawFunc, 8, dwOldFlag, &dwOldFlag);
            return true;
        }
 
        return false;
    }
 
    __InlineHOOK_Base(void* lawfun, void* newfun, DWORD args);
};
 
 
void __declspec(naked) __Inline_Hook_Func(void)
{
    __asm
    {
        push ebp  // save maybe usefull register.
        push ebx
        push esi
        push ecx
        call __InlineHOOK_Base::unhook  // first, remove the hook in order to call the normal function.
        test eax, eax   // check the remove was successful
        jz __return
 
 
    __getargnum :
        mov eax, dword ptr[esp] // esp just is ecx, also is __InlineHOOK_Base's this pointer.
        mov ecx, dword ptr[eax] // get first 4 bytes, that is params total size.
        shr ecx, 2  // get params num, equal with __InlineHOOK_Base::_argsBytes / sizeof( DWORD )
        test ecx, ecx   // check whether there are params.
        jz __callfunc   // no param
 
 
    __pushargs :
        mov edx, esp    // __InlineHOOK_Base's this pointer.
        add edx, 14h    // navigate to first call ret addr.
        add edx, dword ptr[eax]; // add params size.
        push dword ptr[edx];    // push the dll file name pointer.
        loop __pushargs
 
 
    __callfunc :
        call[eax + 8]   // call my function .
        mov ecx, dword ptr[esp]  // get __InlineHOOK_Base's this pointer.
 
        push edx        // save my function return value.
        push eax
 
        call __InlineHOOK_Base::hook   // rehook.
 
        pop eax                  // get saved return value, provided to my superiors to use
        pop edx
 
 
    __return :
        pop ecx
        pop esi
        pop ebx
        pop ebp
        ret
    }
}
 
__InlineHOOK_Base::__InlineHOOK_Base(void* lawfun, void* newfun, DWORD args)
    : _lawFunc(lawfun), _newFunc(newfun), _argsBytes(args * 4)
{
    _newByteCode[0] = 0xB9;     // mov ecx, ...
    (DWORD&)_newByteCode[1] = (DWORD)this;
    _newByteCode[5] = 0xB8;     // mov eax, ...
    (DWORD&)_newByteCode[6] = (DWORD)__Inline_Hook_Func;
    (WORD&)_newByteCode[10] = 0xD0FF;       // call eax
    _newByteCode[12] = 0x000000C3;          // ret
 
    if (args > 0)
    {
        _newByteCode[12] = 0xC2;        // ret ...
        (WORD&)_newByteCode[13] = (WORD)_argsBytes;
        _newByteCode[15] = 0;
    }
 
    memcpy(_lawByteCode, _lawFunc, 16); // save
}
 
 
template< typename _function, DWORD args >
struct Inline_Hook : __InlineHOOK_Base
{
    Inline_Hook(_function lawfun, _function newfun)
        :__InlineHOOK_Base(lawfun, newfun, args) {
        hook();
    }
    ~Inline_Hook(void) { unhook(); }
};
 
MYHOOKMETHOD(myLoadLibrary)(LPCSTR lpcStrFileName)
{
    ::MessageBoxA(NULL, lpcStrFileName, "LoadLibrary Name", MB_OK | MB_ICONINFORMATION);
    return LoadLibraryA(lpcStrFileName);
}
 
 
DECLARE_REGISTER(__inline_hook, LoadLibraryA, myLoadLibrary);
 
 
int main(void)
{
    HMODULE hIntstance = LoadLibraryA("d3d9.dll");
    return 0;
}

如何使用,使用宏进行注入,在程序执行前完成。

DECLARE_REGISTER(__inline_hook, LoadLibraryA, myLoadLibrary);