fbpx
维基百科

钩子编程

钩子编程(hooking),也称作“挂钩”,是计算机程序设计术语,指通过拦截软件模块间的函数调用、消息传递、事件传递来修改或扩展操作系统、应用程序或其他软件组件的行为的各种技术。处理被拦截的函数调用、事件、消息的代码,被称为钩子(hook)。

钩子编程有多种用途,如调试、扩展功能。例如在键盘或鼠标事件到达应用程序之前拦截这些事件;拦截应用程序或其他模块的操作系统调用以监督行为、修改功能。也广泛用于benchmarking程序,如度量3D游戏的帧率

钩子编程也被用于恶意代码,如rootkit是各种通过假扮系统API调用输出来隐藏自身进程的可见性的工具与技术;游戏外挂是另一类例子。

方法

物理修改

在应用程序执行之前,物理修改可执行程序,这典型通过找到函数调用入口点,修改入口点使之在函数被执行前先执行其他的代码。另一种挂钩的方法是修改可执行程序的输入表(import table)。还有一种挂钩方法是采用包装库,使得应用程序不需修改即可调用该包装库完成其功能,而在包装库中插入钩子然后再调用原有的库。

运行时修改

操作系统与软件可提供方法,在运行时插入事件钩子。Microsoft Windows允许插入钩子以处理或修改对话框、滚动条、菜单等的系统事件、应用程序事件;插入、删除、处理或修改键盘鼠标事件。Linux允许类似的钩子通过NetFilter以处理网络事件。

如果没有上述机制或权限,也可拦截进程的库函数调用,在函数调用开始处注入代码。这可通过修改内存中的进程的中断向量表英语Interrupt vector table输入表(import table)实现。

示例代码

虚函数表挂钩

C++使用虚函数,因此可在运行时直接修改虚函数表的内容来挂钩。 Window上很多软件库以COM方式提供的(如DirectX), 所以有需求拦截COM调用的COM Hook。COM里的接口是C++虚表的形式提供的,所以COM的Hook其实就是虚表(vtable)的Hook。ATL就是用接口替代的方式来调试和记录COM接口引用计数的次数

class VirtualTable { // example class   public:   virtual void VirtualFunction01( ticket );  }; void VirtualTable::VirtualFunction01( ticket ) {   printf("VirtualFunction01 called");  } typedef void ( __thiscall* VirtualFunction01_t )( ticket* thisptr );  VirtualFunction01_t g_org_VirtualFunction01;  //our detour function  void __fastcall hk_VirtualFunction01( ticket* thisptr, int edx ) {   printf("Custom function called");   //call the original function   g_org_VirtualFunction01(thisptr);  }  int _tmain(int argc, _TCHAR* argv[]) {  DWORD oldProtection;  VirtualTable* myTable = new VirtualTable();   void** base = *(void***)myTable;  VirtualProtect( &base[0], 4, PAGE_EXECUTE_READWRITE, &oldProtection );   //save the original function   g_org_VirtualFunction01 = (VirtualFunction01_t)base[0];   //overwrite   base[0] = &hk_VirtualFunction01;   VirtualProtect( &base[0], 4, oldProtection, 0 );  //call the virtual function (now hooked) from our class instance   myTable->VirtualFunction01();  return 0;  } 

C#键盘事件钩子

using System.Runtime.InteropServices; namespace Hooks {  public class KeyHook  {  /* Member variables */  protected static int Hook;  protected static LowLevelKeyboardDelegate Delegate;  protected static readonly object Lock = new object();  protected static bool IsRegistered = false;  /* DLL imports */  [DllImport("user32")]  private static extern int SetWindowsHookEx(int idHook, LowLevelKeyboardDelegate lpfn,  int hmod, int dwThreadId);  [DllImport("user32")]  private static extern int CallNextHookEx(int hHook, int nCode, int wParam, KBDLLHOOKSTRUCT lParam);  [DllImport("user32")]  private static extern int UnhookWindowsHookEx(int hHook);  /* Types & constants */  protected delegate int LowLevelKeyboardDelegate(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);  private const int HC_ACTION = 0;  private const int WM_KEYDOWN = 0x0100;  private const int WM_KEYUP = 0x0101;  private const int WH_KEYBOARD_LL = 13;  [StructLayout(LayoutKind.Sequential)]  public struct KBDLLHOOKSTRUCT  {  public int vkCode;  public int scanCode;  public int flags;  public int time;  public int dwExtraInfo;  }  /* Methods */  private static int LowLevelKeyboardHandler(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam)  {  if (nCode == HC_ACTION)  {  if (wParam == WM_KEYDOWN)  System.Console.Out.WriteLine("Key Down: " + lParam.vkCode);  else if (wParam == WM_KEYUP)  System.Console.Out.WriteLine("Key Up: " + lParam.vkCode);  }  return CallNextHookEx(Hook, nCode, wParam, lParam);  }    public static bool RegisterHook()  {  lock (Lock)  {  if (IsRegistered)  return true;  Delegate = LowLevelKeyboardHandler;  Hook = SetWindowsHookEx(  WH_KEYBOARD_LL, Delegate,  Marshal.GetHINSTANCE(  System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]  ).ToInt32(), 0  );  if (Hook != 0)  return IsRegistered = true;  Delegate = null;  return false;  }  }  public static bool UnregisterHook()  {  lock (Lock)  {  return IsRegistered = (UnhookWindowsHookEx(Hook) != 0);  }  }  } } 

