Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikipediaThe Free Encyclopedia
Search

Hooking

From Wikipedia, the free encyclopedia
Techniques to alter an operating system
For other uses, seeHooking (disambiguation).
Not to be confused withHook-up.

Incomputer programming, the termhooking covers a range of techniques used to alter or augment the behaviour of anoperating system, ofapplications, or of other software components by interceptingfunction calls ormessages orevents passed betweensoftware components. Code that handles such intercepted function calls, events or messages is called ahook.

Hook methods are of particular importance in thetemplate method pattern where common code in anabstract class can be augmented by custom code in a subclass. In this case each hook method is defined in the abstract class with an empty implementation which then allows a different implementation to be supplied in each concrete subclass.

Hooking is used for many purposes, includingdebugging and extending functionality.Examples might include intercepting keyboard or mouse event messages before they reach an application, or intercepting operating system calls in order to monitor behavior or modify the function of an application or other component. It is also widely used in benchmarking programs, for exampleframe rate measuring in 3D games, where the output and input is done through hooking.

Hooking can also be used by malicious code. For example,rootkits, pieces of software that try to make themselves invisible by faking the output ofAPI calls that would otherwise reveal their existence, often use hooking techniques.

Methods

[edit]

Typically hooks are inserted while software is already running, but hooking is a tactic that can also be employed prior to the application being started. Both these techniques are described in greater detail below.

Source modification

[edit]

Hooking can be achieved by modifying the source of theexecutable orlibrary before an application is running, through techniques ofreverse engineering. This is typically used to intercept function calls to either monitor or replace them entirely.

For example, by using adisassembler, theentry point of afunction within amodule can be found. It can then be altered to instead dynamically load some other library module and then have it execute desired methods within that loaded library. If applicable, another related approach by which hooking can be achieved is by altering theimport table of an executable. This table can be modified to load any additional library modules as well as changing what external code is invoked when a function is called by the application.

An alternative method for achieving function hooking is by intercepting function calls through awrapper library. A wrapper is a version of a library that an application loads, with all the same functionality of the original library that it will replace. That is, all the functions that are accessible are essentially the same between the original and the replacement. This wrapper library can be designed to call any of the functionality from the original library, or replace it with an entirely new set of logic.

Runtime modification

[edit]

Operating systems and software may provide the means to easily insert event hooks atruntime. It is available provided that theprocess inserting the hook is granted enough permission to do so. Microsoft Windows for example, allows users to insert hooks that can be used to process or modify systemevents and application events fordialogs,scrollbars, andmenus as well as other items. It also allows a hook to insert, remove, process or modifykeyboard andmouse events. Linux provides another example where hooks can be used in a similar manner to process network events within thekernel throughNetFilter.

When such functionality is not provided, a special form of hooking employs intercepting the library function calls made by a process. Function hooking is implemented by changing the very first few code instructions of the target function to jump to an injected code. Alternatively on systems using theshared library concept, theinterrupt vector table or theimport descriptor table can be modified in memory. Essentially these tactics employ the same ideas as those of source modification, but instead altering instructions and structures located in the memory of a process once it is already running.

Sample code

[edit]

Virtual method table hooking

[edit]

Whenever a class defines/inherits avirtual function (or method), compilers add a hidden member variable to the class which points to avirtual method table (VMT or Vtable). Most compilers place the hidden VMT pointer at the first 4 bytes of every instance of the class. A VMT is basically an array ofpointers to all the virtual functions that instances of the class may call. At runtime these pointers are set to point to the right functions, because atcompile time, it is not yet known if the base function is to be called or if an overridden version of the function from a derived class is to be called (thereby allowing forpolymorphism). Therefore, virtual functions can be hooked by replacing the pointers to them within any VMT that they appear. The code below shows an example of a typical VMT hook in Microsoft Windows, written in C++.[1]

