• 我的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也是这样实现的。

    本文提供的代码可以随意引用,但请充分测试后再部署,出问题本人不承担任何责任,欢迎有任何建议和补充~

  • 相关阅读:
    Linux_23 DNS 正向解析区域、反向解析区域;主/从;子域;基本安全控制
    Linux_22 加密和解密及OpenSSL
    Linux_21 日志系统、ssh服务、系统安装及系统故障排除
    Linux_20 子网划分
    Akavache简明使用指南
    Oracle存储过程解析XML内容
    docker部署微服务不支持中文字体的解决方案
    Three.js
    Three.js
    [Linux] vim状态栏配置
  • 原文地址:https://www.cnblogs.com/sdflysha/p/my-api-hook-library.html
Copyright © 2020-2023  润新知