If I have a function foo()
that windows has implemented in kernel32.dll and it always returns true, can I have my program: "bar.exe" hook/detour that Windows function and make it return false for all processes instead?
So, if my svchost, for example, calls foo()
, it will return false instead of true. The same action should be expected for all other processes currently running.
If so, how? I guess I'm looking for a system-wide hook or something.
A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure.
Windows API hooking is a process allowing to intercept API function calls. This gives you the control over the way operating system or a piece of software behaves.
The WH_KEYBOARD_LL hook enables you to monitor keyboard input events about to be posted in a thread input queue. For more information, see the LowLevelKeyboardProc callback function.
Normally when you "hook" into the DLL, you actually put your function in front of the one in the DLL that gets called, so your function gets called instead. You then capture whatever you want, call the other function, capture its return values and whatever else, then return to the original caller.
Take a look at Detours, it's perfect for this sort of stuff.
For system-wide hooking, read this article from MSDN.
First, create a DLL which handles hooking the functions. This example below hooks the socket send and receive functions.
#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; }
Then, create a program to inject the DLL into the target application.
#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; }
This should be more than enough to get you started!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With