跨进程hook api的资料

 什么是“跨进程   API   Hook”?  
  众所周知Windows应用程序的各种系统功能是通过调用API函数来实现。API   Hook就是给系统的API附加上一段小程序,它能监视甚至控    
  制应用程序对API函数的调用。所谓跨进程也就是让自己的程序来控制别人程序的API调用了。  
   
  API   Hook   理论  
  通过对Win32   PE文件的分析(如果你还不熟悉PE文件格式,可以看看Iczelion的PE教程或者LUEVELSMEYER的<>)。我们知道在PE文件中的IMPORT   TABLE内存储着API函数的很多信息。其中包括API的函数名,调用地址等等。而操作系统在执行PE文件时会先将其映射到内存中。在映射的同时还会把当前版本操作系统中API函数的入口地址写入IMPORT   TABLE中一组与API调用相关的结构体内,用于该应用程序的API调用。   当应用程序调用API时,他会在自己内存映像里寻找API的入口地址,然后执行CALL指令。如此一来,我们通过修改应用程序内存映像的IMPORT   TABLE中API函数的入口地址,就可以达到重定向API的目的。将API地址改为我们自己函数的地址,这样我们的函数就可以完成对API的监视和控制了。  
   
  API   Hook   的实现  
  /*   1   */HANDLE   hCurrent   =   GetModuleHandle(NULL);  
  /*   2   */IMAGE_DOS_HEADER   *pidh;  
  /*   3   */IMAGE_NT_HEADERS   *pinh;  
  /*   4   */IMAGE_DATA_DIRECTORY   *pSymbolTable;  
  /*   5   */IMAGE_IMPORT_DESCRIPTOR   *piid;  
     
  /*   6   */pidh   =   (IMAGE_DOS_HEADER   *)hCurrent;    
  /*   7   */pinh   =   (IMAGE_NT_HEADERS   *)((DWORD)hCurrent   +   pidh->e_lfanew);  
  /*   8   */pSymbolTable   =   &pinh->OptionalHeader.DataDirectory[1];  
  /*   9   */piid   =(IMAGE_IMPORT_DESCRIPTOR   *)((DWORD)hCurrent   +     pSymbolTable->VirtualAddress);  
  /*10   */do   {  
  /*11   */         IMAGE_THUNK_DATA   *pitd,*pitd2;  
  /*12   */         pitd   =   (IMAGE_THUNK_DATA   *)((DWORD)hCurrent   +   piid->OriginalFirstThunk);  
  /*13   */         pitd2   =   (IMAGE_THUNK_DATA   *)((DWORD)hCurrent   +   piid->FirstThunk);  
  /*14   */         do   {  
  /*15   */   IMAGE_IMPORT_BY_NAME   *piibn;  
  /*16   */   piibn   =   (IMAGE_IMPORT_BY_NAME   *)((DWORD)hCurrent   +     *((DWORD   *)pitd));  
  /*17   */   PROC   *ppfn   =   (PROC   *)(pitd2->u1.Function);  
  /*18   */   if   (!strcmp("MessageBoxW",(char   *)piibn->Name))   {  
  /*19   */           oldMsg   =   (MsgBoxType)(ppfn);  
  /*20   */           DWORD   addr   =   (DWORD)MyMessage;  
  /*21   */           DWORD   written   =   0;  
              /*   改变内存读写状态   */  
  /*22   */           DWORD   oldAccess;  
  /*23   */           VirtualProtect(&pitd2->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);  
  /*24   */           APIAddress   =   (DWORD)&pitd2->u1.Function;  
              /*   向内存映像写入数据   */  
  /*25   */           WriteProcessMemory(GetCurrentProcess(),&pitd2->u1.Function,   &addr,sizeof(DWORD),   &written);  
  /*26   */   }  
  /*27   */   pitd++;pitd2++;  
  /*28   */         }   while   (pitd->u1.Function);  
     
  /*29   */         piid++;  
  /*30   */}   while   (piid->FirstThunk   +   piid->Characteristics    
      +   piid->ForwarderChain   +   piid->Name   +   piid->TimeDateStamp);  
  分析:  
  寻觅IMPORT   TALBE  
  在/*1*/中我们使用GetModuleHandle(NULL)来返回当前进程在内存中映像的基地址。但这个值在文档中仅仅被描述为"a   module   handle   for   the   specified   module",虽然他确实是进程内存映像的基地址。如果你不太放心的话也可以使用,GetModuleInformation函数来获得基地址,只不过你要额外包含psapi.h和psapi.lib了(这个库在VC6里没有,所以我就没有用这个函数了)。在/*   6   */里我们先找到IMAGE_DOS_HEADER结构,他的起始地址就是映像的基地址。/*7*/通过IMAGE_DOS_HEADER给出的PE文件头的偏移量,找到IMAGE_NT_HEADERS结构。顺藤摸瓜,IMAGE_NT_HEADERS里的OptionalHeader中的DataDirectory数组里的第二个元素正是指向我们想要的IMPORT   TABLE的地址。在/*9*/中我们将其转化为一个IMAGE_IMPORT_DESCRIPTOR的结构指针存入piid中。  
   
  替换的API函数入口地址  
  在/*12*/和/*13*/中我们分别取得OriginalFirstThunk和FirstThunk结构,用于以后得到API函数的名称和入口地址。/*10*/的do循环让我们遍历每一个IMAGE_IMPORT_DESCRIPTOR结构也就是应用程序引用的每个DLL。在/*14*/的循环中我们遍历DLL中的IMAGE_THUNK_DATA结构来一一查询API的信息。/*16*/中我们将OriginalFirstThunk转换为IMAGE_IMPORT_BY_NAME结构用于获得API函数的名称进行比对。在/*18*/我们找到MessageBoxW函数之后,在/*19*/保存其原始入口地址便于以后恢复时使用。在/*23*/我们需要用VirtualProtect改变一下内存区域的读写性,因为一般应用程序的映像都是只读的,直接写入会造成一个非法访问的异常出现。在/*25*/我们写入自己函数的地址。  
   
  这样就基本完成一个API函数的重定向。  
   
  其他  
  恢复函数的API入口地址相对比较简单。只要把保存的值再写回去就可以了。上面的程序中/*24*/我用APIAddress保存了存有MessageBoxW入口地址的地方的地址,便于以后调用WriteProcessMemory恢复时使用。  
   
  跨进程理论  
  我们要用自己的函数来替代别人程序里的API函数,但我们的函数与别人的程序处于不同的进程空间内啊。不同的进程空间是不能相互调用函数的。因此我们要想办法把自己的函数放入别人的进程空间去。这时我们就需要使用DLL   injection技术了。如果你对她还不是十分熟悉的话,建议看看Jeffrey   Richter大师的<>,也可以参考陈宽达先生的<>。  
   
  简而言之,DLL   injection就是想办法让对方的进程加载我们的一个DLL程序,把需要替换的函数放在我们这个DLL里。如此一来,我们的函数就进入了别人的进程空间了。DLL   injection方法很多,Richter大师在书中对各方法利弊有详细解释,陈宽大先生的书中也有深入的分析。我在这里使用SetWindowsHookEx函数来达到目的。主要有这几个原因:   1,   不用重新启动系统,调试方便。2,   可以利用消息循环机制进行两个进程之间的通信,可以较好的掌握Hook的状态。便于安装与卸载。  
   
  SetWindowsHookEx之所以能完成DLL   injection是因为它要给一个应用程序某个环节加上一个Hook,而Hook就要有Hook   Procedure也就是Hook函数。如果这个Hook函数在一个DLL中,那么系统就会把这个DLL加载到SetWindowsHookEx的目标进程上。从而也就达到了我们DLL   injection的目的了。当然这里我们会用WH_GETMESSAGE的Hook进行injection,因为这个Hook可以用来监视目标进程的消息循环方便我们的进程与目标进程通信。

 

 

