首页 > 编程 > C++ > 正文

Inline Hook(ring3)的简单C++实现方法

2020-01-26 15:25:32
字体:
来源:转载
供稿:网友

C++的Inline Hook代码,采用了备份dll的方法,因此在自定义的函数中可以直接调用在内存中备份的dll代码,而不需要把函数头部改来改去。用SetWindowsHookEx程序的稳定性应该会增加许多。

需要注意的是,例子中没有把原函数的头部几个字节改回去是因为,程序很简单,仅仅测试了效果后便可以退出,没有其他的功能。实际应用中,还要在你注入的dll模块卸载时,把原函数的头几个字节改回去,以免影响到程序继续运行的稳定性。(因为注入的程序不是自己的,我们当然不可能知道它到底在何时、有多少个我们所Hook的函数的调用)。

具体实现代码如下:

#include <ntifs.h>#include <windef.h> #include <stdio.h>#pragma comment(lib, "psapi.lib")//BYTE Org_Code[7];// 备份dll法, 因此就可以不需要BYTE New_Code[7];HMODULE hDllHandle = NULL; // 被 Hook 的 DLL 句柄HANDLE hProcess = NULL; // 进程句柄LPVOID _MessageBoxA = NULL; // MessageBoxA() 原地址DWORD _ShowMessage = NULL; // 自定义函数地址void InlineHook();//void UnInlineHook(); // 备份dll法, 因此就可以不需要void BackupDll();// 自定义函数int WINAPI ShowMessage(HWND, LPTSTR, LPTSTR, UINT);void main(){  hProcess = ::GetCurrentProcess();  hDllHandle = ::LoadLibrary("user32.dll");  if (hDllHandle == NULL)    return;  _MessageBoxA = (LPVOID)::GetProcAddress(hDllHandle, "MessageBoxA");  if (_MessageBoxA == NULL)    return;  BackupDll();  InlineHook();  char szText[256];  char szTitle[256];  memset(szText, 0x0, sizeof(szText));  memset(szTitle, 0x0, sizeof(szTitle));  // 下列循环接收来自于用户输入的字符, 并使用 MessageBoxA()  //来显示, 尝试下, 看看发生了什么. :)  while (TRUE)  {    printf("Message Text: ");    scanf("%s", szText);    printf("Message Title: ");    scanf("%s", szTitle);    MessageBoxA(NULL, szText, szTitle, 0);    printf("/n");  }  return;}void InlineHook(){  DWORD _JmpAddr = (DWORD)ShowMessage;  // 构造新头部代码  New_Code[0] = 0xB8;            //  memcpy(&New_Code[1], &_JmpAddr, 4);    // mov eax, _JmpAddr  New_Code[5] = 0xFF;            //  New_Code[6] = 0xE0;            // jmp eax  DWORD dwOldProtect = 0;  // 去内存保护  ::VirtualProtect(_MessageBoxA, 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);  // 把新代码写入 MessageBoxA() 的头部, 这也是Inline Hook  //的核心所在.  ::WriteProcessMemory(    hProcess,    _MessageBoxA,    New_Code,    sizeof(New_Code),    NULL  );  // 写内存保护  ::VirtualProtect(_MessageBoxA, 7, dwOldProtect, &dwOldProtect);  return;}/*void UnInlineHook() // 备份dll法, 因此就可以不需要{  return;}*/int WINAPI ShowMessage(HWND hWnd, LPTSTR lpText, LPTSTR lpTitle, UINT uType){  typedef int WINAPI SHOWMSG(HWND hWnd, LPTSTR lpText, LPTSTR lpTitle, UINT uType);  SHOWMSG *pShowMsg = (SHOWMSG*)_ShowMessage;  // 废弃原先传入的参数, 自己定义对话框文本  char buf[1024];  ::wsprintf(buf, "The Text:"%s" was hacked by miku_fl", lpText);  return pShowMsg(hWnd, buf, lpTitle, MB_ICONINFORMATION | MB_TOPMOST);}void BackupDll(){  MODULEINFO  Mdl_Info;  LPVOID    lpNewDLL  =  NULL;  // 获取模块信息  ::GetModuleInformation(hProcess, hDllHandle, &Mdl_Info, sizeof(Mdl_Info));  // 分配内存空间, 用于备份 dll (这样一来就不需要恢复原头部代码, 调用  //完之后再重新写自定义的头部代码).  lpNewDLL = ::VirtualAllocEx(    hProcess,    NULL,    Mdl_Info.SizeOfImage,    MEM_COMMIT,    PAGE_EXECUTE_READWRITE  );  if (lpNewDLL == NULL)    return;  // 在分配的内存中写入 dll 文件的内容  ::WriteProcessMemory(hProcess, lpNewDLL, Mdl_Info.lpBaseOfDll, Mdl_Info.SizeOfImage, NULL);  // 计算自定义函数的地址.  // 公式: 自定义地址 = 原API函数地址 - 模块基址 + 分配内存的基址  _ShowMessage = (DWORD)_MessageBoxA - (DWORD)Mdl_Info.lpBaseOfDll + (DWORD)lpNewDLL;  return;}

希望本文所述程序实例能对大家有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表