#include<iostream>#include"windows.h"usingnamespacestd;classVirtualClass{public:intnumber;virtualvoidVirtualFn1()//This is the virtual function that will be hooked.{cout<<"VirtualFn1 called "<<number++<<"\n\n";}};usingVirtualFn1_t=void(__thiscall*)(void*thisptr);VirtualFn1_torig_VirtualFn1;void__fastcallhkVirtualFn1(void*thisptr,intedx)//This is our hook function which we will cause the program to call instead of the original VirtualFn1 function after hooking is done.{cout<<"Hook function called"<<"\n";orig_VirtualFn1(thisptr);//Call the original function.}intmain(){VirtualClass*myClass=newVirtualClass();//Create a pointer to a dynamically allocated instance of VirtualClass.void**vTablePtr=*reinterpret_cast<void***>(myClass);//Find the address that points to the base of VirtualClass' VMT (which then points to VirtualFn1) and store it in vTablePtr.DWORDoldProtection;VirtualProtect(vTablePtr,4,PAGE_EXECUTE_READWRITE,&oldProtection);//Removes page protection at the start of the VMT so we can overwrite its first pointer.orig_VirtualFn1=reinterpret_cast<VirtualFn1_t>(*vTablePtr);//Stores the pointer to VirtualFn1 from the VMT in a global variable so that it can be accessed again later after its entry in the VMT has been//overwritten with our hook function.*vTablePtr=&hkVirtualFn1;//Overwrite the pointer to VirtualFn1 within the virtual table to a pointer to our hook function (hkVirtualFn1).VirtualProtect(vTablePtr,4,oldProtection,0);//Restore old page protection.myClass->VirtualFn1();//Call the virtual function from our class instance. Because it is now hooked, this will actually call our hook function (hkVirtualFn1).myClass->VirtualFn1();myClass->VirtualFn1();deletemyClass;return0;}

All virtual functions must be class member functions, and all (non-static) class member functions are called with the __thiscallcalling convention (unless the member function takes a variable number of arguments, in which case it is called with __cdecl). The __thiscall calling convention passes a pointer to the calling class instance (commonly referred to as a "this" pointer) via the ECX register (on the x86 architecture). Therefore, in order for a hook function to properly intercept the "this" pointer that is passed and take it as an argument, it must look into the ECX register. In the above example, this is done by setting the hook function (hkVirtualFn1) to use the __fastcall calling convention, which causes the hook function to look into the ECX register for one of its arguments.

Also note that, in the above example, the hook function (hkVirtualFn1) is not a member function itself so it cannot use the __thiscall calling convention. __fastcall has to be used instead because it is the only other calling convention that looks into the ECX register for an argument.

C# keyboard event hook

[edit]

The following example will hook into keyboard events in Microsoft Windows using theMicrosoft .NET Framework.

usingSystem.Runtime.InteropServices;namespaceHooks;publicclassKeyHook{/* Member variables */protectedstaticintHook;protectedstaticLowLevelKeyboardDelegateDelegate;protectedstaticreadonlyobjectLock=newobject();protectedstaticboolIsRegistered=false;/* DLL imports */[DllImport("user32")]privatestaticexternintSetWindowsHookEx(intidHook,LowLevelKeyboardDelegatelpfn,inthmod,intdwThreadId);[DllImport("user32")]privatestaticexternintCallNextHookEx(inthHook,intnCode,intwParam,KBDLLHOOKSTRUCTlParam);[DllImport("user32")]privatestaticexternintUnhookWindowsHookEx(inthHook);/* Types & constants */protecteddelegateintLowLevelKeyboardDelegate(intnCode,intwParam,refKBDLLHOOKSTRUCTlParam);privateconstintHC_ACTION=0;privateconstintWM_KEYDOWN=0x0100;privateconstintWM_KEYUP=0x0101;privateconstintWH_KEYBOARD_LL=13;[StructLayout(LayoutKind.Sequential)]publicstructKBDLLHOOKSTRUCT{publicintvkCode;publicintscanCode;publicintflags;publicinttime;publicintdwExtraInfo;}/* Methods */staticprivateintLowLevelKeyboardHandler(intnCode,intwParam,refKBDLLHOOKSTRUCTlParam){if(nCode==HC_ACTION){if(wParam==WM_KEYDOWN)System.Console.Out.WriteLine("Key Down: "+lParam.vkCode);elseif(wParam==WM_KEYUP)System.Console.Out.WriteLine("Key Up: "+lParam.vkCode);}returnCallNextHookEx(Hook,nCode,wParam,lParam);}publicstaticboolRegisterHook(){lock(Lock){if(IsRegistered)returntrue;Delegate=LowLevelKeyboardHandler;Hook=SetWindowsHookEx(WH_KEYBOARD_LL,Delegate,Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]).ToInt32(),0);if(Hook!=0)returnIsRegistered=true;Delegate=null;returnfalse;}}publicstaticboolUnregisterHook(){lock(Lock){returnIsRegistered=(UnhookWindowsHookEx(Hook)!=0);}}}

