有过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字节
当然了,要实现类似的效果还有很多其实方法,随着学习的深入,以及对指令的熟悉,
举一反三也就有迹可循了。
#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; }