使用Detours对LoadLibraryExW进行HOOK屏蔽全局钩子
2012-11-12 19:21
453 查看
全局钩子都是做为DLL挂接注入进程,假如应用程序A.exe安装了WH_GETMESSAGE的全局钩子,钩子函数在B.dll中,那么当其它程序在调用GetMessage函数从自己的消息队列中取消息的时候,系统发现程序A安装了WH_GETMESSAGE的全局钩子,就会检查调用GetMessage的进程是否加载了B.dll,如果没有,就调用LoadLibrary进行加载,然后调用B.dll中的钩子过程。这样,钩子dll就会在所有调用GetMessage的进程中加载。
如果程序本身能够对LoadLibrary进行处理,就能够防范其他DLL模块的注入。这里未经任何判断直接返回NULL,有点武断,会影响系统效率。
PS:上面这句话说了等于白说,现在谁还用这种方式啊,都是自己解析加载,要不就走LDR那套,这些都是老的不能再老的东西了,不过这里作为基础学习,还是粘下代码作为备忘了。
以上是自己的DLL,如果需要对某个进程进行保护,只需要插入相关进程就好。当然相关进程如果不想麻烦,可以直接把HOOK过程写入程序代码。
经过调试发现,正常的加载dll函数调用都是从kernel32.dll中来的,而只有加载钩子过程是在user32.dll中进行的。可以对上面的函数进行修改,判断LoadLibrary函数的返回地址,如果是在user32.dll的地址空间,就认为是钩子dll的加载,直接返回NULL就可以了。
首先获取user32.dll的基地址
下面进行判断,如果来自user32.dll的调用直接进行返回。
PS:函数在调用的时候,先要把参数入栈,然后把返回地址入栈,esp指向的应该就是函数的返回地址了。但是为了返回函数时恢复原来的栈和在函数中方便引用传递的参数,编译器一般都会产生两条指令。
如果程序本身能够对LoadLibrary进行处理,就能够防范其他DLL模块的注入。这里未经任何判断直接返回NULL,有点武断,会影响系统效率。
PS:上面这句话说了等于白说,现在谁还用这种方式啊,都是自己解析加载,要不就走LDR那套,这些都是老的不能再老的东西了,不过这里作为基础学习,还是粘下代码作为备忘了。
#include <Windows.h> #include <stdio.h> #include "detours.h" #pragma comment(lib, "detours.lib") #pragma warning(disable : 4098) static HMODULE (WINAPI* _LoadLibraryExW)(LPCTSTR lpFileName,HANDLE hFile,DWORD dwFlags) = LoadLibraryExW; VOID OutputDebugStringExW(const wchar_t* szFormat, ...) { WCHAR Buffer[2048] = {0}; va_list argList; va_start(argList, szFormat); vswprintf(Buffer, sizeof(Buffer), szFormat, argList); va_end(argList); OutputDebugStringW(Buffer); } HMODULE WINAPI NEW_LoadLibraryExW(LPCTSTR lpFileName,HANDLE hFile,DWORD dwFlags) { OutputDebugStringExW(L"%s", lpFileName); return NULL; //return _LoadLibraryExW(lpFileName, hFile, dwFlags); } VOID Hook() { DetourRestoreAfterWith(); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)_LoadLibraryExW, NEW_LoadLibraryExW ) ; DetourTransactionCommit(); } VOID UnHook() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)_LoadLibraryExW, NEW_LoadLibraryExW ); DetourTransactionCommit(); } BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { Hook(); } else if (ul_reason_for_call == DLL_PROCESS_DETACH) { UnHook(); } return TRUE; }
以上是自己的DLL,如果需要对某个进程进行保护,只需要插入相关进程就好。当然相关进程如果不想麻烦,可以直接把HOOK过程写入程序代码。
经过调试发现,正常的加载dll函数调用都是从kernel32.dll中来的,而只有加载钩子过程是在user32.dll中进行的。可以对上面的函数进行修改,判断LoadLibrary函数的返回地址,如果是在user32.dll的地址空间,就认为是钩子dll的加载,直接返回NULL就可以了。
首先获取user32.dll的基地址
static DWORD m_dwUser32Low; //user32.dll 的加载基址 static DWORD m_dwUser32Hi; //user32.dll 的加载基址+ImageSize MODULEINFO user32ModInfo = {0}; //获取user32.dll的加载基址和映象大小 GetModuleInformation(GetCurrentProcess(), GetModuleHandle("user32.dll"), &user32ModInfo, sizeof(user32ModInfo)); m_dwUser32Low = (DWORD)user32ModInfo.lpBaseOfDll; m_dwUser32Hi = (DWORD)user32ModInfo.lpBaseOfDll+user32ModInfo.SizeOfImage;
下面进行判断,如果来自user32.dll的调用直接进行返回。
HMODULE WINAPI NEW_LoadLibraryExW(LPCTSTR lpFileName,HANDLE hFile,DWORD dwFlags) { //获取函数的返回地址 DWORD dwCaller; __asm push dword ptr [ebp+4] __asm pop dword ptr [dwCaller] //判断是否是从User32.dll调用的 if(dwCaller > m_dwUser32Low && dwCaller < m_dwUser32Hi) { OutputDebugStringExW(L"%s", lpFileName); return NULL; } return _LoadLibraryExW(lpFileName, hFile, dwFlags); }
PS:函数在调用的时候,先要把参数入栈,然后把返回地址入栈,esp指向的应该就是函数的返回地址了。但是为了返回函数时恢复原来的栈和在函数中方便引用传递的参数,编译器一般都会产生两条指令。
push ebp mov ebp,esp先把ebp入栈,把原来的esp保存在ebp寄存器中,这样,我们的返回地址就是[ebp+4],第一个参数是[ebp+8],第二个是[ebp+0xC]。
相关文章推荐
- C#使用全局钩子(hook),SetWindowsHookEx返回0、不回调的解决
- HOOK使用:全局键盘钩子
- C#使用全局钩子(hook),SetWindowsHookEx返回0、不回调的解决
- C#使用全局钩子(hook),SetWindowsHookEx返回0、不回调的解决
- 使用调试钩子屏蔽全局钩子
- 使用调试钩子屏蔽全局钩子
- 使用svn和hook(钩子)对puppet进行版本控制
- 使用调试钩子屏蔽全局钩子
- HOOK使用:全局键盘钩子
- 我的学习笔记之三——inline使用DLL进行全局HOOK(ring3_inline_dll_hook_Messagebox)
- HOOK使用:全局键盘钩子
- 我的学习笔记之四——inline使用DLL进行全局HOOK的改进(ring3_inline_dll_hook_Messagebox_临界区)
- 使用调试钩子屏蔽全局钩子
- C#使用全局钩子(hook),SetWindowsHookEx返回0、不回调的解决
- HOOK使用:全局键盘钩子
- 我的学习笔记之三——inline使用DLL进行全局HOOK(ring3_inline_dll_hook_Messagebox)
- C#使用全局钩子(hook),SetWindowsHookEx返回0、不回调的解决
- C#使用全局钩子(hook),SetWindowsHookEx返回0、不回调的解决
- 使用Indy解决Could not load SSL Library错误
- 全局钩子(hook鼠标键盘消息)