如果我有一个函数foo()
windows已在kernel32.dll中实现并且它总是返回true,我可以使用我的程序:“bar.exe”挂钩/绕过Windows函数并使其返回false改为所有流程?
因此,如果我的svchost调用foo()
,它将返回false而不是true。对于当前正在运行的所有其他进程,应该采取相同的操作。
如果是这样,怎么样?我想我正在寻找一个系统范围的钩子。
答案 0 :(得分:35)
看一下Detours,它非常适合这种东西。
对于系统范围的挂钩,请阅读MSDN中的this article。
首先,创建一个处理挂钩函数的DLL。下面的示例挂钩套接字发送和接收函数。
#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;
}
然后,创建一个程序将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;
}
这应该足以让你入门!
答案 1 :(得分:11)
EASYHOOK http://www.codeplex.com/easyhook
在简单性,灵活性和功能性方面支配所有上述技术。
之前在Hook processes上也没有讨论过。我已经阅读了这篇帖子的所有内容,并且绝对认可,EASYHOOK非常优秀。无论你使用C,C ++,CLR还是其他什么。
我会在codeplex主页上粘贴一点,以确保支付足够的图像。
我很高兴我的妓女仍然知道一些技巧比较让我保持身边。但是可以肯定的是,当你需要一个HOOK,99次100,EASYHOOK'r会让你更快。并且它得到了很好的维护。
答案 2 :(得分:8)
请提供您要挂钩的功能的更多详细信息!在这种情况下,有几种方法可以调用自己的代码,例如:
您可以构建一个假DLL,其名称与包含要挂钩的函数的DLL同名(并将其复制到foo.exe
文件夹中)。该库将公开与原始DLL完全相同的功能。除了要挂钩的函数之外,每个公开的函数都会绕过对原始DLL的调用。
您可以在运行时更改函数指针表,例如使用“kitchen”提到的(商业)Detour包。但是,您可以通过自己的方式轻松完成此类挂钩,请参阅this article了解具体方法。
您可以在foo.exe
中找到调用特定函数的位置,只需将调用该函数的汇编代码替换为“返回true
”的代码即可。基本上,你正在打补丁“foo.exe
”..
对于特定功能,Windows提供自动挂钩,例如用于键和鼠标事件。请检查函数SetWindowsHook。
答案 3 :(得分:3)
这在某种程度上取决于您想要定位的Windows版本。尽管如此,如果你在Pre-Vista上玩游戏,你可以简单地使用SetWindowsHookEx将DLL注入每个正在运行的进程中。然后,您的DLL需要使用Detours或类似函数挂钩相应的函数。
答案 4 :(得分:-1)
如果您在装配中编写钩子而不使用Detours(无论出于何种原因),那么您需要一些关于返回FALSE的关键信息:
你需要将EAX或RAX(取决于平台)设置为零作为你正在挂钩的功能的最后一件事。这将导致调用代码接收0作为返回值(假设它们返回int或指针类型值)。