鱼C论坛

 找回密码
 立即注册
查看: 2683|回复: 1

inline hook api 求助

[复制链接]
发表于 2016-7-25 22:25:54 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
最近在百度学习HOOK API 的教程 根据网上的例子自已写下来发现 例子里面的MessageBoxW函数Hook 可以正常 但是我把MessageBoxW 换成CreateProcessA和CreateProcessW 或者OpenProcess 都会提示内存报错 例子里面有一段修改内存是通过了汇编代码来实现在 本人没有学过汇编 ,不懂!下面上代码 有懂的老师还望指教下!谢谢

//这下面是没有问题的MessageBox
  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <tchar.h>
  4. //以MSG定义为原型定义函数类型
  5. typedef int (WINAPI* MsgBoxW)(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
  6. typedef HANDLE (WINAPI *OpenPros)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
  7. HMODULE hmod = NULL;

  8. MsgBoxW oldmsg;  //用于存放未修改过的MSG函数地址 注意这是指针型

  9. FARPROC pfoldmsg;        //指向原函数的远指针



  10. BYTE OldCode[5];

  11. BYTE NewCode[5];

  12. DWORD dwPid = NULL;
  13. HANDLE hProcess = NULL;

  14. void HookOn()
  15. {
  16.         DWORD dwTemp = 0;
  17.         DWORD dwOldProtect;

  18.         //修改API函数入口前5个字节为jmp xxxxxx  
  19.         VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
  20.         WriteProcessMemory(hProcess, pfoldmsg, NewCode, 5, 0);
  21.         VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);

  22. }

  23. void HookOff()
  24. {
  25.         DWORD dwTemp = 0;
  26.         DWORD dwOldProtect;

  27.         //恢复API函数入口前5个字节  
  28.         VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
  29.         WriteProcessMemory(hProcess, pfoldmsg, OldCode, 5, 0);
  30.         VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);
  31. }

  32. HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
  33. {
  34.         MessageBoxW(NULL, _T("哈哈,MessageBoxW被HOOK了"), L"OPENPROCESS", MB_OK);
  35.         return 0;
  36. }

  37. int WINAPI MyMessageBoxW(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
  38. {
  39.        
  40.         HookOff();//调用原函数之前,记得先恢复HOOK呀,不然是调用不到的  
  41.         //如果不恢复HOOK,就调用原函数,会造成死循环  
  42.         //毕竟调用的还是我们的函数,从而造成堆栈溢出,程序崩溃。  

  43.         int nRet = ::MessageBoxW(hwnd, _T("哈哈,MessageBoxW被HOOK了"), lpCaption, uType);

  44.         HookOn();//调用完原函数后,记得继续开启HOOK,不然下次会HOOK不到。   

  45.         return nRet;;
  46.        
  47. }

  48. void writeold()
  49. {
  50.         //保存原API入口的前5个字节

  51.         //保存的目的是为了恢复用的,毕竟我们HOOK了API后,还需要调用真实的API嘛,

  52.         //如何保存一个函数入口的前5个字节呢?这里用到了汇编代码,至于不用汇编可以吗?我想是可以的。

  53.         //有空时,我再试一下,不用汇编是否能保存一个API入口的前5个字节,这里就先用别人写的汇编代码吧,

  54.         _asm
  55.         {
  56.                 lea edi, OldCode        ////获取OldCode数组的地址,放到edi
  57.                         mov esi, pfoldmsg //获取原API入口地址,放到esi
  58.                         cld //方向标志位,为以下俩条指令做准备
  59.                         movsd //复制原API入口前4个字节到OldCode数组
  60.                         movsb //复制原API入口第5个字节到OldCode数组
  61.         }

  62. }

  63. void writenew()
  64. {

  65.         //获取MyMessageBoxW的相对地址,为Jmp做准备  
  66.         //int nAddr= UserFunAddr – SysFunAddr - (我们定制的这条指令的大小);  
  67.         //Jmp nAddr;  
  68.         //(我们定制的这条指令的大小), 这里是5,5个字节嘛  
  69.         //填充完毕,现在NewCode[]里的指令相当于Jmp MyMessageBoxW  
  70.         //既然已经获取到了Jmp MyMessageBoxW  
  71.         //现在该是将Jmp MyMessageBoxW写入原API入口前5个字节的时候了  
  72.         //知道为什么是5个字节吗?  
  73.         //Jmp指令相当于0xe9,占一个字节的内存空间  
  74.         //MyMessageBoxW是一个地址,其实是一个整数,占4个字节的内存空间  
  75.         //int n=0x123;   n占4个字节和MyMessageBoxW占4个字节是一样的  
  76.         //1+4=5,知道为什么是5个字节了吧  
  77.         NewCode[0] = 0xe9;//实际上0xe9就相当于jmp指令
  78.         _asm
  79.         {
  80.                 lea eax, MyMessageBoxW //获取我们的MyMessageBoxW函数地址  
  81.                         mov ebx, pfoldmsg  //原系统API函数地址  
  82.                         sub eax, ebx           //int nAddr= UserFunAddr – SysFunAddr  
  83.                         sub eax, 5             //nAddr=nAddr-5  
  84.                         mov dword ptr[NewCode + 1], eax //将算出的地址nAddr保存到NewCode后面4个字节  
  85.                         //注:一个函数地址占4个字节  
  86.         }

  87. }

  88. int main()
  89. {
  90.        

  91.         //有了保存原API函数地址的变量OldMsgBox和指向原API函数的远指针,我们就可以获取真实API的地址了

  92.         //获取原API入口地址
  93.         hmod = LoadLibrary(_T("User32.dll")); //载入DLL文件

  94.         oldmsg = (MsgBoxW)GetProcAddress(hmod, "MessageBoxW");        //获得DLL文件中MESSAGEBOXW函数地址

  95.         pfoldmsg = (FARPROC)oldmsg;

  96.         dwPid = ::GetCurrentProcessId();

  97.         hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);

  98.         //poldmsg = (BYTE*)oldmsg ;
  99.         writeold();
  100.         writenew();
  101.        
  102.         HookOn();
  103.         MessageBox(NULL, _T("获取原API入口地址出错"), _T("error!"), 0);
  104.        
  105. }