跨进程的实现和几点注意  
  /*   DllPart.Dll   */  
  #include    
  #include    
  #include    
  #include    
  typedef   (WINAPI   *MsgBoxType)(HWND,LPCWSTR,LPCWSTR,UINT);    
  MsgBoxType   oldMsg;     /*API原入口地址*/  
  DWORD   APIAddress;   /*存储API入口地址的地方的地址*/  
  int   WINAPI     MyMessage(HWND   hWnd   ,LPCWSTR   M1,LPCWSTR   M2,   UINT   M3)   {  
    /*   这是用来替换的函数   */  
    return   oldMsg(hWnd,buf,M2,MB_OK);  
  }  
  const   char   szApp[]   =   "DllPart.dll";  
  HHOOK   hHook;   /*Hook的句柄*/  
  HMODULE   hInst;   /*DLL   模块句柄,用于SetWindowsHookEx函数*/  
  HWND   hTarget;   /*目标窗口句柄*/  
  /*DLL   入口*/  
  BOOL   WINAPI   DllMain(HINSTANCE   inst,   DWORD   reason,   LPVOID   lpvReserved)  
  {  
          hInst   =   inst;  
          switch   (reason)   {  
    case   DLL_PROCESS_ATTACH:  
            /*调试信息,表示DLL已经加载*/  
            MessageBox(NULL,"DLL_PROCESS_ATTACH",szApp,MB_OK);  
            break;  
    case   DLL_PROCESS_DETACH:  
            /*调试信息,表示DLL已经卸载*/  
            MessageBox(NULL,"DLL_PROCESS_DETACH",szApp,MB_OK);  
            break;  
          }  
          return   true;  
  }  
  /*显示GetLastError的信息*/  
  void   showerr(const   char   *m)   {  
          char   message[255];  
          FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError()  
    ,MAKELANGID(LANG_NEUTRAL,   SUBLANG_DEFAULT),message,255,   0);  
          MessageBox(NULL,message,m,MB_OK);  
  }  
  //-----------------------  
  void   UnHookApi()   {  
    /*卸载API   Hook用*/  
  }  
  void   HookApi()   {  
    /*加载API   Hook同上面介绍的函数一样*/  
  }  
  //-----------------------  
  /*用于WH_GETMESSAGE的Hook   Procedure*/  
  LRESULT   CALLBACK   GetMsgProc(int   nCode,WPARAM   wParam,   LPARAM   lParam)   {  
    if   (nCode   ==   HC_ACTION)   {  
            MSG   *msg   =   (MSG   *)lParam;  
            if   (msg->message   ==   WM_CHAR)   {  
              if   (msg->wParam   ==   'h')   HookApi();  
              if   (msg->wParam   ==   'u')   UnHookApi();  
            }  
    }  
          return   CallNextHookEx(hHook,nCode,wParam,lParam);  
  }  
  extern   "C"   __declspec(dllexport)   SetAPIHook(HWND   handle)   {  
          DWORD   ThreadId   =   GetWindowThreadProcessId(handle,   NULL);  
          hTarget   =   handle;  
          MessageBox(NULL,   "Enabling   CallWndProc   Hook",   szApp,   MB_OK);  
          hHook   =   SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInst,ThreadId);    
          if   (hHook)   {  
    MessageBox(NULL,"Hook   OK!",   szApp,   MB_OK);  
          }   else   {  
    showerr("SetWindowsHookEx");  
          }  
  }  
  extern   "C"   __declspec(dllexport)   UnHookAPIHook()   {  
          MessageBox(NULL,   "Disenabling   CallWndProc   Hook",   szApp,   MB_OK);  
          if   (UnhookWindowsHookEx(hHook))   {  
                  MessageBox(NULL,"UnHook   OK!",   szApp,   MB_OK);    
          }   else   {  
    showerr("UnHookWindowsHookEx");  
          }  
  }  
  分析  
  几个需要注意的问题  
  SetAPIHook和UnHookAPIHook是我们自己进程调用的用来加载WH_GETMESSAGE   Hook的函数。由于我们的程序要用LoadLibrary加载这个Dll因此这两个函数要用__declspec(dllexport)修饰,使其成为导出函数,才能被GetAddressProc函数找到。加上   extern   "C"是让编译器使用C语言编码方式。因为C++编译器会进行Dynamic   Binding(C++函数重载的实现),将函数的参数类型附加到名称上。是函数的导出名看起来像SetAPIHook@XYTZX之类的,不利于GetAddressProc进行引用。因此使用extern   "C"让编译器不使用Dynamic   Binding,自然使用extern"C"的函数也就不能被重载了。  
   
  不要忘记在GetMsgProc最后要调用CallNextHookEx函数,保证Hook链的完整性。  
   
  一定要在Hook   Procedure中调用HookApi和UnHookApi函数,因为保存API入口地址的地方在目标进程中,你必须在目标进程的进程空间内完成卸载操作,不能在UnHookAPIHook或是SetAPIHook函数中调用,因为UnHookAPIHook是我们的进程调用的,因此在我们的进程空间中。在这里使用UnHookApi会造成一个非法访问的错误。而使用HookApi会给自己的DLL加上API   Hook。  
   
  SetWindowsHookEx的最后参数是ThreadId不是Handle,因此要通过调用GetWindowThreadProcessId转换一下。    
   
  在跨进程API   HOOK时可能用到的其他技术  
  主进程与目标进程的信息交互和共享  
  由于使用了WH_GETMESSAGE钩子我们可以利用Windows消息机制实现进程间通讯。需要注意的是应该使用PostThreadMessage来发送让WH_GETMESSAGE得到的消息而不是SendMessage或者PostMessage,因为后两个是用来给窗口发送消息的。而我们的WH_GETMESSAGE是Hook在线程上面的,因此需使用PostThreadMessage.  
   
  传递不太大的数据可以使用WM_COPYDATA消息来进行。同样也应该注意,如果使用MFC的窗口过程获得消息就需要用SendMessage发送了。WM_COPYDATA的使用相对简单可以参考MSDN的文档。也可以参考附录里的程序Hook.cpp的showerr函数部分。  
   
  如果传递较大的数据或者希望数据共享比较方便可以开辟共享内存来进行数据共享。这里简单分析一下使用共享内存的代码    
   
  HANDLE   hMap;  
  switch   (reason)   {  
          case   DLL_PROCESS_ATTACH:  
          /*创建/打开共享内存区域*/  
          hMap   =   CreateFileMapping((HFILE   *)0xFFFFFFFF,NULL,PAGE_READWRITE,0,sizeof(GLOBALDATA),ID_MAP);  
          pg_data   =   (GLOBALDATA*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0   ,0   ,0);  
          if   (!pg_data)   {  
    MessageBox(NULL,"无法建立共享内存,程序终止!",szApp,MB_OK);  
    if   (hMap)   {  
            CloseHandle(hMap);  
            hMap   =   NULL;  
            return   0;  
                }  
          }  
          pg_data->hInst   =   hInst;  
          showerr("共享内存映像文件");  
          showerr("DLL装载中...",FALSE);  
          break;  
          case   DLL_PROCESS_DETACH:  
          if   (pg_data)   {  
                  UnmapViewOfFile(pg_data);  
    pg_data   =   NULL;  
          }  
          if   (hMap)   {  
    CloseHandle(hMap);  
    hMap   =   NULL;  
            }  
          break;  
  }  
   
  上面的代码通过CreateFileMapping建立共享区域。将其第一个参数设置为0xFFFFFFFF使其能创建一个内存共享区域而不是文件。并标记为可读写的(PAGE_READWRITE).其大小为我们定义的结构体GLOBALDATA的大小。最后的ID_MAP是一个用来标示这个区域的字符串。打开或者创建完共享区域后,我们用MapViewOfFile来获得这个区域的地址。之后就可以直接使用pg_data来操作共享区域了。不要忘记在DLL退出的时候安全的删除共享区域释放内存。    
  消息等待与安全卸载  
  在我们卸载WH_GETMESSAGE钩子之前必须先把目标程序的API调用恢复正常。我们不能再调用UnHookApi之后就立刻调用UnhookWindowsHookEx,因为很有可能UnHookApi还没来得急完成API入口地址的恢复操作,WH_GETMESSAGE钩子就已经被卸载了。因此需要等待一段时间,等UnHookApi完成了恢复操作在调用UnhookWindowsHookEx。以防错误发生。  
   
  extern   "C"   __declspec(dllexport)   void   UnHookAPIHook()   {  
          /*向目标线程发送消息进行API   UNHOOK*/  
          PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOK,(WPARAM)GetCurrentThreadId(),0);  
          showerr("WM_DISABLEAPIHOOK");  
          /*等待目标进程返回WM_UNHOOKOK消息,确认可以将WH_GETMESSAGE的HOOK去掉*/  
           
          MSG   Msg;  
          do   {  
                  GetMessage(&Msg,NULL,0,0);  
          }while(Msg.message   !=     WM_UNHOOKOK);  
          UnhookWindowsHookEx(pg_data->hHook);  
          PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOKOK,(WPARAM)GetCurrentThreadId(),0);  
          showerr("UnHookWindowsHookEx");  
  }  
  上面的代码中我们使用一个含有GetMessage的循环来等待消息的到达,一旦UnHookApi完成他就会发送WM_UNHOOKOK消息。等我们接收到消息确认一切安全了在来卸载WH_GETMESSAGE钩子。    
  弄清消息对象  
  我们一定要清楚代码是在主程序进程空间中执行的还是在目标程序进程空间中执行的。像上面的UnHookAPIHook函数就是通过主程序调用的,因此在主程序进程空间中执行。这样一来用来恢复目标程序API信息的UnHookApi完成后就应该向主程序发送消息,而不是目标程序。  
   
  目标进程加载了其他DLL  
  如果目标进程动态加载了其他的DLL文件,我们必须监视LoadLibrary函数。保证DLL中的API入口地址也被正确修改。防止出现混乱的情况。我从LoadLibrary获得DLL的路径用于GetModuleHandle来取得他的ImageBase的地址。

 

 

