我做了一个api hook,想在系统范围内钩住所有进程对ws2_32里面的wsaSend函数的调用。dll插入没问题,问题出在api hook的安装上面,代码如下:
void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,
PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
ULONG size;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(hModCallerModule,TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
if (pImportDesc == NULL)
return;
for (;pImportDesc->Name;pImportDesc++)
{
LPSTR pszDllName = (LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);
if (!lstrcmpiA(pszDllName,pszCalleeModuleName))
{
break;
}
}
if (pImportDesc->Name == NULL)
{
return;
}
PIMAGE_THUNK_DATA pThunk =(PIMAGE_THUNK_DATA)
((PBYTE)hModCallerModule+pImportDesc->FirstThunk);
for (;pThunk->u1.Function;pThunk++)
{
PROC * ppfn= (PROC *)&pThunk->u1.Function;
if (*ppfn==pfnOriginApiAddress)
{
DWORD dwOldProtect;
VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnDummyFuncAddress,
sizeof(pfnDummyFuncAddress),NULL);
VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),dwOldProtect,0);
return;
}
}
}
BOOL WINAPI HookAllAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,
PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
if (pszCalleeModuleName == NULL)
{
return FALSE;
}
if (pfnOriginApiAddress == NULL)
{
return FALSE;
}
if (hModCallerModule == NULL)
{
MEMORY_BASIC_INFORMATION mInfo;
HMODULE hModHookDLL;
HANDLE hSnapshot;
MODULEENTRY32 me;
me.dwSize=sizeof(MODULEENTRY32);
VirtualQuery(HookOneAPI,&mInfo,sizeof(mInfo));
hModHookDLL=(HMODULE)mInfo.AllocationBase;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
BOOL bOk = Module32First(hSnapshot,&me);
while (bOk)
{
if (me.hModule != hModHookDLL)
{
hModCallerModule = me.hModule;
HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,
pfnDummyFuncAddress,hModCallerModule);
}
bOk = Module32Next(hSnapshot,&me);
}
return TRUE;
}
else
{
HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,
pfnDummyFuncAddress,hModCallerModule);
return TRUE;
}
return FALSE;
}
void InstallApiHooks(BOOL IsHook)
{
if (IsHook)
{
HookAllAPI("WS2_32.dll",GetProcAddress(GetModuleHandle("ws2_32.dll"),
"WSASend"),(PROC)&NewWsaSend,NULL);
}
else
{
UnhookAllAPI("WS2_32.dll",GetProcAddress(GetModuleHandle("ws2_32.dll"),
"WSASend"),(PROC)&NewWsaSend,NULL);
}
}int NewWsaSend(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE)
{
char szFileName[64];
GetModuleFileName(GetModuleHandle(NULL),szFileName,64);
int ret=100;
ret=WSASend(s,lpBuffers,dwBufferCount,lpNumberOfBytesSent,
dwFlags,lpOverlapped,lpCompletionROUTINE);
char szBytesOfSend[20];
wsprintf(szBytesOfSend,"Send %d Bytes",ret);
MessageBox(NULL,lpBuffers->buf,szFileName,MB_OK);
return ret; //问题出在这里,能够显示出调用者传递给它的 lpBuffers ,但返回时目标进程报错,原因是某个内存地址为只读。
}
void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,
PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
ULONG size;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(hModCallerModule,TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
if (pImportDesc == NULL)
return;
for (;pImportDesc->Name;pImportDesc++)
{
LPSTR pszDllName = (LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);
if (!lstrcmpiA(pszDllName,pszCalleeModuleName))
{
break;
}
}
if (pImportDesc->Name == NULL)
{
return;
}
PIMAGE_THUNK_DATA pThunk =(PIMAGE_THUNK_DATA)
((PBYTE)hModCallerModule+pImportDesc->FirstThunk);
for (;pThunk->u1.Function;pThunk++)
{
PROC * ppfn= (PROC *)&pThunk->u1.Function;
if (*ppfn==pfnOriginApiAddress)
{
DWORD dwOldProtect;
VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnDummyFuncAddress,
sizeof(pfnDummyFuncAddress),NULL);
VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),dwOldProtect,0);
return;
}
}
}
BOOL WINAPI HookAllAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,
PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
if (pszCalleeModuleName == NULL)
{
return FALSE;
}
if (pfnOriginApiAddress == NULL)
{
return FALSE;
}
if (hModCallerModule == NULL)
{
MEMORY_BASIC_INFORMATION mInfo;
HMODULE hModHookDLL;
HANDLE hSnapshot;
MODULEENTRY32 me;
me.dwSize=sizeof(MODULEENTRY32);
VirtualQuery(HookOneAPI,&mInfo,sizeof(mInfo));
hModHookDLL=(HMODULE)mInfo.AllocationBase;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
BOOL bOk = Module32First(hSnapshot,&me);
while (bOk)
{
if (me.hModule != hModHookDLL)
{
hModCallerModule = me.hModule;
HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,
pfnDummyFuncAddress,hModCallerModule);
}
bOk = Module32Next(hSnapshot,&me);
}
return TRUE;
}
else
{
HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,
pfnDummyFuncAddress,hModCallerModule);
return TRUE;
}
return FALSE;
}
void InstallApiHooks(BOOL IsHook)
{
if (IsHook)
{
HookAllAPI("WS2_32.dll",GetProcAddress(GetModuleHandle("ws2_32.dll"),
"WSASend"),(PROC)&NewWsaSend,NULL);
}
else
{
UnhookAllAPI("WS2_32.dll",GetProcAddress(GetModuleHandle("ws2_32.dll"),
"WSASend"),(PROC)&NewWsaSend,NULL);
}
}int NewWsaSend(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE)
{
char szFileName[64];
GetModuleFileName(GetModuleHandle(NULL),szFileName,64);
int ret=100;
ret=WSASend(s,lpBuffers,dwBufferCount,lpNumberOfBytesSent,
dwFlags,lpOverlapped,lpCompletionROUTINE);
char szBytesOfSend[20];
wsprintf(szBytesOfSend,"Send %d Bytes",ret);
MessageBox(NULL,lpBuffers->buf,szFileName,MB_OK);
return ret; //问题出在这里,能够显示出调用者传递给它的 lpBuffers ,但返回时目标进程报错,原因是某个内存地址为只读。
}
{
DWORD dwOldProtect;
VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnDummyFuncAddress,
sizeof(pfnDummyFuncAddress),NULL);
VirtualProtect(ppfn,sizeof(pfnDummyFuncAddress),dwOldProtect,0);
return;
} 这里的问题?内存访问违规~~
好象不是,因为执行的时候在这里并没有报错,而是在我自己的函数里面返回的时候报错。
我也没玩过~