.
1.简介
在代码hook中,由于频繁的进行hook和unhook,而且又加上多线程的一些不可靠的因素,会使程序执行效率降低而且可能会导致错误,即
多线程对其hook和unhook导致不稳定的可能性增加, 因此需要找一种不需要频繁进行hook和unhook的方法.
而windows的一些API提供了一种很好的优化方式. 即API代码以mov edi,edi 指令开头,这条执行占了2个字节,而且2个API之间
有5个nop指令,这些nop在一个ret和一个API基址之间,不会被执行到.所以前5个字节可以放下一个远跳转指令,开头2个字节可以存放
一个短跳转指令,通过短跳转指令跳到远跳转指令基址,即可实现hook,然后在hook函数中直接跳转或call到API基址+2的地方执行API.
2.以hook explorer.exe进程的CreateProcessW函数为例, 对于路径中存在qq(不区分大小写)的的进程不予执行的功能的实现
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" #include <Windows.h> #include <wchar.h> #include <string.h> #define FuncName "CreateProcessW" #define DllName "kernel32.dll" typedef BOOL (WINAPI *lpCreateProcessW) ( __in_opt LPCWSTR lpApplicationName, __inout_opt LPWSTR lpCommandLine, __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles, __in DWORD dwCreationFlags, __in_opt LPVOID lpEnvironment, __in_opt LPCWSTR lpCurrentDirectory, __in LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation ); BOOL MyCreateProcessW ( __in_opt LPCWSTR lpApplicationName, __inout_opt LPWSTR lpCommandLine, __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles, __in DWORD dwCreationFlags, __in_opt LPVOID lpEnvironment, __in_opt LPCWSTR lpCurrentDirectory, __in LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation ); DWORD hook(DWORD funcBase, DWORD fakeBase); DWORD unhook(DWORD funcBase, DWORD fakeBase); BYTE orgCode[7] = { 0 }; BYTE fakeCode[7] = { 0xe9 ,0,0,0,0, 0xeb,0xf9 };//短跳转部分直接硬编码 DWORD functionBase; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { DWORD funcBase = (DWORD)GetProcAddress(GetModuleHandleA(DllName), FuncName); DWORD fakeBase = (DWORD)MyCreateProcessW; functionBase = funcBase + 2; //越过mov edi,edi 或者短跳转并不影响执行 switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: hook(funcBase, fakeBase); break; case DLL_PROCESS_DETACH: unhook(funcBase, fakeBase); break; } return TRUE; } DWORD hook(DWORD funcBase, DWORD fakeBase) { if (*(BYTE*)funcBase==0xeb) { return 0; } DWORD page; DWORD opcode; VirtualProtect((LPVOID)(funcBase - 5), 7, PAGE_EXECUTE_READWRITE, &page); memcpy(orgCode , (LPVOID)(funcBase - 5), 7); opcode = fakeBase - funcBase;//fakeBase - (funcBase - 5) - 5=fakeBase - funcBase memcpy(fakeCode + 1, &opcode, 4); memcpy((LPVOID)(funcBase - 5), fakeCode, 7); VirtualProtect((LPVOID)(funcBase - 5), 7, page, &page); return 1; } DWORD unhook(DWORD funcBase, DWORD fakeBase) { if (*(BYTE*)funcBase != 0xeb) { return 0; } DWORD page; VirtualProtect((LPVOID)(funcBase - 5), 7, PAGE_EXECUTE_READWRITE, &page); memcpy((LPVOID)(funcBase - 5), orgCode, 7); VirtualProtect((LPVOID)(funcBase - 5), 7, page, &page); return 1; } BOOL MyCreateProcessW ( __in_opt LPCWSTR lpApplicationName, __inout_opt LPWSTR lpCommandLine, __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles, __in DWORD dwCreationFlags, __in_opt LPVOID lpEnvironment, __in_opt LPCWSTR lpCurrentDirectory, __in LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation ) { WCHAR exeName[MAX_PATH] = { 0 }; if (wcsstr(lpApplicationName,L"qq")|| wcsstr(lpApplicationName, L"QQ") || wcsstr(lpApplicationName, L"Qq") || wcsstr(lpApplicationName, L"qQ")) { wsprintfW(exeName, L"%s没交保护费,禁止启动", lpApplicationName); MessageBoxW(0, exeName, L"温馨提示", 0); return 0; } else { wsprintfW(exeName, L"%s交了保护费,予以启动", lpApplicationName); MessageBoxW(0, exeName, L"温馨提示", 0); return ((lpCreateProcessW)functionBase)( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); } }