|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
最近在百度学习HOOK API 的教程 根据网上的例子自已写下来发现 例子里面的MessageBoxW函数Hook 可以正常 但是我把MessageBoxW 换成CreateProcessA和CreateProcessW 或者OpenProcess 都会提示内存报错 例子里面有一段修改内存是通过了汇编代码来实现在 本人没有学过汇编 ,不懂!下面上代码 有懂的老师还望指教下!谢谢
//这下面是没有问题的MessageBox
- #include <stdio.h>
- #include <windows.h>
- #include <tchar.h>
- //以MSG定义为原型定义函数类型
- typedef int (WINAPI* MsgBoxW)(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
- typedef HANDLE (WINAPI *OpenPros)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
- HMODULE hmod = NULL;
- MsgBoxW oldmsg; //用于存放未修改过的MSG函数地址 注意这是指针型
- FARPROC pfoldmsg; //指向原函数的远指针
- BYTE OldCode[5];
- BYTE NewCode[5];
- DWORD dwPid = NULL;
- HANDLE hProcess = NULL;
- void HookOn()
- {
- DWORD dwTemp = 0;
- DWORD dwOldProtect;
- //修改API函数入口前5个字节为jmp xxxxxx
- VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
- WriteProcessMemory(hProcess, pfoldmsg, NewCode, 5, 0);
- VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);
- }
- void HookOff()
- {
- DWORD dwTemp = 0;
- DWORD dwOldProtect;
- //恢复API函数入口前5个字节
- VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
- WriteProcessMemory(hProcess, pfoldmsg, OldCode, 5, 0);
- VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);
- }
- HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
- {
- MessageBoxW(NULL, _T("哈哈,MessageBoxW被HOOK了"), L"OPENPROCESS", MB_OK);
- return 0;
- }
- int WINAPI MyMessageBoxW(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
- {
-
- HookOff();//调用原函数之前,记得先恢复HOOK呀,不然是调用不到的
- //如果不恢复HOOK,就调用原函数,会造成死循环
- //毕竟调用的还是我们的函数,从而造成堆栈溢出,程序崩溃。
- int nRet = ::MessageBoxW(hwnd, _T("哈哈,MessageBoxW被HOOK了"), lpCaption, uType);
- HookOn();//调用完原函数后,记得继续开启HOOK,不然下次会HOOK不到。
- return nRet;;
-
- }
- void writeold()
- {
- //保存原API入口的前5个字节
- //保存的目的是为了恢复用的,毕竟我们HOOK了API后,还需要调用真实的API嘛,
- //如何保存一个函数入口的前5个字节呢?这里用到了汇编代码,至于不用汇编可以吗?我想是可以的。
- //有空时,我再试一下,不用汇编是否能保存一个API入口的前5个字节,这里就先用别人写的汇编代码吧,
- _asm
- {
- lea edi, OldCode ////获取OldCode数组的地址,放到edi
- mov esi, pfoldmsg //获取原API入口地址,放到esi
- cld //方向标志位,为以下俩条指令做准备
- movsd //复制原API入口前4个字节到OldCode数组
- movsb //复制原API入口第5个字节到OldCode数组
- }
- }
- void writenew()
- {
- //获取MyMessageBoxW的相对地址,为Jmp做准备
- //int nAddr= UserFunAddr – SysFunAddr - (我们定制的这条指令的大小);
- //Jmp nAddr;
- //(我们定制的这条指令的大小), 这里是5,5个字节嘛
- //填充完毕,现在NewCode[]里的指令相当于Jmp MyMessageBoxW
- //既然已经获取到了Jmp MyMessageBoxW
- //现在该是将Jmp MyMessageBoxW写入原API入口前5个字节的时候了
- //知道为什么是5个字节吗?
- //Jmp指令相当于0xe9,占一个字节的内存空间
- //MyMessageBoxW是一个地址,其实是一个整数,占4个字节的内存空间
- //int n=0x123; n占4个字节和MyMessageBoxW占4个字节是一样的
- //1+4=5,知道为什么是5个字节了吧
- NewCode[0] = 0xe9;//实际上0xe9就相当于jmp指令
- _asm
- {
- lea eax, MyMessageBoxW //获取我们的MyMessageBoxW函数地址
- mov ebx, pfoldmsg //原系统API函数地址
- sub eax, ebx //int nAddr= UserFunAddr – SysFunAddr
- sub eax, 5 //nAddr=nAddr-5
- mov dword ptr[NewCode + 1], eax //将算出的地址nAddr保存到NewCode后面4个字节
- //注:一个函数地址占4个字节
- }
- }
- int main()
- {
-
- //有了保存原API函数地址的变量OldMsgBox和指向原API函数的远指针,我们就可以获取真实API的地址了
- //获取原API入口地址
- hmod = LoadLibrary(_T("User32.dll")); //载入DLL文件
- oldmsg = (MsgBoxW)GetProcAddress(hmod, "MessageBoxW"); //获得DLL文件中MESSAGEBOXW函数地址
- pfoldmsg = (FARPROC)oldmsg;
- dwPid = ::GetCurrentProcessId();
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);
- //poldmsg = (BYTE*)oldmsg ;
- writeold();
- writenew();
-
- HookOn();
- MessageBox(NULL, _T("获取原API入口地址出错"), _T("error!"), 0);
-
- }
复制代码
//这下面是我改成OpenProcess后的代码 会提示内存错误
- #include <stdio.h>
- #include <windows.h>
- #include <tchar.h>
- //以MSG定义为原型定义函数类型
- typedef int (WINAPI* MsgBoxW)(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
- typedef HANDLE (WINAPI *OpenPros)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
- HMODULE hmod = NULL;
- OpenPros oldmsg; //用于存放未修改过的MSG函数地址 注意这是指针型
- FARPROC pfoldmsg; //指向原函数的远指针
- BYTE OldCode[5];
- BYTE NewCode[5];
- DWORD dwPid = NULL;
- HANDLE hProcess = NULL;
- void HookOn()
- {
- DWORD dwTemp = 0;
- DWORD dwOldProtect;
- //修改API函数入口前5个字节为jmp xxxxxx
- VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
- WriteProcessMemory(hProcess, pfoldmsg, NewCode, 5, 0);
- VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);
- }
- void HookOff()
- {
- DWORD dwTemp = 0;
- DWORD dwOldProtect;
- //恢复API函数入口前5个字节
- VirtualProtectEx(hProcess, pfoldmsg, 5, PAGE_READWRITE, &dwOldProtect);
- WriteProcessMemory(hProcess, pfoldmsg, OldCode, 5, 0);
- VirtualProtectEx(hProcess, pfoldmsg, 5, dwOldProtect, &dwTemp);
- }
- HANDLE WINAPI MyOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
- {
- MessageBoxW(NULL, _T("哈哈,MessageBoxW被HOOK了"), L"OPENPROCESS", MB_OK);
- return 0;
- }
- int WINAPI MyMessageBoxW(HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
- {
-
- HookOff();//调用原函数之前,记得先恢复HOOK呀,不然是调用不到的
- //如果不恢复HOOK,就调用原函数,会造成死循环
- //毕竟调用的还是我们的函数,从而造成堆栈溢出,程序崩溃。
- int nRet = ::MessageBoxW(hwnd, _T("哈哈,MessageBoxW被HOOK了"), lpCaption, uType);
- HookOn();//调用完原函数后,记得继续开启HOOK,不然下次会HOOK不到。
- return nRet;;
-
- }
- void writeold()
- {
- //保存原API入口的前5个字节
- //保存的目的是为了恢复用的,毕竟我们HOOK了API后,还需要调用真实的API嘛,
- //如何保存一个函数入口的前5个字节呢?这里用到了汇编代码,至于不用汇编可以吗?我想是可以的。
- //有空时,我再试一下,不用汇编是否能保存一个API入口的前5个字节,这里就先用别人写的汇编代码吧,
- _asm
- {
- lea edi, OldCode ////获取OldCode数组的地址,放到edi
- mov esi, pfoldmsg //获取原API入口地址,放到esi
- cld //方向标志位,为以下俩条指令做准备
- movsd //复制原API入口前4个字节到OldCode数组
- movsb //复制原API入口第5个字节到OldCode数组
- }
- }
- void writenew()
- {
- //获取MyMessageBoxW的相对地址,为Jmp做准备
- //int nAddr= UserFunAddr – SysFunAddr - (我们定制的这条指令的大小);
- //Jmp nAddr;
- //(我们定制的这条指令的大小), 这里是5,5个字节嘛
- //填充完毕,现在NewCode[]里的指令相当于Jmp MyMessageBoxW
- //既然已经获取到了Jmp MyMessageBoxW
- //现在该是将Jmp MyMessageBoxW写入原API入口前5个字节的时候了
- //知道为什么是5个字节吗?
- //Jmp指令相当于0xe9,占一个字节的内存空间
- //MyMessageBoxW是一个地址,其实是一个整数,占4个字节的内存空间
- //int n=0x123; n占4个字节和MyMessageBoxW占4个字节是一样的
- //1+4=5,知道为什么是5个字节了吧
- NewCode[0] = 0xe9;//实际上0xe9就相当于jmp指令
- _asm
- {
- lea eax, MyOpenProcess //获取我们的MyMessageBoxW函数地址
- mov ebx, pfoldmsg //原系统API函数地址
- sub eax, ebx //int nAddr= UserFunAddr – SysFunAddr
- sub eax, 5 //nAddr=nAddr-5
- mov dword ptr[NewCode + 1], eax //将算出的地址nAddr保存到NewCode后面4个字节
- //注:一个函数地址占4个字节
- }
- }
- int main()
- {
-
- //有了保存原API函数地址的变量OldMsgBox和指向原API函数的远指针,我们就可以获取真实API的地址了
- //获取原API入口地址
- hmod = LoadLibrary(_T("Kernel32.dll")); //载入DLL文件
- oldmsg = (OpenPros)GetProcAddress(hmod, "OpenProcess"); //获得DLL文件中MESSAGEBOXW函数地址
- pfoldmsg = (FARPROC)oldmsg;
- dwPid = ::GetCurrentProcessId();
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);
-
- writeold();
- writenew();
-
- HookOn();
- MessageBox(NULL, _T("获取原API入口地址出错"), _T("error!"), 0);
-
- }
复制代码 |
|