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

wf821229 2010-05-26 10:39:52
通过下全局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()?





...全文
404 点赞 收藏 7
写回复
7 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
aiwnx 2011-04-01
使用调试器(如windbg)在Ws2_32.dll的recv()处下断点,看看能不能断下来,再根据结果来判断是由于程序的问题还是由于根本就没有调用该API的问题。找到问题所在就好办了
回复
huodeming 2011-03-31
我用C#.NET2008成功HOOK SEND RECV 但怪的事出来了 RECV收到的TCP包都是BYTE[65536] 其实一切正常,被HOOK的程序也运行很正常
回复
jason176374 2010-05-27
你把api[0]设成RECV试一试?

另外,SOCKET函数HOOK的话似乎没见过用APIHOOK的,
SOCKET机制里面有一个SPI,专门过滤SOCKET函数的,不过我也只是
在书上看过这个技术,没有自己做过。
回复
悟迟 2010-05-27
帮你顶顶吧
回复
wf821229 2010-05-27
怎么没人帮我顶下呢?高手都那里去了
回复
norsd 2010-05-27
直接修改跳转地址才是王道.
回复
wf821229 2010-05-27

谢谢jason176374 ,wozhaolala,我把api[0]设成RECV还是不行!
是不是修改IAT中函数地址为何截获不了SOCKET函数??
但是网上好多人说可以但是没例子
回复
相关推荐
发帖
进程/线程/DLL
创建于2007-09-28

1.5w+

社区成员

VC/MFC 进程/线程/DLL
申请成为版主
帖子事件
创建了帖子
2010-05-26 10:39
社区公告
暂无公告