通过下全局API Hook修改IAT中函数地址为何截获不了Ws2_32.dll的recv()
(2)   在ActiveKey.h文件中加入HOOKAPI结构,此结构用来存储被挡截API函数名称、原API函数地址和替代函数地址。   
    
     typedef   struct   tag_HOOKAPI     
     {     
     LPCSTR   szFunc;//被HOOK的API函数名称。   
     PROC   pNewProc;//替代函数地址。   
     PROC   pOldProc;//原API函数地址。   
     }HOOKAPI,   *LPHOOKAPI;       
    
    (3)   打开ActiveKey.cpp文件,首先加入一个函数,用于定位输入库在输入数据段中的IAT地址。代码如下:   
    
     extern   "C"   __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR     
     LocationIAT(HMODULE   hModule,   LPCSTR   szImportMod)     
     //其中,hModule为进程模块句柄;szImportMod为输入库名称。   
     {     
     //检查是否为DOS程序,如是返回NULL,因DOS程序没有IAT。   
     PIMAGE_DOS_HEADER   pDOSHeader   =   (PIMAGE_DOS_HEADER)   hModule;     
     if(pDOSHeader->e_magic   !=   IMAGE_DOS_SIGNATURE)   return   NULL;     
      //检查是否为NT标志,否则返回NULL。   
      PIMAGE_NT_HEADERS   pNTHeader   =   (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+   (DWORD)(pDOSHeader->e_lfanew));     
      if(pNTHeader->Signature   !=   IMAGE_NT_SIGNATURE)   return   NULL;     
      //没有IAT表则返回NULL。   
      if(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress   ==   0)   return   NULL;     
      //定位第一个IAT位置。     
      PIMAGE_IMPORT_DESCRIPTOR   pImportDesc   =   (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader   +   (DWORD)(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));     
      //根据输入库名称循环检查所有的IAT,如匹配则返回该IAT地址,否则检测下一个IAT。   
      while   (pImportDesc->Name)     
      {     
       //获取该IAT描述的输入库名称。   
     PSTR   szCurrMod   =   (PSTR)((DWORD)pDOSHeader   +   (DWORD)(pImportDesc->Name));    
     if   (stricmp(szCurrMod,   szImportMod)   ==   0)   break;     
     pImportDesc++;     
      }     
      if(pImportDesc->Name   ==   NULL)   return   NULL;     
     return   pImportDesc;     
     }     
    
    再加入一个函数,用来定位被挡截API函数的IAT项并修改其内容为替代函数地址。代码如下:   
    
     extern   "C"   __declspec(dllexport)     
     HookAPIByName(   HMODULE   hModule,   LPCSTR   szImportMod,   LPHOOKAPI   pHookApi)     
     //其中,hModule为进程模块句柄;szImportMod为输入库名称;pHookAPI为HOOKAPI结构指针。   
     {     
      //定位szImportMod输入库在输入数据段中的IAT地址。   
      PIMAGE_IMPORT_DESCRIPTOR   pImportDesc   =   LocationIAT(hModule,   szImportMod);     
    if   (pImportDesc   ==   NULL)   return   FALSE;     
      //第一个Thunk地址。   
      PIMAGE_THUNK_DATA   pOrigThunk   =   (PIMAGE_THUNK_DATA)((DWORD)hModule   +   (DWORD)(pImportDesc->OriginalFirstThunk));     
       //第一个IAT项的Thunk地址。   
      PIMAGE_THUNK_DATA   pRealThunk   =   (PIMAGE_THUNK_DATA)((DWORD)hModule   +   (DWORD)(pImportDesc->FirstThunk));     
      //循环查找被截API函数的IAT项,并使用替代函数地址修改其值。   
     while(pOrigThunk->u1.Function)     
  {     
   //检测此Thunk是否为IAT项。   
  if((pOrigThunk->u1.Ordinal   &   IMAGE_ORDINAL_FLAG)   !=   IMAGE_ORDINAL_FLAG)     
  {   
      //获取此IAT项所描述的函数名称。   
   PIMAGE_IMPORT_BY_NAME   pByName   =(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk->u1.AddressOfData));     
   if(pByName->Name[0]   ==   '\0')   return   FALSE;     
    //检测是否为挡截函数。   
  if(strcmpi(pHookApi->szFunc,   (char*)pByName->Name)   ==   0)     
      {     
         MEMORY_BASIC_INFORMATION   mbi_thunk;   
         //查询修改页的信息。   
         VirtualQuery(pRealThunk,   &mbi_thunk,   sizeof(MEMORY_BASIC_INFORMATION));     
  //改变修改页保护属性为PAGE_READWRITE。   
         VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,   PAGE_READWRITE,   &mbi_thunk.Protect);     
  //保存原来的API函数地址。   
          if(pHookApi->pOldProc   ==   NULL)     
  pHookApi->pOldProc   =   (PROC)pRealThunk->u1.Function;     
      //修改API函数IAT项内容为替代函数地址。   
  pRealThunk->u1.Function   =   (PDWORD)pHookApi->pNewProc;     
  //恢复修改页保护属性。   
  DWORD   dwOldProtect;     
         VirtualProtect(mbi_thunk.BaseAddress,   mbi_thunk.RegionSize,   mbi_thunk.Protect,   &dwOldProtect);     
          }     
  }     
      pOrigThunk++;     
      pRealThunk++;     
  }     
    SetLastError(ERROR_SUCCESS);   //设置错误为ERROR_SUCCESS,表示成功。   
    return   TRUE;     
     }       
    
    (4)   定义替代函数,此实例中只给MessageBoxA和recv两个API进行挡截。代码如下:   
    
     static   int   WINAPI   MessageBoxA1   (HWND   hWnd   ,   LPCTSTR   lpText,   LPCTSTR   lpCaption,   UINT   uType)   
     {   
    return   MessageBox(hWnd,   "Hook   API   OK!",   "Hook   API",   uType);     
     }     
     static   int   WINAPI   recv1(SOCKET   s,   char   FAR   *buf,   int   len,   int   flags   )   
     {   
       
       MessageBox(NULL,"intercept recv success!","recv",MB_OK);  
    
     return   recv(s,buf,len,flags);   
     }       
    
  (5)   在KeyboardProc函数中加入激活挡截API代码,在if(   wParam   ==   0X79   )语句中后面加入如下else   if语句:   
    
     ......   
     //当激活F11键时,启动挡截API函数功能。   
     else   if(   wParam   ==   0x7A   )   
     {     
      HOOKAPI   api[2];   
  api[0].szFunc   ="MessageBoxA";//设置被挡截函数的名称。   
  api[0].pNewProc   =   (PROC)MessageBoxA1;//设置替代函数的地址。   
  api[1].szFunc   ="recv";//设置被挡截函数的名称。   
  api[1].pNewProc   =   (PROC)recv1;   //设置替代函数的地址。   
  //设置挡截User32.dll库中的MessageBoxA函数。   
  HookAPIByName(GetModuleHandle(NULL),"User32.dll",&api[0]);   
  //设置挡截Wsock32.dll库中的recv函数。   
  HookAPIByName(GetModuleHandle(NULL),"Ws2_32.dll",&api[1]);   
     }   
     ......       
  recv拦截成功应该出现“intercept recv success!”对话框,但运行后没有截获到目标程序的数据。   
  而同样的代码却在MessageBoxA1()中运行正常,我发现目标程序被钩住后,一调用MessageBoxA就被截获   
  测试程序是我自己编的是调用了 Ws2_32.dll的recv函数排除了因为可能调用的Wsock32.dll里的recv函数
调试几天都没调出来,本人刚接触api拦截,请大虾指点,为何截获不到recv()?   
  

解决方案 »

  1.   

    你把api[0]设成RECV试一试?另外,SOCKET函数HOOK的话似乎没见过用APIHOOK的,
    SOCKET机制里面有一个SPI,专门过滤SOCKET函数的,不过我也只是
    在书上看过这个技术,没有自己做过。
      

  2.   

     
    谢谢jason176374 ,wozhaolala,我把api[0]设成RECV还是不行!
    是不是修改IAT中函数地址为何截获不了SOCKET函数??
    但是网上好多人说可以但是没例子
      

  3.   

    我用C#.NET2008成功HOOK SEND RECV 但怪的事出来了  RECV收到的TCP包都是BYTE[65536] 其实一切正常,被HOOK的程序也运行很正常
      

  4.   

    使用调试器(如windbg)在Ws2_32.dll的recv()处下断点,看看能不能断下来,再根据结果来判断是由于程序的问题还是由于根本就没有调用该API的问题。找到问题所在就好办了