Vous êtes sur la page 1sur 5

WindowsHooks

Using WindowsHooks
2005 mcMike

2005 mcMike

This tutorial will teach how to use SetWindowHookEx() from DLL to hook into another apps message-queue. Tools needed: Visual Studio 6 (VC6++) DLL-injector with ability to Hook (example Winject 1.2 from MPC-forums) OllyDbg is helpful tool to check whats happening. OS: Windows XP SP2 (should work in others too) See also SimpleSEH - Detours, Api-hijacking, injecting, faking debug-registers

WindowHooks
From MSDN: 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.

HHOOK SetWindowsHookEx( int idHook, type of hook HOOKPROC lpfn, pointer to hook callback-function HINSTANCE hMod, handle to DLL containing callback (optional *) DWORD dwThreadId threadid of target-app to be hooked (optional *) ); *) typically specify only either one. ( For more information see MSDN->Hooks. )

What this means is that we provide a callback-function and tell the OS that when certain things happens call first Us. Lets start with single-app hook which is used to monitor events in some specific target and have the callback-function in same application which set the hook. This server-app needs to be running as long as hook is used.
Method-1. Install hook from other process // Set the hook and pass pointer for our callback function. // We provide dwThreadID which identifies the target-app

hMyHook = SetWindowsHookEx(WH_GETMESSAGE, MessageProc,NULL,dwThreadID); WH_GETMESSAGE = type of hook. See MSDN. MessageProc = pointer to callback function which we provide from our app dwThreadID = ThreadID of target process we are hooking
// hook callback