使用跳转指令的API/函数钩子拦截

下述例子使用JMP英语JMP (x86 instruction)指令,修改windows API中的MessageBoxW函数的前6个字节执行其他代码。这段代码编译为DLL文件,采用DLL注入技术让应用程序使用。[1]微软提供了封装好的Detours库用于此目的。

/*  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 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 0xC3 = 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  } 

Netfilter钩子

使用Netfilter钩子修改Linux内核的网络交通。

#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 */ static const uint16_t port = 25; /* This is the hook function itself */ static unsigned int hook_func(unsigned int hooknum,  struct sk_buff **pskb,  const struct net_device *in,  const struct net_device *out,  int (*okfn)(struct sk_buff *)) {  struct iphdr *iph = ip_hdr(*pskb);  struct tcphdr *tcph, tcpbuf;  if (iph->protocol != IPPROTO_TCP)  return NF_ACCEPT;  tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), sizeof(*tcph), &tcpbuf);  if (tcph == NULL)  return NF_ACCEPT;  return (tcph->dest == port) ? NF_DROP : NF_ACCEPT; } /* Used to register our hook function */ static struct nf_hook_ops nfho = {  .hook = hook_func,  .hooknum = NF_IP_PRE_ROUTING,  .pf = NFPROTO_IPV4,  .priority = NF_IP_PRI_FIRST, }; static __init int my_init(void) {  return nf_register_hook(&nfho); } static __exit void my_exit(void) {  nf_unregister_hook(&nfho); } module_init(my_init); module_exit(my_exit); 

内部IAT钩子

下例展示通过修改可执行程序的输入地址表(IAT),把钩子函数替代原函数。

#include <windows.h> typedef int(__stdcall *pMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); //This is the 'type' of the MessageBoxA call. pMessageBoxA RealMessageBoxA; //This will store a pointer to the original function. void DetourIATptr(const char* function, void* newfunction, HMODULE module); int __stdcall NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) { //Our fake function  printf("The String Sent to MessageBoxA Was : %s\n", lpText);  return RealMessageBoxA(hWnd, lpText, lpCaption, uType); //Call the real function } int main(int argc, CHAR *argv[]) {  DetourIATptr("MessageBoxA",(void*)NewMessageBoxA,0); //Hook the function  MessageBoxA(NULL, "Just A MessageBox", "Just A MessageBox", 0); //Call the function -- this will invoke our fake hook.  return 0; } void **IATfind(const char *function, HMODULE module) { //Find the IAT (Import Address Table) entry specific to the given function.  int ip = 0;  if (module == 0)  module = GetModuleHandle(0);  PIMAGE_DOS_HEADER pImgDosHeaders = (PIMAGE_DOS_HEADER)module;  PIMAGE_NT_HEADERS pImgNTHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)pImgDosHeaders + pImgDosHeaders->e_lfanew);  PIMAGE_IMPORT_DESCRIPTOR pImgImportDesc = (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 (int funcIdx = 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);  const uintptr_t nModFuncName = (uintptr_t)modFuncName;  bool isString = !(nModFuncName & (sizeof(nModFuncName) == 4 ? 0x80000000 : 0x8000000000000000));  if (isString) {  if (!_stricmp(function, modFuncName))  return funcIdx + (LPVOID*)(iid->FirstThunk + (SIZE_T)module);  }  }  }  return 0; } void DetourIATptr(const char *function, void *newfunction, HMODULE module) {  void **funcptr = IATfind(function, module);  if (*funcptr == newfunction)  return;  DWORD oldrights, newrights = PAGE_READWRITE;  //Update the protection to READWRITE  VirtualProtect(funcptr, sizeof(LPVOID), newrights, &oldrights);  RealMessageBoxA = (pMessageBoxA)*funcptr; //Some compilers require the cast like "MinGW" not sure about MSVC  *funcptr = newfunction;  //Restore the old memory protection flags.  VirtualProtect(funcptr, sizeof(LPVOID), oldrights, &newrights); } 

