Windows下64位程序的Inline Hook


有過32位hook的介紹,代碼不是主要的,所以貼在最后,首先記述下原理。

主體代碼還是參考與那本關於黑客技術的書,部分內容則參考自以下博客。

https://blog.csdn.net/zuishikonghuan/article/details/47979603

原理:
mov rax,地址 push rax ret
64位程序中,jmp 貌似也只能跳轉4字節的偏移,而程序的地址都是8字節。所以單獨一條jmp指令不足以實現功能。

這也是原理上的不同。
rax是一個64位寄存器,首先把程序地址保存到rax寄存器中。
隨后把rax寄存器的內容壓入棧中。
最后使用ret返回。
關鍵之處在於ret指令返回的地址就是棧頂里面的內容。
所以ret后直接跳到了我們指定函數的地址中。

有了32位Inline Hook的經驗,我們對照着代碼,使用x64dbg調試(功能類似於OD,但是支持64位程序),會比較容易理解。

本次需要12字節:
mov rax,地址 => 0x48 0xb8 + 8字節地址 = 10字節
push rax => 0x50 1字節
ret => 0xc3 1字節

當然了,要實現類似的效果還有很多其實方法,隨着學習的深入,以及對指令的熟悉,
舉一反三也就有跡可循了。
以下為另一篇關於64位Hook的博客,這里記錄以下,方便日后參考
https://www.cnblogs.com/iBinary/p/11334793.html

 

#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;
#define len 12
class MyHook
{
public:
    MyHook()
    {
        funcAddr = NULL;
        ZeroMemory(oldBytes,len);
        ZeroMemory(newBytes,len);
    }
    ~MyHook()
    {
        UnHook();
        funcAddr = NULL;
        ZeroMemory(oldBytes,len);
        ZeroMemory(newBytes,len);
    }
    /*
     *Hook的模塊名稱,Hook的API函數名稱,鈎子函數地址
    */
    WINBOOL Hook(LPSTR ModuleName, LPSTR FuncName, PROC HookFunc)
    {
        BOOL bRet = FALSE;
        funcAddr = (PROC)GetProcAddress(GetModuleHandleA(ModuleName),FuncName);
        if(funcAddr!=NULL)
        {
            SIZE_T num = 0;
            ReadProcessMemory(GetCurrentProcess(),(void*)funcAddr,oldBytes,len,&num);
            for (int i = 0; i < len; i++)
            {
                printf("%0x ", oldBytes[i]);
            }
            cout << " finish" << endl;
            newBytes[0] = 0x48;
            newBytes[1] = 0xB8;
            newBytes[10] = 0x50;
            newBytes[11] = 0xC3;
            memcpy(newBytes+2,(void*)&HookFunc,8);
            for(int i=0;i<12;i++)
            {
                printf("%0x ",newBytes[i]);
            }
            cout<<endl;
            WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,newBytes,len,&num);
            cout<<"mytest"<<endl;
            bRet = TRUE;
        }
        return bRet;
    }
    void UnHook()
    {
        if(funcAddr!=0)
        {
            SIZE_T num = 0;
            WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,oldBytes,len,&num);
        }
    }
    WINBOOL ReHook()
    {
        BOOL ret = FALSE;
        if(funcAddr!=0)
        {
            SIZE_T num;
            WriteProcessMemory(GetCurrentProcess(),(void*)funcAddr,newBytes,len,&num);
            ret = TRUE;
        }
        return ret;
    }

private:
    PROC funcAddr;
    BYTE oldBytes[len];
    BYTE newBytes[len];
};

MyHook hook;
int WINAPI MyMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT type)
{
    hook.UnHook();
    MessageBox(hWnd,"Hook流程",lpCaption,type);
    MessageBox(hWnd,lpText,lpCaption,type);
    hook.ReHook();
    return 0;
}
int main()
{

    MessageBox(NULL,"正常流程1","test",MB_OK);
    hook.Hook((LPSTR)"User32.dll",(LPSTR)"MessageBoxA",(PROC)&MyMessageBoxA);
    MessageBox(NULL,"被Hook了1","test",MB_OK);
    MessageBox(NULL,"被Hook了2","test",MB_OK);
    cout<<"finish"<<endl;
    hook.UnHook();
    MessageBox(NULL,"正常流程2","test",MB_OK); 
    cout<<&MyMessageBoxA<<endl;
}

 


免責聲明!

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



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