附:跨进程APIHook的例子  
  先打开一个记事本程序并输入几个字符,运行下面的程序,加载APIHook.之后在记事本的文件菜单中选择新建就会看到API   Hook将MessageBoxW   函数Hook的结果了.  
  代码在WinXP   SP1   +   VC6.0测试成功。  
   
  以下为源程序:  
   
  这是DLL的程序,Hook.dll  
  #include    
  #include    
  #include    
  #include    
  #include   "mydef.h"  
   
  const   char   szApp[]   =   "Hook.dll";   /*应用程序名称*/  
  HANDLE   hMap;/*在共享内存映像的句柄*/  
  GLOBALDATA   *pg_data;   /*在共享内存中的全局数据*/  
  LRESULT   CALLBACK   GetMsgProc(int,WPARAM,   LPARAM);  
   
  /*显示GetLastError指出的错误*/  
  void   showerr(const   char   *m,   BOOL   GetError   =   TRUE)   {  
          char   message[127];  
          char   buf[255];  
          COPYDATASTRUCT   cds;  
          if   (GetError)    
                  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0  
      ,GetLastError(),MAKELANGID(LANG_NEUTRAL,   SUBLANG_DEFAULT),message,127,   0);  
          else    
                  *message   =   0;  
          if   (GetCurrentThreadId()   !=   pg_data->idMain)  
                  sprintf(buf,"目标程序空间DLL:   %-30s   [%-40s]",m,   message);  
          else  
                  sprintf(buf,"主程序空间DLL     :   %-30s   [%-40s]",m,   message);  
          cds.lpData   =   buf;  
          cds.cbData   =   sizeof(buf);  
          cds.dwData   =   0;  
     
          SendMessage(pg_data->hWndMain,WM_COPYDATA,(WPARAM)pg_data->hWndTarget,(LPARAM)&cds);  
       
          SetLastError(0);  
  }  
  int   WINAPI   MyMessageBoxW(HWND   hWnd   ,LPCWSTR   M1,LPCWSTR   M2,   UINT   M3)   {  
          wchar_t   buf[255];  
          swprintf(buf,L"!!这个窗口的API被Hook了!!/nHWND:   0x%08X/nMessage:   %s/nCaption:   %s"  
                  ,(DWORD   *)hWnd  
                  ,   M1  
                  ,   M2);  
          pg_data->oldAPIFunction(hWnd,buf,M2,MB_OK);  
          return   pg_data->oldAPIFunction(hWnd,M1,M2,M3);  
  }  
   
  /*DLL   入口函数*/  
  BOOL   WINAPI   DllMain(HINSTANCE   hInst,   DWORD   reason,LPVOID   lpvReserved)  
  {  
          switch   (reason)   {  
          case   DLL_PROCESS_ATTACH:  
                  /*创建/打开共享内存区域*/  
                  hMap   =   CreateFileMapping((HFILE   *)0xFFFFFFFF,NULL,PAGE_READWRITE,0,sizeof(GLOBALDATA),ID_MAP);  
                  pg_data   =   (GLOBALDATA*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0   ,0   ,0);  
                  if   (!pg_data)   {  
                        MessageBox(NULL,"无法建立共享内存,程序终止!",szApp,MB_OK);  
                        if   (hMap)   {  
                                CloseHandle(hMap);  
                                hMap   =   NULL;  
                                return   0;  
                          }  
                  }  
                  pg_data->hInst   =   hInst;  
                  showerr("共享内存映像文件");  
                  showerr("DLL装载中...",FALSE);  
                  break;  
          case   DLL_PROCESS_DETACH:  
                  showerr("DLL卸载中...",FALSE);  
                  if   (pg_data)   {  
                          UnmapViewOfFile(pg_data);  
                          pg_data   =   NULL;  
                  }  
                  if   (hMap)   {  
                          CloseHandle(hMap);  
                          hMap   =   NULL;  
                  }  
                  break;  
          }  
          return   true;  
  }  
  /*卸载API   Hook*/  
  void   UnHookApi()   {  
          DWORD   written   =   0;  
          DWORD   oldaddrAPIFunction   =   (DWORD)pg_data->oldAPIFunction;  
          WriteProcessMemory(GetCurrentProcess(),(DWORD   *)pg_data->addrAPIEntryPoint  
                  ,   &oldaddrAPIFunction,sizeof(DWORD),   &written);  
          showerr("WriteProcessMemory   on   UnHook");  
          /*向主线程发送   API   UNHOOK   处理完毕的消息*/  
          PostThreadMessage(pg_data->idMain,WM_UNHOOKOK,0,0);  
  }  
   
  /*加载API   Hook*/  
  void   HookApi(const   char*   szApiName,   tAPIFunction   newAddr,   DWORD   ImageBase)   {  
          /*这段代码请参考文章中的分析*/  
          IMAGE_DOS_HEADER   *pidh;  
          IMAGE_NT_HEADERS   *pinh;  
          IMAGE_DATA_DIRECTORY   *pSymbolTable;  
          IMAGE_IMPORT_DESCRIPTOR   *piid;  
       
          pidh   =   (IMAGE_DOS_HEADER   *)ImageBase;          
          pinh   =   (IMAGE_NT_HEADERS   *)((DWORD)ImageBase   +   pidh->e_lfanew);  
          pSymbolTable   =   &pinh->OptionalHeader.DataDirectory[1];  
          piid   =(IMAGE_IMPORT_DESCRIPTOR   *)((DWORD)ImageBase   +     pSymbolTable->VirtualAddress);  
   
          do   {  
                  IMAGE_THUNK_DATA   *pitd_org,*pitd_1st;  
                  pitd_org   =   (IMAGE_THUNK_DATA   *)((DWORD)ImageBase   +   piid->OriginalFirstThunk);  
                  pitd_1st   =   (IMAGE_THUNK_DATA   *)((DWORD)ImageBase   +   piid->FirstThunk);  
                  do   {  
                          IMAGE_IMPORT_BY_NAME   *piibn;  
                          piibn   =   (IMAGE_IMPORT_BY_NAME   *)((DWORD)ImageBase   +     *((DWORD   *)pitd_org));  
                          PROC   *pAPIFunction   =   (PROC   *)(pitd_1st->u1.Function);  
                          if   (!strcmp(szApiName,(char   *)piibn->Name))   {  
                                  DWORD   addrNewAPIFunction   =   (DWORD)MyMessageBoxW;  
                                  DWORD   written   =   0;  
                                  DWORD   oldAccess;  
   
                                  pg_data->oldAPIFunction   =   (tAPIFunction)(pAPIFunction);  
                                  /*Change   Memeory   State*/  
                                  VirtualProtect(&pitd_1st->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);  
                                  showerr("VirtualProtect");  
                                  pg_data->addrAPIEntryPoint   =   (DWORD)&pitd_1st->u1.Function;  
                                  /*Write   Process   Memory*/  
                                  WriteProcessMemory(GetCurrentProcess(),&pitd_1st->u1.Function  
                                          ,   &addrNewAPIFunction,sizeof(DWORD),   &written);  
                                  showerr("WriteProcessMemory   on   Hook");  
                          }  
                          pitd_org++;  
                          pitd_1st++;  
                  }   while   (pitd_1st->u1.Function);  
                 
                  piid++;  
          }   while   (piid->FirstThunk   +   piid->Characteristics    
    +   piid->ForwarderChain   +   piid->Name   +   piid->TimeDateStamp);  
  }  
   
  //-----------------------  
  extern   "C"   __declspec(dllexport)   BOOL   SetAPIHook(HWND   _target)   {  
          pg_data->hHook   =   SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,pg_data->hInst,pg_data->idTarget);          
          showerr("SetWindowsHookEx");  
          /*向目标线程发送消息进行API   HOOK*/  
          if   (pg_data->hHook)   {  
                  PostThreadMessage(pg_data->idTarget,WM_ENABLEAPIHOOK,0,0);  
          }   else   {  
                  return   FALSE;  
          }  
          showerr("WM_ENABLEAPIHOOK");  
          return   TRUE;  
  }  
   
  extern   "C"   __declspec(dllexport)   void   UnHookAPIHook()   {  
          /*向目标线程发送消息进行API   UNHOOK*/  
          PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOK,(WPARAM)GetCurrentThreadId(),0);  
          showerr("WM_DISABLEAPIHOOK");  
          /*等待目标进程返回WM_UNHOOKOK消息,确认可以将WH_GETMESSAGE的HOOK去掉*/  
          MSG   Msg;  
          do   {  
                  GetMessage(&Msg,NULL,0,0);  
          }while(Msg.message   !=     WM_UNHOOKOK);  
   
          UnhookWindowsHookEx(pg_data->hHook);  
          PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOKOK,(WPARAM)GetCurrentThreadId(),0);  
          showerr("UnHookWindowsHookEx");  
  }  
   
  LRESULT   CALLBACK   GetMsgProc(int   nCode,WPARAM   wParam,   LPARAM   lParam)   {  
          if   (nCode   ==   HC_ACTION)   {  
                  MSG   *msg   =   (MSG   *)lParam;  
             
                  if   (msg->message   ==   WM_ENABLEAPIHOOK)   {  
                          HookApi("MessageBoxW",MyMessageBoxW,(DWORD)GetModuleHandle(NULL));  
                  }  
                  if   (msg->message   ==   WM_DISABLEAPIHOOK)   {  
                          UnHookApi();  
                  }  
                  if   (msg->message   ==   WM_DESTROY)   {  
                          showerr("目标进程退出!",FALSE);  
                  }  
          }  
          return   CallNextHookEx(pg_data->hHook,nCode,wParam,lParam);  
  }

 

 

 这个是主程序的关键部分   HookGui.cpp  
  用MFC建立一个窗口程序,包含两个按钮和一个ListBox  
   
  typedef   void   (*PUnHookAPIHook)();  
  typedef   BOOL   (*PSetAPIHook)(HWND);  
  HMODULE   hDll   =   NULL;  
  HWND   hNotePad   =   NULL;  
  PSetAPIHook   SetAPIHook;  
  PUnHookAPIHook   UnHookAPIHook;  
  GLOBALDATA   *pg_data;   /*在共享内存中的全局数据*/  
  HANDLE   hMap;   /*在共享内存映像的句柄*/  
  int   CHookGUIDlg::showerr(const   char*   m)   {  
          char   message[127];  
          char   buf[255];  
          int   errId   =   GetLastError();  
          FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0  
    ,errId,MAKELANGID(LANG_NEUTRAL,   SUBLANG_DEFAULT),message,127,   0);  
          sprintf(buf,"主程序                   :   %-30s   [%-40s]/n",m,   message);  
          c_List1.InsertString(c_List1.GetCount(),buf);  
          UpdateData(FALSE);  
          return   errId;  
  }  
   
  void   CHookGUIDlg::OnSetapihook()    
  {  
          //   TODO:   Add   your   control   notification   handler   code   here  
          hDll   =   LoadLibrary("Hook.dll");  
          showerr("LoadLibrary");  
          hMap   =   OpenFileMapping(FILE_MAP_ALL_ACCESS,false,ID_MAP);  
          showerr("OpenFileMapping");          
          pg_data   =   (GLOBALDATA   *)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);  
          showerr("MapViewOfFile");          
          if   (!pg_data)   {  
                  MessageBox("不能打开共享内存程序终止!");  
                  return;  
          }  
          SetAPIHook   =   (PSetAPIHook)GetProcAddress(hDll,"SetAPIHook");  
          showerr("GetProcAddress-SetAPIHOOK");  
         
          pg_data->hWndTarget   =   ::FindWindow("NotePad",NULL);  
          pg_data->hWndMain   =   m_hWnd;  
          pg_data->idMain   =   GetWindowThreadProcessId(m_hWnd,NULL);  
          pg_data->idTarget   =   GetWindowThreadProcessId(pg_data->hWndTarget,NULL);  
          if   (!showerr("FindWindow"))   {  
                  if   (SetAPIHook)   {    
                          if   (SetAPIHook(hNotePad))  
                                  PostThreadMessage(pg_data->idTarget  
        ,   WM_SETCALLERID,(LPARAM)GetCurrentThreadId(),0);  
                          else   {  
                                  MessageBox("SetWindowHookEx时出错,程序终止!");  
                                  return;  
                          }  
                  }   else   {  
                          MessageBox("无法取得SetAPIHook函数!程序终止!");                                          
                  }  
          }   else   {  
                          MessageBox("内存中没有找到NOTEPAD.EXE");                          
          }  
          c_SetApiHook.EnableWindow(FALSE);  
          c_UnsetApiHook.EnableWindow();  
  }  
   
  void   CHookGUIDlg::OnUnsetapihook()    
  {  
          //   TODO:   Add   your   control   notification   handler   code   here  
          if   (hDll)   {  
                  if   (   !IsWindow(pg_data->hWndTarget))   {  
                          MessageBox("目标进程不在内存中");  
                          return;  
                  }  
                  UnHookAPIHook   =   (PUnHookAPIHook)GetProcAddress(hDll,"UnHookAPIHook");  
                  showerr("GetProcAddress-UnHookAPIHook");  
                  if   (UnHookAPIHook)    
                          UnHookAPIHook();  
                  FreeLibrary(hDll);  
                  showerr("FreeLibrary");  
                  hDll   =   NULL;  
          }   else   {  
                  MessageBox("请先加载DLL");  
          }  
          c_SetApiHook.EnableWindow();  
          c_UnsetApiHook.EnableWindow(FALSE);  
  }  
   
  void   CHookGUIDlg::OnOK()    
  {  
          //   TODO:   Add   extra   validation   here  
          if   (hDll)   {  
                  OnUnsetapihook();  
          }  
          CDialog::OnOK();  
  }  
   
  BOOL   CHookGUIDlg::OnCopyData(CWnd*   pWnd,   COPYDATASTRUCT*   pCopyDataStruct)    
  {  
          //   TODO:   Add   your   message   handler   code   here   and/or   call   default  
          c_List1.InsertString(c_List1.GetCount(),(char   *)pCopyDataStruct->lpData);  
          return   CDialog::OnCopyData(pWnd,   pCopyDataStruct);  

 

 

下面是另一个API   HOOK的实例剖析:  
  一、APIHOOK之dll部分  
     
    APIHook_Dll.cpp    
  //                                                           rivershan写于2002.9.23                                                                     //  
  /  
   
  #include   "stdafx.h"  
  #include   "APIHook_Dll.h"  
   
  #include    
  #include    
   
  #pragma   comment(lib,"ImageHlp")   //定义全局共享数据段  
   
  #pragma   data_seg("Shared")  
  HMODULE   hmodDll=NULL;  
  HHOOK   hHook=NULL;  
   
  #pragma   data_seg()  
   
  #pragma   comment(linker,"/Section:Shared,rws")   //设置全局共享数据段的属性  
   
  /   DllMain   函数   /  
  //dll的入口点  
  BOOL   APIENTRY   DllMain(   HMODULE   hModule,    
                                                DWORD     ul_reason_for_call,    
                                                LPVOID   lpReserved  
              )  
  {  
    switch(ul_reason_for_call)  
    {  
    case   DLL_PROCESS_ATTACH:  
      //if(sHook)      
       
    case   DLL_PROCESS_DETACH:  
      UnInstallHook();  
      break;  
    }  
    hmodDll=hModule;  
          return   TRUE;  
  }  
   
  /   HookOneAPI   函数   /  
  //进行IAT转换的关键函数,其参数含义:  
  //pszCalleeModuleName:需要hook的模块名  
  //pfnOriginApiAddress:要替换的自己API函数的地址  
  //pfnDummyFuncAddress:需要hook的模块名的地址  
  //hModCallerModule:我们要查找的模块名称,如果没有被赋值,  
  //           将会被赋值为枚举的程序所有调用的模块  
   
  void   WINAPI   HookOneAPI(LPCTSTR   pszCalleeModuleName,PROC   pfnOriginApiAddress,    
                  PROC   pfnDummyFuncAddress,HMODULE   hModCallerModule)  
  {  
    ULONG   size;  
   
    //获取指向PE文件中的Import中IMAGE_DIRECTORY_DESCRIPTOR数组的指针  
   
    PIMAGE_IMPORT_DESCRIPTOR   pImportDesc   =   (PIMAGE_IMPORT_DESCRIPTOR)  
      ImageDirectoryEntryToData(hModCallerModule,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);  
   
    if   (pImportDesc   ==   NULL)  
      return;  
   
    //查找记录,看看有没有我们想要的DLL  
   
    for   (;pImportDesc->Name;pImportDesc++)  
    {  
      LPSTR   pszDllName   =   (LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);  
      if   (lstrcmpiA(pszDllName,pszCalleeModuleName)   ==   0)  
        break;  
    }  
   
    if   (pImportDesc->Name   ==   NULL)  
    {  
      return;  
    }  
   
    //寻找我们想要的函数  
   
    PIMAGE_THUNK_DATA   pThunk   =    
      (PIMAGE_THUNK_DATA)((PBYTE)hModCallerModule+pImportDesc->FirstThunk);//IAT  
    for   (;pThunk->u1.Function;pThunk++)  
    {  
      //ppfn记录了与IAT表项相应的函数的地址  
   
      PROC   *   ppfn=   (PROC   *)&pThunk->u1.Function;      
      if   (*ppfn   ==   pfnOriginApiAddress)    
      {  
        //如果地址相同,也就是找到了我们想要的函数,进行改写,将其指向我们所定义的函数  
   
        WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnDummyFuncAddress),  
          sizeof(pfnDummyFuncAddress),NULL);  
        return;  
      }  
    }  
  }  
   
  //查找所挂钩的进程所应用的dll模块的  
   
  BOOL   WINAPI   HookAllAPI(LPCTSTR   pszCalleeModuleName,PROC   pfnOriginApiAddress,  
                  PROC   pfnDummyFuncAddress,HMODULE   hModCallerModule)  
  {  
    if   (pszCalleeModuleName   ==   NULL)  
    {  
      return   FALSE;  
    }  
    if   (pfnOriginApiAddress   ==   NULL)  
    {  
      return   FALSE;  
    }  
    //如果没传进来要挂钩的模块名称,枚举被挂钩进程的所有引用的模块,  
    //并对这些模块进行传进来的相应函数名称的查找  
     
    if   (hModCallerModule   ==   NULL)  
    {  
      MEMORY_BASIC_INFORMATION   mInfo;  
      HMODULE   hModHookDLL;  
      HANDLE   hSnapshot;  
      MODULEENTRY32   me   =   {sizeof(MODULEENTRY32)};  
      //MODULEENTRY32:描述了一个被指定进程所应用的模块的struct  
   
      VirtualQuery(HookOneAPI,&mInfo,sizeof(mInfo));  
      hModHookDLL=(HMODULE)mInfo.AllocationBase;  
       
      hSnapshot   =   CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);  
      BOOL   bOk   =   Module32First(hSnapshot,&me);  
      while   (bOk)  
      {  
        if   (me.hModule   !=   hModHookDLL)  
        {  
          hModCallerModule   =   me.hModule;//赋值  
          //me.hModule:指向当前被挂钩进程的每一个模块    
          HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,  
            pfnDummyFuncAddress,hModCallerModule);  
        }  
        bOk   =   Module32Next(hSnapshot,&me);  
      }  
      return   TRUE;      
    }  
    //如果传进来了,进行查找  
    else  
    {  
      HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,  
          pfnDummyFuncAddress,hModCallerModule);  
      return   TRUE;  
    }  
    return   FALSE;  
  }  
   
    UnhookAllAPIHooks   函数   /  
  //通过使pfnDummyFuncAddress与pfnOriginApiAddress相等的方法,取消对IAT的修改  
  BOOL   WINAPI   UnhookAllAPIHooks(LPCTSTR   pszCalleeModuleName,PROC   pfnOriginApiAddress,  
                    PROC   pfnDummyFuncAddress,HMODULE   hModCallerModule)  
  {  
    PROC   temp;  
    temp   =   pfnOriginApiAddress;  
    pfnOriginApiAddress   =   pfnDummyFuncAddress;  
    pfnDummyFuncAddress   =   temp;  
    return   HookAllAPI(pszCalleeModuleName,pfnOriginApiAddress,  
      pfnDummyFuncAddress,hModCallerModule);  
  }  
   
  //   GetMsgProc   函数    
  //钩子子程。与其它钩子子程不大相同,没做什么有意义的事情,继续调用下一个钩子子程,形成循环  
  LRESULT   CALLBACK   GetMsgProc(int   code,WPARAM   wParam,LPARAM   lParam)  
  {  
    return   CallNextHookEx(hHook,code,wParam,lParam);  
  }  
   
    InstallHook   函数   /  
  //安装或卸载钩子,BOOL   IsHook参数是标志位  
  //对要钩哪个API函数进行初始化  
  //我们这里装的钩子类型是WH_GETMESSAGE  
  void   __declspec(dllexport)   WINAPI   InstallHook(BOOL   IsHook,DWORD   dwThreadId)  
  {  
    if(IsHook)  
    {  
    hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,hmodDll,dwThreadId);  
     
    //GetProcAddress(GetModuleHandle("GDI32.dll"),"ExtTextOutA"):取得要钩的函数在所在dll中的地址  
     
    HookAllAPI("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),  
      "TextOutW"),(PROC)&H_TextOutW,NULL);  
    HookAllAPI("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),  
      "TextOutA"),(PROC)&H_TextOutA,NULL);  
    }  
    else  
    {  
      UnInstallHook();  
      UnhookAllAPIHooks("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),  
        "TextOutW"),(PROC)&H_TextOutW,NULL);  
      UnhookAllAPIHooks("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),  
        "TextOutA"),(PROC)&H_TextOutA,NULL);  
    }  
  }  
   
  /   UnInstallHook   函数    
  //卸载钩子  
  BOOL   WINAPI   UnInstallHook()  
  {  
    UnhookWindowsHookEx(hHook);  
    return   TRUE;  
  }  
   
  /   H_TextOutA   函数   /  
  //我们的替换函数,可以在里面实现我们所要做的功能  
  //这里我做的是显示一个对话框,指明是替换了哪个函数  
  BOOL   WINAPI   H_TextOutA(HDC   hdc,int   nXStart,int   nYStart,LPCSTR   lpString,int   cbString)  
  {  
    MessageBox(NULL,"TextOutA","APIHook_Dll   ---rivershan",MB_OK);  
    TextOutA(hdc,nXStart,nYStart,lpString,cbString);//返回原来的函数,以显示字符  
    return   TRUE;  
  }  
   
  /   H_TextOutW   函数   /  
  //同上  
  BOOL   WINAPI   H_TextOutW(HDC   hdc,int   nXStart,int   nYStart,LPCWSTR   lpString,int   cbString)  
  {  
    MessageBox(NULL,"TextOutW","APIHook_Dll   ---rivershan",MB_OK);  
    TextOutW(hdc,nXStart,nYStart,lpString,cbString);//返回原来的函数,以显示字符  
    return   TRUE;  
  }

 

 

  APIHook_Dll.h    
  //                                                           rivershan写于2002.9.23                                                                     //  
  /  
   
  //dll头文件,用于声明函数  
   
  void   __declspec(dllexport)   WINAPI   InstallHook(BOOL,DWORD);  
  BOOL   WINAPI   UnInstallHook();  
  LRESULT   CALLBACK   GetMsgProC(int   code,WPARAM   wParam,LPARAM   lParam);  
   
  void   WINAPI   HookOneAPI(LPCTSTR   pszCalleeModuleName,PROC   pfnOriginApiAddress,  
                  PROC   pfnDummyFuncAddress,HMODULE   hModCallerModule);  
  BOOL   WINAPI   HookAllAPI(LPCTSTR   pszCalleeModuleName,PROC   pfnOriginApiAddress,  
                  PROC   pfnDummyFuncAddress,HMODULE   hModCallerModule);  
  BOOL   WINAPI   UnhookAllAPIHooks(LPCTSTR   pszCalleeModuleName,PROC   pfnOriginApiAddress,  
                    PROC   pfnDummyFuncAddress,HMODULE   hModCallerModule);  
   
  BOOL   WINAPI   H_TextOutA(HDC,   int,   int,   LPCSTR,   int);  
  BOOL   WINAPI   H_TextOutW(HDC,   int,   int,   LPCWSTR,   int);  
  BOOL   WINAPI   H_ExtTextOutA(HDC,   int,   int,   UINT,   CONST   RECT   *,LPCSTR,   UINT,   CONST   INT   *);  
  BOOL   WINAPI   H_ExtTextOutW(HDC,   int,   int,   UINT,   CONST   RECT   *,LPCWSTR,   UINT,   CONST   INT   *);  
   
  **********************************************************************************************  
  **********************************************************************************************  
   
  ;APIHook_Dll之def文件  
  LIBRARY   APIHook_Dll.dll  
  EXPORT  
    InstallHook  
     
  二、APIHOOK之exe部分  
   
    APIHook_EXEDlg.cpp   /  
  //                                                           rivershan写于2002.9.23                                                                     //  
  /  
   
   
  #include   "stdafx.h"  
  #include   "APIHook_EXE.h"  
  #include   "APIHook_EXEDlg.h"  
  #include   "APIHook_Dll.h"  
   
  #ifdef   _DEBUG  
  #define   new   DEBUG_NEW  
  #undef   THIS_FILE  
  static   char   THIS_FILE[]   =   __FILE__;  
  #endif  
   
  /  
  //   CAPIHook_EXEDlg   dialog  
   
  CAPIHook_EXEDlg::CAPIHook_EXEDlg(CWnd*   pParent   /*=NULL*/)  
  :   CDialog(CAPIHook_EXEDlg::IDD,   pParent)  
  {  
    //{{AFX_DATA_INIT(CAPIHook_EXEDlg)  
    //   NOTE:   the   ClassWizard   will   add   member   initialization   here  
    //}}AFX_DATA_INIT  
    //   Note   that   LoadIcon   does   not   require   a   subsequent   DestroyIcon   in   Win32  
    m_hIcon   =   AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
  }  
   
  void   CAPIHook_EXEDlg::DoDataExchange(CDataExchange*   pDX)  
  {  
    CDialog::DoDataExchange(pDX);  
    //{{AFX_DATA_MAP(CAPIHook_EXEDlg)  
    //   DDX_Control(pDX,   IDC_EDIT1,   m_Edit);  
    //}}AFX_DATA_MAP  
  }  
   
  BEGIN_MESSAGE_MAP(CAPIHook_EXEDlg,   CDialog)  
  //{{AFX_MSG_MAP(CAPIHook_EXEDlg)  
  ON_WM_PAINT()  
  ON_WM_QUERYDRAGICON()  
    ON_BN_CLICKED(IDC_BUTTON_OUT,   OnButtonOut)  
    ON_BN_CLICKED(IDC_BUTTON_BEGIN,   OnButtonBegin)  
    ON_BN_CLICKED(IDC_BUTTON_STOP,   OnButtonStop)  
    //}}AFX_MSG_MAP  
  END_MESSAGE_MAP()  
   
  /  
  //   CAPIHook_EXEDlg   message   handlers  
   
  BOOL   CAPIHook_EXEDlg::OnInitDialog()  
  {  
    CDialog::OnInitDialog();  
     
    //   Set   the   icon   for   this   dialog.     The   framework   does   this   automatically  
    //   when   the   application's   main   window   is   not   a   dialog  
    SetIcon(m_hIcon,   TRUE);       //   Set   big   icon  
    SetIcon(m_hIcon,   FALSE);     //   Set   small   icon  
     
    //   TODO:   Add   extra   initialization   here  
     
    return   TRUE;     //   return   TRUE     unless   you   set   the   focus   to   a   control  
  }  
   
  //   If   you   add   a   minimize   button   to   your   dialog,   you   will   need   the   code   below  
  //     to   draw   the   icon.     For   MFC   applications   using   the   document/view   model,  
  //     this   is   automatically   done   for   you   by   the   framework.  
   
  void   CAPIHook_EXEDlg::OnPaint()    
  {  
    if   (IsIconic())  
    {  
      CPaintDC   dc(this);   //   device   context   for   painting  
       
      SendMessage(WM_ICONERASEBKGND,   (WPARAM)   dc.GetSafeHdc(),   0);  
       
      //   Center   icon   in   client   rectangle  
      int   cxIcon   =   GetSystemMetrics(SM_CXICON);  
      int   cyIcon   =   GetSystemMetrics(SM_CYICON);  
      CRect   rect;  
      GetClientRect(&rect);  
      int   x   =   (rect.Width()   -   cxIcon   +   1)   /   2;  
      int   y   =   (rect.Height()   -   cyIcon   +   1)   /   2;  
       
      //   Draw   the   icon  
      dc.DrawIcon(x,   y,   m_hIcon);  
    }  
    else  
    {  
      CDialog::OnPaint();  
    }  
  }  
   
  //   The   system   calls   this   to   obtain   the   cursor   to   display   while   the   user   drags  
  //     the   minimized   window.  
  HCURSOR   CAPIHook_EXEDlg::OnQueryDragIcon()  
  {  
    return   (HCURSOR)   m_hIcon;  
  }  
  /   OnButtonOut   函数   //  
  //使用TextOut函数  
  void   CAPIHook_EXEDlg::OnButtonOut()    
  {  
    //   TODO:   Add   your   control   notification   handler   code   here  
    HDC   hdc   =   ::GetDC(GetSafeHwnd());  
    ::TextOutA(hdc,0,0,"APIHOOK_EXE   ---rivershan",30);  
    UpdateWindow();  
  }  
   
  /   OnButtonBegin   函数    
  //开始挂钩,这里我们挂的是自身这个APIHook_EXE这个程序  
  void   CAPIHook_EXEDlg::OnButtonBegin()  
  {  
    DWORD   dwThreadId   =   GetWindowThreadProcessId(m_hWnd,NULL);//获得自身进程ID  
    InstallHook(TRUE,dwThreadId);  
  }  
   
  /   OnButtonStop   函数    
  //取消挂钩  
  void   CAPIHook_EXEDlg::OnButtonStop()  
  {  
    InstallHook(FALSE,0);  
  }  
   
  三、APIHOOK之集成  
   
  1.   用   VC++新建一个   Win32   Dynamic-Link   Library   程序,命名为   APIHook_Dll。接下来选择第二项   A   Simple   DLL   Project;  
  2.   新建一头文件,命名为   APIHook_Dll.h。删除工程中   APIHook_Dll.cpp文件中原来的内容,然后把上面的   APIHook_Dll.cpp   和   APIHook_Dll.h文件的内容全部复制到新建的这个工程的   .cpp及   .h文件中来;  
  3.   新建一   Text文件,命名为   APIHook_Dll.def。复制上面的def文件内容。  
  4.   编译;  
  5.   新建一   MFC   APPWizard(exe)程序,命名为   APIHook_EXE。接着选择第三项,基于对话框的程序,其它默认;  
  6.   删除原来对话框上的控件,然后新建三个按钮ID分别为:IDC_BUTTON_BEGIN、IDC_BUTTON_STOP、IDC_BUTTON_OUT,Caption分别为:Bigin   Hook、Stop   Hook、Text   Out。不要让这三个按钮出于对话框客户区的最上面就行;  
  7.   拷贝   APIHook_Dll.h文件到   APIHook_EXE程序目录下,然后加到   APIHook_EXE的头文件夹中。  
  8.   删除工程中   APIHook_EXEDlg.cpp文件中原来的内容,然后把上面的   APIHook_EXEDlg.cpp文件的内容全部复制到新建的这个工程的   .cpp文件中来;  
  9.   打开   Project->Setting菜单,选择第四项link,在   Object/library   moduls里添加我们的dll的lib文件的路径:../APIHook_Dll/Debug/APIHook_Dll.lib;  
  10.   编译;  
  11.   把   APIHook_Dll.dll文件放在   APIHook_Dll.exe程序的同一个文件夹内;  
  12.   运行程序,点击   Bigin   Hook按钮,开始挂钩。再点击   Text   Out按钮会跳出对话框并且会在程序中显示所要显示的字。点击   Stop   Hook然后在点击   Text   Out按钮就没有对话框出现了。  
   
  四、一些说明  
   
  1、我这个   HookAPI是使用了   Jeffrey   Richter的改写程序的   IAT来实现的,也可以用跳转函数入口点的方法来实现,这个我没做研究。:)  
   
  2、我的一些心得:  
   
    所谓   HookAPI,就是改写程序的   IAT,再调用我自己写的用于替换原API函数的函数。在我们自己写的API函数中,我们可以进行我们想要的工作。之后呢,可以把原来的函数传回去,也可以不传回去,只要你设计好了就行。  
   
    而所谓调用自己的函数,就是把原函数参数都传给我的替换函数。我们就可以利用这些参数去干我们想做的事。而系统呢,我想由于微软设置的这个钩子的目的(我这么认为的),所以不会去检查替换函数是否就是原函数,只要参数、返回值符合条件就行,要不会出错。替换函数的返回值最好是原函数,否则有可能会出错  
   
    HookAPI时,exe程序起到的作用就是进行Hook,把dll注入到要Hook的程序,并且传回要挂接的进程的ID或者全局钩子,以便查询所要挂接的模块的IAT。如果不注入进去,系统不会让你去查询IAT的。DLL做的事情是确定要挂接哪个函数和这个函数在哪个DLL中等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目前最好的EasyHook的完整Demo程序,包括了Hook.dll动态库和Inject.exe注入程序。 Hook.dll动态库封装了一套稳定的下钩子的机制,以后对函数下钩子,只需要填下数组表格就能实现了,极大的方便了今后的使用。 Inject.exe是用MFC写的界面程序,只需要在界面上输入进程ID就能正确的HOOK上相应的进程,操作起来非常的简便。 这个Demo的代码风格也非常的好,用VS2010成功稳定编译通过,非常值得下载使用。 部分代码片段摘录如下: //【Inject.exe注入程序的代码片段】 void CInjectHelperDlg::OnBnClickedButtonInjectDllProcessId() { ////////////////////////////////////////////////////////////////////////// //【得到进程ID值】 UINT nProcessID = 0; if (!GetProcessID(nProcessID)) { TRACE(_T("%s GetProcessID 失败"), __FUNCTION__); return; } ////////////////////////////////////////////////////////////////////////// //【得到DLL完整路径】 CString strPathDLL; if (!GetDllFilePath(strPathDLL)) { TRACE(_T("%s GetDllFilePath 失败"), __FUNCTION__); return; } ////////////////////////////////////////////////////////////////////////// //【注入DLL】 NTSTATUS ntStatus = RhInjectLibrary(nProcessID, 0, EASYHOOK_INJECT_DEFAULT, strPathDLL.GetBuffer(0), NULL, NULL, 0); if (!ShowStatusInfo(ntStatus)) { TRACE(_T("%s ShowStatusInfo 失败"), __FUNCTION__); return; } } //【Hook.dll动态库的代码片段】 extern "C" __declspec(dllexport) void __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO* InRemoteInfo) { if (!DylibMain()) { TRACE(_T("%s DylibMain 失败"), __FUNCTION__); return; } } FUNCTIONOLDNEW_FRMOSYMBOL array_stFUNCTIONOLDNEW_FRMOSYMBOL[]= { {_T("kernel32"), "CreateFileW", (void*)CreateFileW_new}, {_T("kernel32"), "CreateFileA", (void*)CreateFileA_new}, {_T("kernel32"), "ReadFile", (void*)ReadFile_new} }; BOOL HookFunctionArrayBySymbol() { /////////////////////////////////////////////////////////////// int nPos = 0; do { /////////////////////////////// FUNCTIONOLDNEW_FRMOSYMBOL* stFunctionOldNew = &g_stFUNCTIONOLDNEW_FRMOSYMBOL[nPos]; if (NULL == stFunctionOldNew->strModuleName) { break; } /////////////////////////////// if (!HookFunctionBySymbol(stFunctionOldNew->strModuleName, stFunctionOldNew->strNameFunction, stFunctionOldNew->pFunction_New)) { TRACE(_T("%s HookFunctionBySymbol 失败"), __FUNCTION__); return FALSE; } } while(++nPos); /////////////////////////////////////////////////////////////// return TRUE; } HANDLE WINAPI CreateFileW_new( PWCHAR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ) { TRACE(_T("CreateFileW_new. lpFileName = %s"), lpFileName); return CreateFileW( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值