Windows API提供的挂钩函数

  • SetWinEventHook:基本没有权限问题,也就是说这个API可以Hook到高权限程序的事件,同时支持进程内(WINEVENT_INCONTEXT)和进程外(WINEVENT_OUTOFCONTEXT)2种Hook方式,可以进程外的方式Hook到64位程序的事件。
  • SetWindowsHookEx:64位编程情形,32位DLL没法直接注入到64位的应用程序里面, 因为地址空间完全不一样。UAC打开的情况下低权限程序没法Hook高权限程序。对于64位问题,解决方法是提供2个DLL,分别可以Hook32和64位程序。对于权限问题,通过注册系统服务,由服务进程创建工作进程。因为Windows Vista开始有了Session隔离机制,服务进程运行在Session 0,用户程序运行在Session 1, Session 2等,如果直接在服务程序里干活,我们就只能在Session 0里工作。通过创建进程,可以在DuplicateTokenEx后将Token的SessionID设置成目标Session,并且在CreateProcessAsUser时指定目标WinStation和Desktop, 这样就获得了System权限,并且也可以和当前桌面进程交互。

参见

  • 回调函数
  • 委托 (编程)
  • 终止并驻留英语Terminate and Stay Resident#Using TSR
  • User exit英语User exit
  • WinAPIOverride32英语WinAPIOverride32

参考文献

  1. ^ For more information, see http://ntvalk.blogspot.nl/2013/11/hooking-explained-detouring-library.html (页面存档备份,存于互联网档案馆
  • Jonathan Daniel. Hooking explained: detouring library calls and vtable patching in Windows/Linux/MAC-OSX. 2013-11-27 [2014-01-01]. (原始内容于2018-05-03). 
  • Binh Nguyen. Hacking-Lexicon / Linux Dictionary V 0.16. 2004-08-16 [2008-02-23]. (原始内容于2021-03-22). Hook 
  • Author: Holy Father. Hooking Windows API - Technics of hooking API functions on Windows 1.1 english (PDF). 2002-06-10 [2008-02-21]. (原始内容 (PDF)于2020-10-28). 

外部链接

Windows

  • 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

  • A student research project that utilizes hooking.
  • 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

  • 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 与 iOS

  • 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.

Depth API Hooking

  • x86 API Hooking Demystified (页面存档备份,存于互联网档案馆) Article on various API Hooking methods, for the x86 architecture.