API/function hooking/interception using JMP instruction aka splicing

[edit]

The following source code is an example of an API/function hooking method which hooks by overwriting the first six bytes of a destinationfunction with aJMP instruction to a new function. The code is compiled into aDLL file then loaded into the target process using any method ofDLL injection. Using a backup of the original function one might then restore the first six bytes again so the call will not be interrupted. In this example thewin32 API function MessageBoxW is hooked.[2]

/* This idea is based on chrom-lib approach, Distributed under GNU LGPL License. Source chrom-lib: https://github.com/linuxexp/chrom-lib Copyright (C) 2011  Raja Jamwal*/#include<windows.h>#define SIZE 6typedefint(WINAPI*pMessageBoxW)(HWND,LPCWSTR,LPCWSTR,UINT);// Messagebox prototypeintWINAPIMyMessageBoxW(HWND,LPCWSTR,LPCWSTR,UINT);// Our detourvoidBeginRedirect(LPVOID);pMessageBoxWpOrigMBAddress=NULL;// address of originalBYTEoldBytes[SIZE]={0};// backupBYTEJMP[SIZE]={0};// 6 byte JMP instructionDWORDoldProtect,myProtect=PAGE_EXECUTE_READWRITE;INTAPIENTRYDllMain(HMODULEhDLL,DWORDReason,LPVOIDReserved){switch(Reason){caseDLL_PROCESS_ATTACH:// if attachedpOrigMBAddress=(pMessageBoxW)GetProcAddress(GetModuleHandleA("user32.dll"),// get address of original"MessageBoxW");if(pOrigMBAddress!=NULL)BeginRedirect(MyMessageBoxW);// start detouringbreak;caseDLL_PROCESS_DETACH:VirtualProtect((LPVOID)pOrigMBAddress,SIZE,myProtect,&oldProtect);// assign read write protectionmemcpy(pOrigMBAddress,oldBytes,SIZE);// restore backupVirtualProtect((LPVOID)pOrigMBAddress,SIZE,oldProtect,&myProtect);// reset protectioncaseDLL_THREAD_ATTACH:caseDLL_THREAD_DETACH:break;}returnTRUE;}voidBeginRedirect(LPVOIDnewFunction){BYTEtempJMP[SIZE]={0xE9,0x90,0x90,0x90,0x90,0xC3};// 0xE9 = JMP 0x90 = NOP 0xC3 = RETmemcpy(JMP,tempJMP,SIZE);// store jmp instruction to JMPDWORDJMPSize=((DWORD)newFunction-(DWORD)pOrigMBAddress-5);// calculate jump distanceVirtualProtect((LPVOID)pOrigMBAddress,SIZE,// assign read write protectionPAGE_EXECUTE_READWRITE,&oldProtect);memcpy(oldBytes,pOrigMBAddress,SIZE);// make backupmemcpy(&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 functionVirtualProtect((LPVOID)pOrigMBAddress,SIZE,oldProtect,&myProtect);// reset protection}intWINAPIMyMessageBoxW(HWNDhWnd,LPCWSTRlpText,LPCWSTRlpCaption,UINTuiType){VirtualProtect((LPVOID)pOrigMBAddress,SIZE,myProtect,&oldProtect);// assign read write protectionmemcpy(pOrigMBAddress,oldBytes,SIZE);// restore backupintretValue=MessageBoxW(hWnd,lpText,lpCaption,uiType);// get return value of original functionmemcpy(pOrigMBAddress,JMP,SIZE);// set the jump instruction againVirtualProtect((LPVOID)pOrigMBAddress,SIZE,oldProtect,&myProtect);// reset protectionreturnretValue;// return original return value}

