现在的位置: 首页 > 综合 > 正文

通过下全局API Hook修改IAT中函数地址为何截获不了Ws2_32.dll的recv()

2014年09月05日 ⁄ 综合 ⁄ 共 6105字 ⁄ 字号 评论关闭
(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)   
     {   
  HANDLE   hFile;   
    
  if((hFile   =CreateFile("c://MessageBoxA1.log",   GENERIC_WRITE,   0,   NULL,   OPEN_ALWAYS,   FILE_ATTRIBUTE_NORMAL,   NULL))   <0)   
  {   
  WriteLog("open   file   %s   failed",   fname);   
  return   -1;   
  }   
  _llseek((HFILE)hFile,   0,   SEEK_END);   
  char   temp[2048];   
  wsprintf(temp,   "/r/n(LPCTSTR   lpText%s,   LPCTSTR   lpCaption%s)   ",     lpText,lpCaption);   
  DWORD   dw;   
  WriteFile(hFile,   temp,   strlen(temp),   &dw,   NULL);   
    
  _lclose((HFILE)hFile);   
      //过滤掉原MessageBoxA的正文和标题内容,只显示如下内容。   
  return   MessageBox(hWnd,   "Hook   API   OK!",   "Hook   API",   uType);     
     }     
     static   int   WINAPI   recv1(SOCKET   s,   char   FAR   *buf,   int   len,   int   flags   )   
     {   
     HANDLE   hFile;   
    
  if((hFile   =CreateFile("c://recv1.log",   GENERIC_WRITE,   0,   NULL,   OPEN_ALWAYS,   FILE_ATTRIBUTE_NORMAL,   NULL))   <0)   
  {   
  WriteLog("open   file   %s   failed",   fname);   
  return   -1;   
  }   
  _llseek((HFILE)hFile,   0,   SEEK_END);   
  char   temp[2048];   
  wsprintf(temp,   "/r/n(len=%d)   ",     len);   
  DWORD   dw;   
  WriteFile(hFile,   temp,   strlen(temp),   &dw,   NULL);   
    
    
  for(int   i   =0;   i<len;   i++)   
  {   
    
          wsprintf(temp,   "(%02x)",   buf[i]&0x00FF);   
  WriteFile(hFile,   temp,   strlen(temp),   &dw,   NULL);   
  }   
  _lclose((HFILE)hFile);   
    
    
    
    
     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]);   
     }   
     ......       
  我在recv1()里写了个截获数据并保存到c:/recv1.log的代码,但运行后没有截获到目标程序的数据。   
  而同样的代码却在MessageBoxA1()中运行正常,我发现目标程序被钩住后,一调用MessageBoxA就被截获,并纪录在c:/recv1.log   
    
  请大虾指点,为何截获不到recv()?   




win2000下企图使用IAT方法勾到Recv   |   WSARecv   是非常不现实的。为此我已经尝试了3天了。原因是启用WSAStartup的时候,就要进行hModule(hInstance)的检查。   
  目前我觉得比较现实的方法:   
    
  1,写一个fake   WS2_32.dll(把握较大)   
  2,使用ZWOpenfile来打开//Device//Tcp(Udp),然后进行进程对比,获取当前进程所有的Socket   handle,然后搞花样。   
  3,使用packet.dll(winpcap上去找),使用PacketRecivePacket。这样就比较丢脸了,做的程序还要加上别人的一个packet.dll。   
  4,如同arcnode(小二哥)   同志所言,直接找到Recv/WSARecv的地址,在里面找空位置JMP到自己函数的地址,执行完自己的代码后再JMP回去。须汇编功底,我可干不了:(   
    
  密切关注!有进展彼此分享一下,应当不介意吧?   



又注:WPE   (window   packet   editor)就做到了!我察看了他所用的dll调用,基本判断他是用IAT的方法完成的。不理解!


recv函数不是在ws2_32.dll中吧,应该在wsock.dll中的

抱歉!评论已关闭.