复制代码


//这下面是我改成OpenProcess后的代码 会提示内存错误

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <tchar.h>
  4. //以MSG定义为原型定义函数类型
  5. typedef int (WINAPI* MsgBoxW)(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
  6. typedef HANDLE (WINAPI *OpenPros)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
  7. HMODULE hmod = NULL;

  8. OpenPros oldmsg;  //用于存放未修改过的MSG函数地址 注意这是指针型

  9. FARPROC pfoldmsg;        //指向原函数的远指针



  10. BYTE OldCode[5];

  11. BYTE NewCode[5];

  12. DWORD dwPid = NULL;
  13. HANDLE hProcess = NULL;

  14. void HookOn()
  15. {
  16.         DWORD dwTemp = 0;
  17.         DWORD dwOldProtect;

  18.         //修改API函数入口前5个字节为jmp xxxxxx  
  19.         VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
  20.         WriteProcessMemory(hProcess, pfoldmsg, NewCode, 5, 0);
  21.         VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);

  22. }

  23. void HookOff()
  24. {
  25.         DWORD dwTemp = 0;
  26.         DWORD dwOldProtect;

  27.         //恢复API函数入口前5个字节  
  28.         VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
  29.         WriteProcessMemory(hProcess, pfoldmsg, OldCode, 5, 0);
  30.         VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);
  31. }

  32. HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
  33. {
  34.         MessageBoxW(NULL, _T("哈哈,MessageBoxW被HOOK了"), L"OPENPROCESS", MB_OK);
  35.         return 0;
  36. }

  37. int WINAPI MyMessageBoxW(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
  38. {
  39.        
  40.         HookOff();//调用原函数之前,记得先恢复HOOK呀,不然是调用不到的  
  41.         //如果不恢复HOOK,就调用原函数,会造成死循环  
  42.         //毕竟调用的还是我们的函数,从而造成堆栈溢出,程序崩溃。  

  43.         int nRet = ::MessageBoxW(hwnd, _T("哈哈,MessageBoxW被HOOK了"), lpCaption, uType);

  44.         HookOn();//调用完原函数后,记得继续开启HOOK,不然下次会HOOK不到。   

  45.         return nRet;;
  46.        
  47. }

  48. void writeold()
  49. {
  50.         //保存原API入口的前5个字节

  51.         //保存的目的是为了恢复用的,毕竟我们HOOK了API后,还需要调用真实的API嘛,

  52.         //如何保存一个函数入口的前5个字节呢?这里用到了汇编代码,至于不用汇编可以吗?我想是可以的。

  53.         //有空时,我再试一下,不用汇编是否能保存一个API入口的前5个字节,这里就先用别人写的汇编代码吧,

  54.         _asm
  55.         {
  56.                 lea edi, OldCode        ////获取OldCode数组的地址,放到edi
  57.                         mov esi, pfoldmsg //获取原API入口地址,放到esi
  58.                         cld //方向标志位,为以下俩条指令做准备
  59.                         movsd //复制原API入口前4个字节到OldCode数组
  60.                         movsb //复制原API入口第5个字节到OldCode数组
  61.         }

  62. }

  63. void writenew()
  64. {

  65.         //获取MyMessageBoxW的相对地址,为Jmp做准备  
  66.         //int nAddr= UserFunAddr – SysFunAddr - (我们定制的这条指令的大小);  
  67.         //Jmp nAddr;  
  68.         //(我们定制的这条指令的大小), 这里是5,5个字节嘛  
  69.         //填充完毕,现在NewCode[]里的指令相当于Jmp MyMessageBoxW  
  70.         //既然已经获取到了Jmp MyMessageBoxW  
  71.         //现在该是将Jmp MyMessageBoxW写入原API入口前5个字节的时候了  
  72.         //知道为什么是5个字节吗?  
  73.         //Jmp指令相当于0xe9,占一个字节的内存空间  
  74.         //MyMessageBoxW是一个地址,其实是一个整数,占4个字节的内存空间  
  75.         //int n=0x123;   n占4个字节和MyMessageBoxW占4个字节是一样的  
  76.         //1+4=5,知道为什么是5个字节了吧  
  77.         NewCode[0] = 0xe9;//实际上0xe9就相当于jmp指令
  78.         _asm
  79.         {
  80.                 lea eax, MyOpenProcess //获取我们的MyMessageBoxW函数地址  
  81.                         mov ebx, pfoldmsg  //原系统API函数地址  
  82.                         sub eax, ebx           //int nAddr= UserFunAddr – SysFunAddr  
  83.                         sub eax, 5             //nAddr=nAddr-5  
  84.                         mov dword ptr[NewCode + 1], eax //将算出的地址nAddr保存到NewCode后面4个字节  
  85.                         //注:一个函数地址占4个字节  
  86.         }

  87. }

  88. int main()
  89. {
  90.        

  91.         //有了保存原API函数地址的变量OldMsgBox和指向原API函数的远指针,我们就可以获取真实API的地址了

  92.         //获取原API入口地址
  93.         hmod = LoadLibrary(_T("Kernel32.dll")); //载入DLL文件

  94.         oldmsg = (OpenPros)GetProcAddress(hmod, "OpenProcess");        //获得DLL文件中MESSAGEBOXW函数地址

  95.         pfoldmsg = (FARPROC)oldmsg;

  96.         dwPid = ::GetCurrentProcessId();

  97.         hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);

  98.        
  99.         writeold();
  100.         writenew();
  101.        
  102.         HookOn();
  103.         MessageBox(NULL, _T("获取原API入口地址出错"), _T("error!"), 0);
  104.        
  105. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2016-7-26 11:45:32 | 显示全部楼层
什么情况 没有人吗 !自已顶一下。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-14 15:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表