钩子编程, 本條目存在以下問題, 請協助改善本條目或在討論頁針對議題發表看法, 此條目包含過多行話或專業術語, 可能需要簡化或提出進一步解釋, 2018年3月5日, 請在討論頁中發表對於本議題的看法, 並移除或解釋本條目中的行話, 此條目包含指南或教學內容, 2018年3月5日, 請藉由移除或重寫指南段落來改善條目, 或在討論頁提出討論, 此條目包含過多僅特定讀者會感興趣的過度細節內容, 2018年3月5日, 請重新整理本條目以切合主題, 並移除与維基百科內容方針相悖的過度細節內容, 詳細信息請參見討論頁, hoo. 本條目存在以下問題 請協助改善本條目或在討論頁針對議題發表看法 此條目包含過多行話或專業術語 可能需要簡化或提出進一步解釋 2018年3月5日 請在討論頁中發表對於本議題的看法 並移除或解釋本條目中的行話 此條目包含指南或教學內容 2018年3月5日 請藉由移除或重寫指南段落來改善條目 或在討論頁提出討論 此條目包含過多僅特定讀者會感興趣的過度細節內容 2018年3月5日 請重新整理本條目以切合主題 並移除与維基百科內容方針相悖的過度細節內容 詳細信息請參見討論頁 钩子编程 hooking 也称作 挂钩 是计算机程序设计术语 指通过拦截软件模块间的函数调用 消息传递 事件传递来修改或扩展操作系统 应用程序或其他软件组件的行为的各种技术 处理被拦截的函数调用 事件 消息的代码 被称为钩子 hook 钩子编程有多种用途 如调试 扩展功能 例如在键盘或鼠标事件到达应用程序之前拦截这些事件 拦截应用程序或其他模块的操作系统调用以监督行为 修改功能 也广泛用于benchmarking程序 如度量3D游戏的帧率 钩子编程也被用于恶意代码 如rootkit是各种通过假扮系统API调用输出来隐藏自身进程的可见性的工具与技术 游戏外挂是另一类例子 目录 1 方法 1 1 物理修改 1 2 运行时修改 2 示例代码 2 1 虚函数表挂钩 2 2 C 键盘事件钩子 2 3 使用跳转指令的API 函数钩子拦截 2 4 Netfilter钩子 2 5 内部IAT钩子 2 6 Windows API提供的挂钩函数 3 参见 4 参考文献 5 外部链接 5 1 Windows 5 2 Linux 5 3 Emacs 5 4 OS X 与 iOS 5 5 Depth API Hooking方法 编辑物理修改 编辑 在应用程序执行之前 物理修改可执行程序 这典型通过找到函数调用入口点 修改入口点使之在函数被执行前先执行其他的代码 另一种挂钩的方法是修改可执行程序的输入表 import table 还有一种挂钩方法是采用包装库 使得应用程序不需修改即可调用该包装库完成其功能 而在包装库中插入钩子然后再调用原有的库 运行时修改 编辑 操作系统与软件可提供方法 在运行时插入事件钩子 Microsoft Windows允许插入钩子以处理或修改对话框 滚动条 菜单等的系统事件 应用程序事件 插入 删除 处理或修改键盘鼠标事件 Linux允许类似的钩子通过NetFilter以处理网络事件 如果没有上述机制或权限 也可拦截进程的库函数调用 在函数调用开始处注入代码 这可通过修改内存中的进程的中断向量表 英语 Interrupt vector table 或输入表 import table 实现 示例代码 编辑虚函数表挂钩 编辑 C 使用虚函数 因此可在运行时直接修改虚函数表的内容来挂钩 Window上很多软件库以COM方式提供的 如DirectX 所以有需求拦截COM调用的COM Hook COM里的接口是C 虚表的形式提供的 所以COM的Hook其实就是虚表 vtable 的Hook ATL就是用接口替代的方式来调试和记录COM接口引用计数的次数 class VirtualTable example class public virtual void VirtualFunction01 ticket void VirtualTable VirtualFunction01 ticket printf VirtualFunction01 called typedef void thiscall VirtualFunction01 t ticket thisptr VirtualFunction01 t g org VirtualFunction01 our detour function void fastcall hk VirtualFunction01 ticket thisptr int edx printf Custom function called call the original function g org VirtualFunction01 thisptr int tmain int argc TCHAR argv DWORD oldProtection VirtualTable myTable new VirtualTable void base void myTable VirtualProtect amp base 0 4 PAGE EXECUTE READWRITE amp oldProtection save the original function g org VirtualFunction01 VirtualFunction01 t base 0 overwrite base 0 amp hk VirtualFunction01 VirtualProtect amp base 0 4 oldProtection 0 call the virtual function now hooked from our class instance myTable gt VirtualFunction01 return 0 C 键盘事件钩子 编辑 using System Runtime InteropServices namespace Hooks public class KeyHook Member variables protected static int Hook protected static LowLevelKeyboardDelegate Delegate protected static readonly object Lock new object protected static bool IsRegistered false DLL imports DllImport user32 private static extern int SetWindowsHookEx int idHook LowLevelKeyboardDelegate lpfn int hmod int dwThreadId DllImport user32 private static extern int CallNextHookEx int hHook int nCode int wParam KBDLLHOOKSTRUCT lParam DllImport user32 private static extern int UnhookWindowsHookEx int hHook Types amp constants protected delegate int LowLevelKeyboardDelegate int nCode int wParam ref KBDLLHOOKSTRUCT lParam private const int HC ACTION 0 private const int WM KEYDOWN 0 x0100 private const int WM KEYUP 0 x0101 private const int WH KEYBOARD LL 13 StructLayout LayoutKind Sequential public struct KBDLLHOOKSTRUCT public int vkCode public int scanCode public int flags public int time public int dwExtraInfo Methods private static int LowLevelKeyboardHandler int nCode int wParam ref KBDLLHOOKSTRUCT lParam if nCode HC ACTION if wParam WM KEYDOWN System Console Out WriteLine Key Down lParam vkCode else if wParam WM KEYUP System Console Out WriteLine Key Up lParam vkCode return CallNextHookEx Hook nCode wParam lParam public static bool RegisterHook lock Lock if IsRegistered return true Delegate LowLevelKeyboardHandler Hook SetWindowsHookEx WH KEYBOARD LL Delegate Marshal GetHINSTANCE System Reflection Assembly GetExecutingAssembly GetModules 0 ToInt32 0 if Hook 0 return IsRegistered true Delegate null return false public static bool UnregisterHook lock Lock return IsRegistered UnhookWindowsHookEx Hook 0 使用跳转指令的API 函数钩子拦截 编辑 下述例子使用JMP 英语 JMP x86 instruction 指令 修改windows API中的MessageBoxW函数的前6个字节执行其他代码 这段代码编译为DLL文件 采用DLL注入技术让应用程序使用 1 微软提供了封装好的Detours库用于此目的 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 lt windows h gt 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 0xC3 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 amp oldProtect memcpy oldBytes pOrigMBAddress SIZE make backup memcpy amp JMP 1 amp 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 Netfilter钩子 编辑 使用Netfilter钩子修改Linux内核的网络交通 include lt linux module h gt include lt linux kernel h gt include lt linux skbuff h gt include lt linux ip h gt include lt linux tcp h gt include lt linux in h gt include lt linux netfilter h gt include lt linux netfilter ipv4 h gt Port we want to drop packets on static const uint16 t port 25 This is the hook function itself static unsigned int hook func unsigned int hooknum struct sk buff pskb const struct net device in const struct net device out int okfn struct sk buff struct iphdr iph ip hdr pskb struct tcphdr tcph tcpbuf if iph gt protocol IPPROTO TCP return NF ACCEPT tcph skb header pointer pskb ip hdrlen pskb sizeof tcph amp tcpbuf if tcph NULL return NF ACCEPT return tcph gt dest port NF DROP NF ACCEPT Used to register our hook function static struct nf hook ops nfho hook hook func hooknum NF IP PRE ROUTING pf NFPROTO IPV4 priority NF IP PRI FIRST static init int my init void return nf register hook amp nfho static exit void my exit void nf unregister hook amp nfho module init my init module exit my exit 内部IAT钩子 编辑 下例展示通过修改可执行程序的输入地址表 IAT 把钩子函数替代原函数 include lt windows h gt typedef int stdcall pMessageBoxA HWND hWnd LPCSTR lpText LPCSTR lpCaption UINT uType This is the type of the MessageBoxA call pMessageBoxA RealMessageBoxA This will store a pointer to the original function void DetourIATptr const char function void newfunction HMODULE module int stdcall NewMessageBoxA HWND hWnd LPCSTR lpText LPCSTR lpCaption UINT uType Our fake function printf The String Sent to MessageBoxA Was s n lpText return RealMessageBoxA hWnd lpText lpCaption uType Call the real function int main int argc CHAR argv DetourIATptr MessageBoxA void NewMessageBoxA 0 Hook the function MessageBoxA NULL Just A MessageBox Just A MessageBox 0 Call the function this will invoke our fake hook return 0 void IATfind const char function HMODULE module Find the IAT Import Address Table entry specific to the given function int ip 0 if module 0 module GetModuleHandle 0 PIMAGE DOS HEADER pImgDosHeaders PIMAGE DOS HEADER module PIMAGE NT HEADERS pImgNTHeaders PIMAGE NT HEADERS LPBYTE pImgDosHeaders pImgDosHeaders gt e lfanew PIMAGE IMPORT DESCRIPTOR pImgImportDesc PIMAGE IMPORT DESCRIPTOR LPBYTE pImgDosHeaders pImgNTHeaders gt OptionalHeader DataDirectory IMAGE DIRECTORY ENTRY IMPORT VirtualAddress if pImgDosHeaders gt e magic IMAGE DOS SIGNATURE printf libPE Error e magic is no valid DOS signature n for IMAGE IMPORT DESCRIPTOR iid pImgImportDesc iid gt Name NULL iid for int funcIdx 0 funcIdx LPVOID iid gt FirstThunk SIZE T module NULL funcIdx char modFuncName char funcIdx SIZE T iid gt OriginalFirstThunk SIZE T module SIZE T module 2 const uintptr t nModFuncName uintptr t modFuncName bool isString nModFuncName amp sizeof nModFuncName 4 0x80000000 0x8000000000000000 if isString if stricmp function modFuncName return funcIdx LPVOID iid gt FirstThunk SIZE T module return 0 void DetourIATptr const char function void newfunction HMODULE module void funcptr IATfind function module if funcptr newfunction return DWORD oldrights newrights PAGE READWRITE Update the protection to READWRITE VirtualProtect funcptr sizeof LPVOID newrights amp oldrights RealMessageBoxA pMessageBoxA funcptr Some compilers require the cast like MinGW not sure about MSVC funcptr newfunction Restore the old memory protection flags VirtualProtect funcptr sizeof LPVOID oldrights amp newrights Windows API提供的挂钩函数 编辑 SetWinEventHook 基本没有权限问题 也就是说这个API可以Hook到高权限程序的事件 同时支持进程内 WINEVENT INCONTEXT 和进程外 WINEVENT OUTOFCONTEXT 2种Hook方式 可以进程外的方式Hook到64位程序的事件 SetWindowsHookEx 64位编程情形 32位DLL没法直接注入到64位的应用程序里面 因为地址空间完全不一样 UAC打开的情况下低权限程序没法Hook高权限程序 对于64位问题 解决方法是提供2个DLL 分别可以Hook32和64位程序 对于权限问题 通过注册系统服务 由服务进程创建工作进程 因为Windows Vista开始有了Session隔离机制 服务进程运行在Session 0 用户程序运行在Session 1 Session 2等 如果直接在服务程序里干活 我们就只能在Session 0里工作 通过创建进程 可以在DuplicateTokenEx后将Token的SessionID设置成目标Session 并且在CreateProcessAsUser时指定目标WinStation和Desktop 这样就获得了System权限 并且也可以和当前桌面进程交互 参见 编辑回调函数 委托 编程 终止并驻留 英语 Terminate and Stay Resident Using TSR User exit 英语 User exit WinAPIOverride32 英语 WinAPIOverride32 参考文献 编辑 For more information see http ntvalk blogspot nl 2013 11 hooking explained detouring library html 页面存档备份 存于互联网档案馆 Jonathan Daniel Hooking explained detouring library calls and vtable patching in Windows Linux MAC OSX 2013 11 27 2014 01 01 原始内容存档于2018 05 03 Binh Nguyen Hacking Lexicon Linux Dictionary V 0 16 2004 08 16 2008 02 23 原始内容存档于2021 03 22 Hook Author Holy Father Hooking Windows API Technics of hooking API functions on Windows 1 1 english PDF 2002 06 10 2008 02 21 原始内容存档 PDF 于2020 10 28 外部链接 编辑Windows 编辑 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 编辑 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 编辑 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 与 iOS 编辑 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 Depth API Hooking 编辑 x86 API Hooking Demystified 页面存档备份 存于互联网档案馆 Article on various API Hooking methods for the x86 architecture 取自 https zh wikipedia org w index php title 钩子编程 amp oldid 75835571, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。