Netfilter hook

[edit]

This example shows how to use hooking to alternetwork traffic in the Linux kernel usingNetfilter.

#include<linux/module.h>#include<linux/kernel.h>#include<linux/skbuff.h>#include<linux/ip.h>#include<linux/tcp.h>#include<linux/in.h>#include<linux/netfilter.h>#include<linux/netfilter_ipv4.h>/* Port we want to drop packets on */staticconstuint16_tport=25;/* This is the hook function itself */staticunsignedinthook_func(unsignedinthooknum,structsk_buff**pskb,conststructnet_device*in,conststructnet_device*out,int(*okfn)(structsk_buff*)){structiphdr*iph=ip_hdr(*pskb);structtcphdr*tcph,tcpbuf;if(iph->protocol!=IPPROTO_TCP)returnNF_ACCEPT;tcph=skb_header_pointer(*pskb,ip_hdrlen(*pskb),sizeof(*tcph),&tcpbuf);if(tcph==NULL)returnNF_ACCEPT;return(tcph->dest==port)?NF_DROP:NF_ACCEPT;}/* Used to register our hook function */staticstructnf_hook_opsnfho={.hook=hook_func,.hooknum=NF_IP_PRE_ROUTING,.pf=NFPROTO_IPV4,.priority=NF_IP_PRI_FIRST,};static__initintmy_init(void){returnnf_register_hook(&nfho);}static__exitvoidmy_exit(void){nf_unregister_hook(&nfho);}module_init(my_init);module_exit(my_exit);

Internal IAT hooking

[edit]

The following code demonstrates how to hook functions that are imported from another module.This can be used to hook functions in a different process from the calling process. For this the code must be compiled into aDLL file then loaded into the target process using any method ofDLL injection.The advantage of this method is that it is less detectable byantivirus software and/oranti-cheat software, one might make this into an external hook that doesn't make use of any malicious calls. ThePortable Executable header contains theImport Address Table (IAT), which can be manipulated as shown in the source below. The source below runs under Microsoft Windows.

#include<windows.h>typedefint(__stdcall*pMessageBoxA)(HWNDhWnd,LPCSTRlpText,LPCSTRlpCaption,UINTuType);//This is the 'type' of the MessageBoxA call.pMessageBoxARealMessageBoxA;//This will store a pointer to the original function.voidDetourIATptr(constchar*function,void*newfunction,HMODULEmodule);int__stdcallNewMessageBoxA(HWNDhWnd,LPCSTRlpText,LPCSTRlpCaption,UINTuType){//Our fake functionprintf("The String Sent to MessageBoxA Was : %s\n",lpText);returnRealMessageBoxA(hWnd,lpText,lpCaption,uType);//Call the real function}intmain(intargc,CHAR*argv[]){DetourIATptr("MessageBoxA",(void*)NewMessageBoxA,0);//Hook the functionMessageBoxA(NULL,"Just A MessageBox","Just A MessageBox",0);//Call the function -- this will invoke our fake hook.return0;}void**IATfind(constchar*function,HMODULEmodule){//Find the IAT (Import Address Table) entry specific to the given function.intip=0;if(module==0)module=GetModuleHandle(0);PIMAGE_DOS_HEADERpImgDosHeaders=(PIMAGE_DOS_HEADER)module;PIMAGE_NT_HEADERSpImgNTHeaders=(PIMAGE_NT_HEADERS)((LPBYTE)pImgDosHeaders+pImgDosHeaders->e_lfanew);PIMAGE_IMPORT_DESCRIPTORpImgImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)pImgDosHeaders+pImgNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);if(pImgDosHeaders->e_magic!=IMAGE_DOS_SIGNATURE)printf("libPE Error : e_magic is no valid DOS signature\n");for(IMAGE_IMPORT_DESCRIPTOR*iid=pImgImportDesc;iid->Name!=NULL;iid++){for(intfuncIdx=0;*(funcIdx+(LPVOID*)(iid->FirstThunk+(SIZE_T)module))!=NULL;funcIdx++){char*modFuncName=(char*)(*(funcIdx+(SIZE_T*)(iid->OriginalFirstThunk+(SIZE_T)module))+(SIZE_T)module+2);constuintptr_tnModFuncName=(uintptr_t)modFuncName;boolisString=!(nModFuncName&(sizeof(nModFuncName)==4?0x80000000:0x8000000000000000));if(isString){if(!_stricmp(function,modFuncName))returnfuncIdx+(LPVOID*)(iid->FirstThunk+(SIZE_T)module);}}}return0;}voidDetourIATptr(constchar*function,void*newfunction,HMODULEmodule){void**funcptr=IATfind(function,module);if(*funcptr==newfunction)return;DWORDoldrights,newrights=PAGE_READWRITE;//Update the protection to READWRITEVirtualProtect(funcptr,sizeof(LPVOID),newrights,&oldrights);RealMessageBoxA=(pMessageBoxA)*funcptr;//Some compilers require the cast (like "MinGW"), not sure about MSVC though*funcptr=newfunction;//Restore the old memory protection flags.VirtualProtect(funcptr,sizeof(LPVOID),oldrights,&newrights);}

