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

darkway 2003-12-23 02:15:27
但我在2000/XP/2003下试过确实可以用这种方法截获MessageBoxA,几乎所有的MessageBoxA都可以截获到。
请成功截获过的大虾赐教!!
...全文
234 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
softice2002 2004-02-22
  • 打赏
  • 举报
回复
recv函数不是在ws2_32.dll中吧,应该在wsock.dll中的
sakurako 2004-02-21
  • 打赏
  • 举报
回复
你好啊,搂主,我也想学习一下,如果能发一份代码到我的邮箱里,小弟不胜感激
sonic17@163.com
最后,衷心祝福搂主早日完成作品
rimren 2004-02-12
  • 打赏
  • 举报
回复
你好,能给我一份完整的代码学习吗?我也想学习截取send与recv,请帮帮我!谢谢你!
我的信箱是rimren@126.com 谢谢!
oknight 2003-12-27
  • 打赏
  • 举报
回复
关注: oknight@21cn.com
glacierrr 2003-12-26
  • 打赏
  • 举报
回复
好啊
jackwuwei 2003-12-26
  • 打赏
  • 举报
回复
是在做那个外挂吗?呵呵,那个代码不全,前不久帮人把那个在画图里画‘R’的代码搞定,那东西我也看过,讲得太粗了,等有时间再帮你做一下。
darkway 2003-12-26
  • 打赏
  • 举报
回复
http://research.microsoft.com/sn/detours/
Detours is a library for instrumenting arbitrary Win32 functions on x86 machines. Detours intercepts Win32 functions by re-writing target function images.

上面这个是微软的开发者作的,可以参考。我还没来得及看铁锅来共享先!
darkway 2003-12-26
  • 打赏
  • 举报
回复
通过两天的努力,已经可以通过修改函数入口点地址来达到目的。但在VC IDE里不好调试,因为VC会在内存里插入许多int 3 ,结果搞的修改后的函数地址偏移老是出问题,如果需要源代码,请留下mail.
这里有篇文章也是讲述这一技术:http://nocturnalnetwork.com/redirect.htm
欢迎大家就这个技术作进一步探讨。
wangii 2003-12-25
  • 打赏
  • 举报
回复
又注:WPE (window packet editor)就做到了!我察看了他所用的dll调用,基本判断他是用IAT的方法完成的。不理解!
wangii 2003-12-25
  • 打赏
  • 举报
回复
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回去。须汇编功底,我可干不了:(

密切关注!有进展彼此分享一下,应当不介意吧?
wangii 2003-12-25
  • 打赏
  • 举报
回复
下文是Delphi TeamB关于此问题的看法:

Well, my bet is that there are no hooks to enable you to do this.
Yes, you should be able to use Delphi.

Actually, your best bet would be the network card, I think. I know
some network cards can be placed into permiscous mode so that they see
every packet on the network. I have used this to develop a simple
network analyzer in the past. I don't remember exactly what I did but
there is a hook that you can grab that will call you for every packet.
Keep in mind I did this with Delphi 1, however, so it may have been a
hardware interrupt or such. But that may help.

As for writing a replacement winsock dll, it should be possible. I
know there are 3rd party winsock implementations you can buy. There
may even be one out there that supports what you are looking for.
Actually, depending on your exact needs you may be able to use the new
Microsoft V-LAN software to estabulish encrypted links. But that
would probably only work if all your clients are remote and not on the
same physical network. But if I was you I'd look check to see if
there were hooks in winsock 2 or if there was a 3rd party winsock
vendor who supplied hooks.

Bingo. I just remembered that the hook I was using was supplied by
Trumpet winsock. I don't know if it is still around but you may be
able to get a copy of it. Don't know if they ever made a winsock 2
version though.

Your best bet is to see if someone has created a public
domain/shareware winsock implementation that you can somehow get
source code to.

As for creating a layered service provider where they call your
winsock dll and then you call the real winsock I believe you will have
problems with that one. Just a gut feeling really, but you would have
to rename the real winsock dll and it may have other dlls that it uses
or who knows what. But I think you would have more trouble with that
then just creating your own winsock dll.

Good luck. Oh, and if you do happen to find source to a winsock
implementation could you post that information on here. I'm sure
people would be interested.

darkway 2003-12-24
  • 打赏
  • 举报
回复
(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()?
darkway 2003-12-24
  • 打赏
  • 举报
回复
楼上大虾们能给个直接修改函数跳转hook的实例吗?
arcnode 2003-12-24
  • 打赏
  • 举报
回复
不要用修改IAT方式hook,直接修改函数跳转hook,100%没有问题,不过此法在win9x下不行。
darkway 2003-12-24
  • 打赏
  • 举报
回复
再顶!又沉了
danfeng 2003-12-23
  • 打赏
  • 举报
回复
是啊 原理上是没有问题的 你没有截获成功只能是你程序的原因了
你发一份截获MessageBoxA的代码来我的邮箱
我帮你看看
smilingky@263.net
darkway 2003-12-23
  • 打赏
  • 举报
回复
up
Semigod 2003-12-23
  • 打赏
  • 举报
回复
没代码谁都帮不了你

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