我的API HOOK庫


API HOOK有兩種做法,一種是SetWindowHookEx,簡單易用,但如果做其它的HOOK,如HOOK OpenProcess,就需要修改內存地址了,內存地址可以通過WriteProcessMemory來修改,先將調用函數的地址改成自己的(jmp到自己的函數),然后需要時,再改回來。

#pragma once

#ifdef _M_IX86
template <typename T>
class Hooker
{
protected:
    static DWORD HookFunction(LPCWSTR lpModule, LPCSTR lpFuncName, PROC lpFunction)
    {
        DWORD dwAddr = (DWORD) GetProcAddress(GetModuleHandle(lpModule), lpFuncName);
        BYTE jmp [] =
        {
            0xe9,    //jmp
            0x00, 0x00, 0x00, 0x00,    //address
            0xc3    //retn
        };

        ReadProcessMemory(GetCurrentProcess(), (LPVOID) dwAddr, MemoryAddress(), 6, 0);

        DWORD dwCalc = ((DWORD) lpFunction - dwAddr - 5);    //((to)-(from)-5)

        memcpy(&jmp[1], &dwCalc, 4);    //build the jmp

        WriteProcessMemory(GetCurrentProcess(), (LPVOID) dwAddr, jmp, 6, 0);

        return dwAddr;
    }

    static BOOL UnHookFunction(LPCWSTR lpModule, LPCSTR lpFuncName)
    {
        DWORD dwAddr = (DWORD) GetProcAddress(GetModuleHandle(lpModule), lpFuncName);

        if (WriteProcessMemory(GetCurrentProcess(), (LPVOID) dwAddr, MemoryAddress(), 6, 0))
            return TRUE;

        return FALSE;
    }

    static BYTE* MemoryAddress()
    {
        static BYTE backup[6];
        return backup;
    }
};
#elif _M_AMD64
template <typename T>
class Hooker
{
protected:
    static UINT64 HookFunction(LPCWSTR lpModule, LPCSTR lpFuncName, LPVOID lpFunction)
    {
        UINT64 dwAddr = (UINT64) GetProcAddress(GetModuleHandle(lpModule), lpFuncName);
        BYTE jmp [] =
        {
            0x48, 0xb8,    //jmp
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, //address
            0x50, 0xc3  //retn
        };

        ReadProcessMemory(GetCurrentProcess(), (LPVOID) dwAddr, MemoryAddress(), 12, 0);

        UINT64 dwCalc = (UINT64) lpFunction;

        memcpy(&jmp[2], &dwCalc, 8);    //build the jmp

        WriteProcessMemory(GetCurrentProcess(), (LPVOID) dwAddr, jmp, 12, nullptr);

        return dwAddr;
    }

    static BOOL UnHookFunction(LPCWSTR lpModule, LPCSTR lpFuncName)
    {
        UINT64 dwAddr = (UINT64) GetProcAddress(GetModuleHandle(lpModule), lpFuncName);

        if (WriteProcessMemory(GetCurrentProcess(), (LPVOID) dwAddr, MemoryAddress(), 12, 0))
            return TRUE;

        return FALSE;
    }

    static BYTE* MemoryAddress()
    {
        static BYTE backup[12];
        return backup;
    }
};
#endif
View Code

值得注意的是,64位和32位的注入字節有些許不同。

由於目前Visual Studio 2013 Preview實現的C++類中,還是不允許有非int靜態變量,但卻允許函數中有靜態變量,所以我將目標指針數據備份到靜態成員中:

    static BYTE* MemoryAddress()
    {
        static BYTE backup[6];
        return backup;
    }

然后,在使用時,從Hooker繼承一個類即可:

class MessageBoxHooker : Hooker<MessageBoxHooker>
{
public:
    static void BeginHook()
    {
        HookFunction(L"user32.dll", "MessageBoxW", (PROC) MyMessageBoxW);
    }
    static void StopHook()
    {
        UnHookFunction(L"user32.dll", "MessageBoxW");
    }
private:
    static int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
    {
        StopHook();
        int x = MessageBox(hWnd, L"hooked", lpCaption, uType);
        BeginHook();
        return x;
    }
};
View Code

要開啟Hook,只需調用:

MessageBoxHooker::BeginHook();

這個API HOOK庫我使了一個模板,之所以用模板是因為C++函數指針不包含實例的指針。這種使用模板來解決C++指針的缺點的做法很常見,ATL也是這樣實現的。

 

本文提供的代碼可以隨意引用,但請充分測試后再部署,出問題本人不承擔任何責任,歡迎有任何建議和補充~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM