Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I hook Windows functions in C/C++?

Tags:

c++

c

windows

hook

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.

like image 237
Clark Gaebel Avatar asked May 17 '09 00:05

Clark Gaebel


People also ask

What are window hooks?

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.

What is API hooking?

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.

What is Wh_keyboard_ll?

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.

What is hook C++?

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.


1 Answers

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!

like image 132
xian Avatar answered Sep 28 '22 15:09

xian