我是通过修改模块的导入表来实现挂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);
}
这是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);
}
解决方案 »
- Qt中用OpenGL绘图,贴纹理的问题。
- 线程的问题
- 关于ListControl,,,乱码
- 我有个程序希望集成进QQ,比如在QQ的控制面板上加个按钮,不知道QQ有没公开的插件api?
- 关于制作断点的问题?
- 一个关于捕获键盘消息的策略??!!
- 请问如何将内存中存储的一个内存地址[如36fb4000,即0x0040fb36]读成一个真正的内存地址,赋给一个LPBYTE
- 一个单机版的VC数据库程序在作成安装程序之前竟包含的文件有哪些?在先等
- 求教:怎样做出不规则形状按钮(按照位图图案),急!
- WaitForSingleObjects()检测无信号时,是不是自动放弃CPU?
- RegSetValueEx的参数问题
- 【WinXP】下怎样用自己写的程序旋转显示器方向
自己写个简单的socket程序,看dll能否成功替换send?
IE使用的API基本是WinSock V2.X, 如WSASend, WSASendTo你Hook 版本V2.X 的函数才可以
我也钩了WSASendTo、WSASend等函数,也没用……
为了简洁,我没把钩WSASendTo、WSASend函数的代码贴出来
但是我想,对于IE来说,它不太会去调用WriteFile去做网络通讯的事情吧?