See also

[edit]

References

[edit]
  1. ^psyfl
  2. ^For more information, seehttp://ntvalk.blogspot.nl/2013/11/hooking-explained-detouring-library.html

External links

[edit]

Windows

[edit]
  • Information on Import Address Table function hooking.
  • Information from Microsoft on hooking
  • Information and various techniques regarding x86 hooking.
  • APISpy32 is an application used to hook win32 API.
  • Detours is a general purpose function hooking library created by Microsoft Research which works in C / C++.
  • winspy Three ways to inject code into another process.
  • HookTool SDK (ACF SDK) Provides a comprehensive overview on API hooking and code injection. A commercial product available too.
  • madCodeHook is a commercial x86 and x64 API hooking and DLL injection library for C++ and Delphi.
  • EasyHook is an open source hooking engine supporting x86 and x64 in Windows in both user and kernel land.
  • SpyStudio Application Trace SpyStudio is an Application tracer which hook calls, displaying the results in a structured way.
  • rohitab.com API Monitor is a freeware application that can hook and display 10,000+ Windows APIs and COM Interfaces in 32-bit and 64-bit applications and services.
  • Deviare API Hook Deviare is a freeware inter-process hook framework that can be used to intercept other processes' API calls and show full-parameter information or create API monitors.
  • WinAPIOverride WinAPIOverride is a freeware for non commercial use. It can hook win32 API, COM, OLE, ActiveX, .NET in 32-bit and 64-bit processes. It includes monitoring post analysis tools.
  • urmem C++11 cross-platform library (x86) for working with memory (hooks, patches, pointer's wrapper, signature scanner etc.)

Linux

[edit]
  • [1] A student research project that utilizes hooking.
  • [2] Functionality that allows a piece of software to observe and control the execution of another process.
  • [3] Use of LD_PRELOAD to hook shared library calls.

Emacs

[edit]
  • Emacs Hooks Hooks are an important mechanism for customization of Emacs. A hook is a Lisp variable which holds a list of functions, to be called on some well-defined occasion. (This is called running the hook.)

OS X and iOS

[edit]
  • Cydia Substrate is a framework for jailbroken iOS devices allowing developers to hook into any other framework or application.
  • harpoon is an OS X library for runtime function hooking.

In Depth API Hooking

[edit]
Retrieved from "https://en.wikipedia.org/w/index.php?title=Hooking&oldid=1269076588"
Categories:
Hidden categories:

[8]ページ先頭

©2009-2025 Movatter.jp