Naar inhoud springen

Hooking (programmeren)

Uit Wikipedia, de vrije encyclopedie

Hooking is een reeks van technieken die gebruikt wordt bij programmeren. Bij deze technieken worden subroutines onderschept, bewerkt en doorgestuurd om een programma anders te laten werken. De code die de onderschepte subroutine verwerkt wordt simpelweg een 'hook' of een 'detour' genoemd.

Hooken wordt voor meerdere doelen gebruikt, waaronder debuggen en software uitbreidingen. Voorbeelden van software uitbreidingen zijn:

  • Benchmarking, waarbij de prestatie van bepaalde software gemonitord kan worden.
  • Toetsenbord of muis instructies onderscheppen voordat ze bij het betreffende programma aankomen.
  • Verschillende OS calls hooken waardoor men het gedrag van andere programma's kan monitoren of bewerken.

Verboden praktijken

[bewerken | brontekst bewerken]

Doordat programma's extern bewerkt kunnen worden via een hook worden hooks het vaakst gebruikt voor rootkits en het schrijven van hacks. Zo worden de meeste wallhacks geschreven door middel van een hook. Hierbij worden subroutines onderschept en bewerkt om de gebruiker andere beelden terug te sturen van bijvoorbeeld gekleurde tegenstanders of onzichtbare muren. Dit geeft een groot voordeel voor de gebruiker van de hook tegenover andere spelers en wordt daardoor vaak gezien als verboden.

API Hooken met de JMP instructie

[bewerken | brontekst bewerken]

Hooken kan worden gedaan door de eerste zes bytes van een bepaalde functie te veranderen met een JMP instructie naar de hook functie. De code wordt gecompileerd naar een DLL waarbij door middel van DLL-injectie de hook toegang heeft tot het geheugen van het andere programma. Door een back-up te maken van de originele zes bytes kan men ervoor zorgen dat de call naar de functie ongestoord verder loopt. In dit voorbeeld wordt de functie MessageBoxW van het Win32 API gehooked[1].

#include <windows.h>  
#define SIZE 6

 typedef int (WINAPI *pMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT);  // Messagebox prototype
 int WINAPI MyMessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT);            // Our detour

 void BeginRedirect(LPVOID);                                        
 pMessageBoxW pOrigMBAddress = NULL;                                // address of original
 BYTE oldBytes[SIZE] = {0};                                         // backup
 BYTE JMP[SIZE] = {0};                                              // 6 byte JMP instruction
 DWORD oldProtect, myProtect = PAGE_EXECUTE_READWRITE;

 INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)  
 {  
   switch(Reason)  
   {  
   case DLL_PROCESS_ATTACH:                                        // if attached
     pOrigMBAddress = (pMessageBoxW)                      
       GetProcAddress(GetModuleHandle("user32.dll"),               // get address of original 
               "MessageBoxW");  
     if(pOrigMBAddress != NULL)  
       BeginRedirect(MyMessageBoxW);                               // start detouring
     break;

   case DLL_PROCESS_DETACH:  
     memcpy(pOrigMBAddress, oldBytes, SIZE);                       // restore backup

   case DLL_THREAD_ATTACH:  
   case DLL_THREAD_DETACH:  
     break;  
   }  
   return TRUE;  
 }

 void BeginRedirect(LPVOID newFunction)  
 {  
   BYTE tempJMP[SIZE] = {0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3};         // 0xE9 = JMP 0x90 = NOP oxC3 = RET
   memcpy(JMP, tempJMP, SIZE);                                        // store jmp instruction to JMP
   DWORD JMPSize = ((DWORD)newFunction - (DWORD)pOrigMBAddress - 5);  // calculate jump distance
   VirtualProtect((LPVOID)pOrigMBAddress, SIZE,                       // assign read write protection
           PAGE_EXECUTE_READWRITE, &oldProtect);  
   memcpy(oldBytes, pOrigMBAddress, SIZE);                            // make backup
   memcpy(&JMP[1], &JMPSize, 4);                              // fill the nop's with the jump distance (JMP,distance(4bytes),RET)
   memcpy(pOrigMBAddress, JMP, SIZE);                                 // set jump instruction at the beginning of the original function
   VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);    // reset protection
 }

 int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uiType)  
 {  
   VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL);     // assign read write protection
   memcpy(pOrigMBAddress, oldBytes, SIZE);                            // restore backup
   int retValue = MessageBoxW(hWnd, lpText, lpCaption, uiType);       // get return value of original function
   memcpy(pOrigMBAddress, JMP, SIZE);                                 // set the jump instruction again
   VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);    // reset protection
   return retValue;                                                   // return original return value
 }
[bewerken | brontekst bewerken]