今天我使用的代码钩取的技术手段钩取了loadLibaryA,但是却报错了,查看汇编代码,发现在调用loadLibaryA后还会调用一个检查堆栈平衡的函数,这个是编译器在debug版本自动加的。
详细说明请看:
本次案例代码为钩取函数的代码,编译环境为:vs2010,字符集为unicode,运行环境windos7 32位,如下图所示
#include <stdio.h> #include <Windows.h> #include <tchar.h> #include <locale.h> /** 名称:hookByCode 功能: 在某个API下钩子 参数:PVOID APIAddr 被钩取的函数地址 PVOID hookProc 钩子函数 PBYTE pBuf 保存前五个字节的缓冲区 返回值:PBYTE 返回被下钩子的API的前5个字节 用于脱钩 **/ VOID hookByCode(PVOID APIAddr,PVOID hookProc,PBYTE pBuf){ memcpy(pBuf,APIAddr,5); //计算跳转距离 // 若已经被钩取则返回FALSE if( ((PBYTE)APIAddr)[0] == 0xE9 ) return ; //目标位置 DWORD desPos = (DWORD)hookProc; //源位置 DWORD srcPos = (DWORD)APIAddr+5; DWORD jmpDistance = desPos-srcPos; //取得可写权限 DWORD lpflOldProtect; VirtualProtect(APIAddr,5,PAGE_READWRITE,&lpflOldProtect); //设置跳转语句 memcpy((byte *)APIAddr+1,&jmpDistance,4); *(BYTE *)APIAddr = 0xE9; VirtualProtect(APIAddr,5,lpflOldProtect,&lpflOldProtect); } HMODULE myload(LPCSTR lpLibFileName){ printf("惊喜吗!!!"); return 0; } void main(){ /*BYTE bytes1[4] = {0x00,0x10,0x40,0x00}; BYTE bytes2[4] = {0x05,0x20,0x40,0x00}; DWORD b1 = *(DWORD *)bytes1; DWORD b2 = *(DWORD *)bytes2; DWORD result = b1-b2; printf("%X-%X=%X",b1,b2,result);*/ //loadW("user32.dll"); //printf("0x%X",(int)p); BYTE pBuf[5]={0,}; //hookByCode("kernel32.dll","LoadLibraryA",(FARPROC)myload,pBuf); //unhook_by_code("kernel32.dll","LoadLibraryA",pBuf); // HMODULE (*loadW)(LPCSTR); //loadW = (HMODULE (*)(LPCSTR))getAPIAddress(L"kernel32.dll",L"LoadLibraryA"); hookByCode(LoadLibraryA,myload,pBuf); //unhookByCode(LoadLibraryA,pBuf); system("pause"); myload("a"); LoadLibraryA("user32.dll"); printf("12"); system("pause"); }
debug版本,的汇编代码,如下图所示
红圈的是LoadLibrary的汇编代码,而蓝圈的是检查堆栈平衡,就是因为它我钩取Loadlibrary后才会报错,效果图如下
release版本,的汇编代码,如下图所示
只剩下红圈里LoadLibrary的汇编代码,而蓝圈的检查代码消失了,果然不报错了,效果图如下