我是通过修改模块的导入表来实现挂send函数的钩子的,用的是《windows内核编程》第22章中的ReplaceIATEntryInOneMod函数,但实际测试的时候,发现并没有产生希望的效果,自定义的MySend函数并没有被调用。仔细思考了一下,也没想出来是什么原因,代码如下:
这是Dll的代码,由另一个exe注入到目标IE进程中。
#include<Winsock2.h>
#include<Dbghelp.h>
#include<Tlhelp32.h>
#pragma comment(lib,"Dbghelp.lib")#define OUT_ERROR(x) MessageBox(NULL,x,x,0)#pragma data_seg("MySec")HMODULE hModule=0;#pragma data_seg()
#pragma comment(linker,"/section:MySec,RWS")DWORD WINAPI MainThread(LPVOID);BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID)
{
if(dwReason==DLL_PROCESS_ATTACH)
{
hModule=hInstance;
CreateThread(NULL,0,MainThread,NULL,0,NULL);
}
return TRUE;
}BOOL ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, //API所在的Dll文件的名字。
PROC pfnCurrent, //当前的API地址
 PROC pfnNew, //新的API地址
 HMODULE hmodCaller) //要挂钩子的模块
{
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc= (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(hmodCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
if(pImportDesc==NULL)
{
//OUT_ERROR("目标模块的导入表为空");
return FALSE;
}
for(;pImportDesc->Name;pImportDesc++)
{
PSTR pszModName = (PSTR) 
((PBYTE)hmodCaller+pImportDesc->Name);
if(lstrcmpiA(pszModName, pszCalleeModName)==0)
break;
}

if(pImportDesc->Name==0)
{
//OUT_ERROR("Can't Find The Module");
return FALSE;
}
PIMAGE_THUNK_DATA pThunk=(PIMAGE_THUNK_DATA)
((PBYTE)hmodCaller+pImportDesc->FirstThunk);
for(; pThunk->u1.Function;pThunk++)
{
PROC* ppfn=(PROC*)&pThunk->u1.Function;
BOOL fFound=(*ppfn==pfnCurrent);
        if(fFound)
{
/*char b[100];
wsprintf(b,"%d",ppfn);
OUT_ERROR(b);*/
DWORD dwOldProtect=0;
if(!VirtualProtect(ppfn,4,PAGE_READWRITE,&dwOldProtect))
{
char b[100];
wsprintf(b,"改变内存页面属性失败!错误代码:%d",GetLastError());
OUT_ERROR(b);
};
if(!WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnNew,sizeof(pfnNew),NULL))
{
char b[100];
wsprintf(b,"写内存失败!错误代码:%d",GetLastError());
OUT_ERROR(b);
};
VirtualProtect(ppfn,4,dwOldProtect,0);
char buf[100];
wsprintf(buf,"原地址为:%x,现地址为:%x",pfnCurrent,pThunk->u1.Function);
//OUT_ERROR(buf);
return TRUE;
}
}
//OUT_ERROR("Can't Find The Function");
return FALSE;
}typedef int (__stdcall* fnSend)(SOCKET,const char*,int,int); //这一段是为send函数做的
fnSend OrigSend=0; //原函数入口地址
int __stdcall MySend(SOCKET s,const char FAR * buf,int len,int flags) //我的函数
{
MessageBox(NULL,buf,buf,0);
return OrigSend(s,buf,len,flags);
}DWORD WINAPI MainThread(LPVOID)
{
BOOL bRet = FALSE; 
BOOL bFound = FALSE; 
HANDLE hModuleSnap = NULL; 
MODULEENTRY32 me32 = {0};  hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());  if (hModuleSnap == INVALID_HANDLE_VALUE) 
{
OUT_ERROR("无法创建映像");
} me32.dwSize = sizeof(MODULEENTRY32); 
////////////////////
OrigSend=
(fnSend)GetProcAddress(GetModuleHandle("ws2_32.dll"),"send"); if (Module32First(hModuleSnap, &me32)) 
{
do 
{
if(me32.hModule==hModule)
continue;
if(!ReplaceIATEntryInOneMod("ws2_32.dll",(PROC)OrigSend,(PROC)MySend,me32.hModule))
{

}
else
{
char bb[100];
wsprintf(bb,"在%s中替换send函数成功",me32.szModule);
OUT_ERROR(bb); } while (Module32Next(hModuleSnap, &me32)); 
}
else
{
OUT_ERROR("无法查找");
}
CloseHandle (hModuleSnap); 
return (bRet); 
}

解决方案 »

  1.   

    是否找到send函数并成功替换?
    自己写个简单的socket程序,看dll能否成功替换send?
      

  2.   

    对,先是测试了自己写的socket程序,能成功替换,才到IE中测试,却失败了。
      

  3.   

    send 是属于WinSock V1.X的 
    IE使用的API基本是WinSock V2.X, 如WSASend, WSASendTo你Hook 版本V2.X 的函数才可以
      

  4.   

    回复楼上:
    我也钩了WSASendTo、WSASend等函数,也没用……
    为了简洁,我没把钩WSASendTo、WSASend函数的代码贴出来
      

  5.   

    HOOK API 你首先要确定目标程序确实是用了这个API!对于网络通讯,并不全是用SOCKET来做的。建议你再HOOK一个函数:WriteFile。兴许这个可以。
      

  6.   

    确定iat里面找到了你要替换的函数吗?如果其使用的LoadLibrary GetAddr...方式,iat里面是没有对应dll还函数的
      

  7.   

    谢谢楼上,我试试
    但是我想,对于IE来说,它不太会去调用WriteFile去做网络通讯的事情吧?
      

  8.   

    也可以试试hook LoadLibrary这样的函数,看是否动态加载了像ws2_32.dll这样的关键dll
      

  9.   

    回复9楼。我可以确认的是,只是在个别的几个加载到IE中的模块的IAT里找到了这个函数。我也怀疑LoadLibrary和GetProcAddress,就挂了它们的钩子,到末了只发现IE在初始化,即调用WSAStartup函数时,它才用GetProcAddress函数去Get send函数的地址。挂了LoadLibraryA和LoadLibraryW,没发现有哪个线程调用过这两个函数。
      

  10.   

    刚才仔细检查了一下,发现所有模块的LoadLibraryA、LoadLibraryW、LoadLibraryExA、LoadLibraryExW都没有被替换成功,似乎是没在IAT中找到这几个函数,连IEXPLORE.EXE中都没找到。而我用Dumpbin看过,Iexplore.exe确实导入了LoadLibraryA。怪事。