我怎样才能挂钩在C / C + +的Windowsfunction?

如果我有一个函数foo() ,窗口已经在kernel32.dll中实现,它总是返回true,我可以有我的程序:“bar.exe”钩/绕道Windowsfunction,并使所有进程返回false?

所以,如果我的svchost,例如,调用foo() ,它将返回false而不是true。 对于当前正在运行的所有其他进程,也应该采取同样的行动

如果是这样,怎么样? 我想我正在寻找一个全系统的钩子什么的。

看看Detours吧 ,这对于这类东西来说是完美的。


对于全系统挂钩,请阅读MSDN上的这篇文章 。


首先,创build一个处理挂钩函数的DLL。 下面的这个例子钩住了套接字的发送和接收function。

 #include <windows.h> #include <detours.h> #pragma comment( lib, "Ws2_32.lib" ) #pragma comment( lib, "detours.lib" ) #pragma comment( lib, "detoured.lib" ) int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send; int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv; int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags ); int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ); int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) { // .. do stuff .. return Real_Send( s, buf, len, flags ); } int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) { // .. do stuff .. return Real_Recv( s, buf, len, flags ); } BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) { switch ( dwReason ) { case DLL_PROCESS_ATTACH: DetourTransactionBegin(); DetourUpdateThread( GetCurrentThread() ); DetourAttach( &(PVOID &)Real_Send, Mine_Send ); DetourAttach( &(PVOID &)Real_Recv, Mine_Recv ); DetourTransactionCommit(); break; case DLL_PROCESS_DETACH: DetourTransactionBegin(); DetourUpdateThread( GetCurrentThread() ); DetourDetach( &(PVOID &)Real_Send, Mine_Send ); DetourDetach( &(PVOID &)Real_Recv, Mine_Recv ); DetourTransactionCommit(); break; } return TRUE; } 

然后,创build一个程序将DLL注入到目标应用程序中。

 #include <cstdio> #include <windows.h> #include <tlhelp32.h> void EnableDebugPriv() { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tkp; OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ); LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid ); tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = luid; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL ); CloseHandle( hToken ); } int main( int, char *[] ) { PROCESSENTRY32 entry; entry.dwSize = sizeof( PROCESSENTRY32 ); HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL ); if ( Process32First( snapshot, &entry ) == TRUE ) { while ( Process32Next( snapshot, &entry ) == TRUE ) { if ( stricmp( entry.szExeFile, "target.exe" ) == 0 ) { EnableDebugPriv(); char dirPath[MAX_PATH]; char fullPath[MAX_PATH]; GetCurrentDirectory( MAX_PATH, dirPath ); sprintf_s( fullPath, MAX_PATH, "%s\\DllToInject.dll", dirPath ); HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, entry.th32ProcessID ); LPVOID libAddr = (LPVOID)GetProcAddress( GetModuleHandle( "kernel32.dll" ), "LoadLibraryA" ); LPVOID llParam = (LPVOID)VirtualAllocEx( hProcess, NULL, strlen( fullPath ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); WriteProcessMemory( hProcess, llParam, fullPath, strlen( fullPath ), NULL ); CreateRemoteThread( hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)libAddr, llParam, NULL, NULL ); CloseHandle( hProcess ); } } } CloseHandle( snapshot ); return 0; } 

这应该足以让你开始!

EASYHOOK http://www.codeplex.com/easyhook

统治的所有上述技术在简单,灵活性和function。

以前没有讨论Hook过程 。 我已经读过这个主题的所有叶子,并且绝对是合格的, EASYHOOK是非常优秀的。 无论你使用C,C ++,CLR,不pipe。

我会从codeplex主页上粘贴一下,以确保足够的omage被支付。

以下是一个不完整的function列表:

  1. 所谓的“线程死锁屏障”在钩住未知的API时将摆脱许多核心问题; 这项技术对于EasyHook来说是独一无二的
  2. 您可以为非托pipeAPI编写托pipe的钩子处理程序
  3. 您可以使用所有便利的托pipe代码提供,例如NET Remoting,WPF和WCF
  4. 一个logging,纯粹的非托pipe挂钩API
  5. 支持32位和64位内核模式挂钩(也可以查看我的PatchGuard 3旁路驱动程序,可以在发布列表中find)
  6. 目标中没有资源或内存泄漏
  7. 实验隐形注射机制,不会引起目前任何AV软件的注意
  8. EasyHook32.dll和EasyHook64.dll是纯粹的非托pipe模块,可以在没有安装任何.NET框架的情况下使用!
  9. 所有的挂钩安装并自动以稳定的方式移除
  10. 通过使用完全未logging的API支持Windows Vista SP1 x64和Windows Server 2008 SP1 x64,仍然允许连接到任何terminal会话。
  11. 挂钩处理程序中的托pipe/非托pipe模块堆栈跟踪
  12. 在钩子处理程序中调用managed / unmanaged模块
  13. 在钩子处理程序中创build自定义堆栈跟踪
  14. 您将能够编写针对AnyCPU编译的注入库和宿主进程,这将允许您通过在所有情况下使用相同的程序集,将代码注入64位和32位进程的32位和64位进程。
  15. EasyHook支持64位目标的RIP相对寻址重定位。
  16. 不需要拆包/安装。
  17. Visual Studio Redistributable不是必需的。

我很高兴,我的妓女仍然知道一些比较的技巧,使我保持他们周围。 但是可以肯定的是,当你需要一个HOOK时,100次的99次,EASYHOOK'r会让你更快。 这是相当积极的维护。

请给出你想挂钩的function的更多细节! 在这种情况下,有几种方法可以调用自己的代码,例如:

  • 您可以使用与包含您要挂钩的函数的DLL相同的名称构build一个假DLL(并将其复制到foo.exe文件夹中)。 这个库将暴露与原始DLL完全相同的function。 每个暴露的函数都会绕过对原始DLL的调用,除了要挂钩的函数之外。

  • 您可以在运行期间更改函数指针表,例如使用“kitchen”提到的(商业)Detour软件包。 但是,做这样的挂钩可以很容易地由你自己完成,看到这篇文章来学习如何。

  • 你可以find在foo.exe调用特定函数的foo.exe ,只需用“返回true ”的代码replace调用该函数的汇编代码即可。 基本上,你正在修补“ foo.exe ”..

  • 对于特定的function,Windows提供自动挂钩,例如用于按键和鼠标事件。 检查函数SetWindowsHook为此。

这在一定程度上取决于您想要定位的Windows版本。 尽pipe如此,如果你在Pre-Vista上玩,你可以简单地使用SetWindowsHookEx来将你的DLL注入到每个正在运行的进程中。 然后您的DLL需要使用Detours或类似的钩子适当的function。

如果你在汇编中编写你的钩子而不使用Detours(无论出于何种原因),那么你需要一些关于returing FALSE的关键信息:

  • Win32,将EAX设置为0
  • Win64,将RAX设置为0

您需要将EAX或RAX(取决于平台)设置为零,作为您正在挂接的函数的最后一件事情。 这将导致调用代码接收0作为返回值(假设它们返回一个int或指针types值)。