LRESULT CALLBACK MessageProc(int code,WPARAM wParam,LPARAM lParam) {


Explain this later .

To install system-wide hook we need to build separate DLL which exports the callback-function for hook. The hook can be installed from launcher-app or inside from DLL itself. The launcher is needed in both cases in order to get things initiated.

Page 1 of 5

WindowsHooks
Method-2. Install system-wide hook

2005 mcMike

HOOKPROC HINSTANCE HHOOK

pfnMessageProc; // pointer to hook-callback function in myhook.DLL hinstDLL; // INSTANCE handle for myhook.DLL hMyHook; // Hook Handle

// Selfload the DLL first

hinstDLL = LoadLibrary("d:\\dlls\\myhook.dll");
// Get address of hook callback

pfnMessageProc = (HOOKPROC)GetProcAddress(hinstDLL, "MessageProc");


// Set system-wide hook. We provide HINSTANCE of our hook.dll and // NULL for threadID to make it system-wide

hMyHook = SetWindowsHookEx(WH_GETMESSAGE, pfnMessageProc, hinstDLL, NULL); WH_GETMESSAGE = type of hook. See MSDN. pfnMessageProc = Pointer to hook-callback function in DLL Myhook.dll = the DLL we have built

After setting system-wide hook the OS will load our hook.dll automaticly to ALL processes that will be hooked. The loading doesnt happen instantly but when the hook-event for that app is occurred for the first time. In this tutorial we will use 3rd-type of hook which is mixed from both methods. It is actually not documented way to do things. Our hook callback will reside inside the DLL and is set also from inside the DLL BUT we still hook only single-target. The reason for this is because; we dont want to keep our launcher-app (which sets the hook) running after DLL is inside the target-process. There is a little catch we need to overcome. If we set the actual hook from launcher-app and close it the hook will vanish. We will first set pseudo-hook which is only used to get a callback in target-process thread-context. From there we will set the final hook which is not anymore dependant of launcher-app. So we first get the ThreadID of target-app (GetWindowThreadProcessId()) and then (self)load the DLL in launcher to get the address of function that will set the hook. We then call that function and let it set the pseudo-hook for target-app (ThreadID). After the first callback happens we remove the pseudo-hook and set the actual hook. This time the code runs in Target-apps Thread-context and the hook is not anymore depended of launcher app.
// This is the exported function which is called from launcher

int InstallRemoteHook(DWORD dwThreadID) {


// Store ThreadID to global/shared-variable

if(!g_dwThreadID) g_dwThreadID=dwThreadID;
// Try to install the hook

hInstallHook = SetWindowsHookEx(WH_CALLWNDPROC, InstallHookProc,hInstDLL, g_dwThreadID); return 0; }


// Set the final hook and remove installer pseudo-hook. // This is called when first hook-callback is received

LRESULT CALLBACK InstallHookProc(int code,WPARAM wParam,LPARAM lParam) {


// Remove the installer-pseudohook. It is not needed anymore once we got first callback

UnhookWindowsHookEx( hInstallHook );
// Set new final Hook

hMessageHook = SetWindowsHookEx(WH_GETMESSAGE, MessageProc,hInstDLL,g_dwThreadID); }

Obviously we could do this multiple other ways also. Inject DLL , hijack some API to have a callback and set hooks from there. But I wanted to present the hook-method for injecting since it might be handy in some cases. PLUS the injected DLL will have keyboard/mouse-event hook from the start. So we can set some keys to toggle things on/off in the hack.
Page 2 of 5

WindowsHooks

2005 mcMike

Lets cover briefly how to handle the hook-callback. The handler depends of the type of hook. The important thing is to CallNextHookEx() to call next hook in hook-chain. Its not required but highly recommended.
LRESULT CALLBACK MessageProc(int code,WPARAM wParam,LPARAM lParam) {
// If the OS passes <0 for code we should not handle the message. //So lets just pass it to next hook

if (code<0) return CallNextHookEx(hMessageHook, code, wParam, lParam);


// Build pointer to MSG-struct in lParam

MSG* lpMsg = (MSG*)lParam;


// Just for example Check for RightMouse....

if (lpMsg->message == WM_RBUTTONDOWN) MessageBox(NULL,"RMOUSE","SEH_example II",0); return CallNextHookEx(hMessageHook, code, wParam, lParam); }

Hooking with Winject


Winject 1.2 provides new inject-method which uses hooks. You can download it from MPCforums. Just select Target Process and DLL to Inject and choose Inject with Hook from Hook-menu. Winject will selfload the selected DLL and check that it exports: __declspec( dllexport ) int InstallRemoteHook(DWORD dwThreadID); It will then call that function which will force OS to load the DLL in target process and eventually install the hook.

Page 3 of 5

WindowsHooks
The CODE
// Tutorial for WindowsHooks (c) 2005 mcMike #define #include #include WIN32_LEAN_AND_MEAN <windows.h> <stdio.h>

2005 mcMike

// SetWindowHookEx() and our Function defines LRESULT CALLBACK MessageProc(int code,WPARAM wParam,LPARAM lParam); LRESULT CALLBACK InstallHookProc(int code,WPARAM wParam,LPARAM lParam); __declspec( dllexport ) int InstallRemoteHook(DWORD dwThreadID); HHOOK hMessageHook=NULL;

// Callback for actual hook // pseudohook for installing // export for launcher app

// global MessageHook handle. We don't share this since we keep it only // for instance that loads into target actually

// Global Shared data-section among all instance of this DLL #pragma data_seg(".HOOKDATA") HHOOK hInstallHook=NULL; // shared installerHook handle DWORD dwHookedThreadID=0; // threadID of targetProcess we hook into HMODULE hInstDLL=NULL; // modulehandle for our DLL int nError=0; // shared errorcode for return #pragma data_seg() #pragma comment(linker, "/SECTION:.HOOKDATA,RWS") // DLL entrypoint which OS-loader calls for us after loading BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(GetModuleHandle(NULL)); if (!hInstDLL) hInstDLL=(HMODULE)hModule; // Store handle to global/shared variable break; case DLL_PROCESS_DETACH: // Try to remove all hooks and handlers. if (hMessageHook) UnhookWindowsHookEx( hMessageHook ); if (hInstallHook) UnhookWindowsHookEx( hInstallHook ); break; } return true; } // Install the pseudo-Hook. This is called from launcher (winject) int InstallRemoteHook(DWORD dwThreadID) { // Store ThreadID to global/shared-variable if(!dwHookedThreadID) dwHookedThreadID=dwThreadID; // Try to install the hook hInstallHook = SetWindowsHookEx(WH_CALLWNDPROC, InstallHookProc,hInstDLL,dwHookedThreadID); if (!hInstallHook) return GetLastError(); return 0; } // Set the final hook and remove installer pseudo-hook. // This is called when first hook-callback is received LRESULT CALLBACK InstallHookProc(int code,WPARAM wParam,LPARAM lParam) { // Remove the installer-pseudohook. It is not needed anymore once we got first callback UnhookWindowsHookEx( hInstallHook ); hInstallHook =NULL; // Set new final Hook hMessageHook = SetWindowsHookEx(WH_GETMESSAGE, MessageProc,hInstDLL,dwHookedThreadID); if (!hMessageHook) nError=GetLastError(); // something went wrong. pass errorcode in shared-variable // Show message that all is now set and we're "standalone" now MessageBox(NULL,"Final Hook installed"," WindowsHoooks",0); return CallNextHookEx(NULL, code, wParam, lParam); } Page 4 of 5 // something went wrong. pass errorcode

// just to be sure

WindowsHooks
// MessageHook Callback. Called by OS to interrept messages in target-process // return 1 if you don't want to pass the keypress/mouse to game // otherwise return CallNextHookEx() to pass it forward LRESULT CALLBACK MessageProc(int code,WPARAM wParam,LPARAM lParam) { // Bailout if we should not handle this message if (code<0) return CallNextHookEx(hMessageHook, code, wParam, lParam); // Build pointer to MSG-struct in lParam MSG* lpMsg = (MSG*)lParam; // Just for example Check for RightMouse.... if (lpMsg->message == WM_RBUTTONDOWN) MessageBox(NULL,"RMOUSE","SEH_example II",0); // Check and handle keyboard messages..... if (lpMsg->message == WM_KEYDOWN) { switch (lpMsg->wParam) { case VK_HOME: MessageBox(NULL,"HOME !"," WindowsHoooks ",0); break; case VK_DELETE: MessageBox(NULL,"DEL !","WindowsHoooks",0); break; } } return CallNextHookEx(hMessageHook, code, wParam, lParam); }

2005 mcMike

Page 5 of 5

Vous aimerez peut-être aussi