[英]Winsock recv hooking with Detours
我有一個應用程序,它使用 Winsock 2.0 recv
function,我可以通過 Redox Packet Editor 捕獲 output,例如,它確認版本是 2.0。
我有這個代碼來掛鈎 function:
#define _CRT_SECURE_NO_DEPRECATE
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <WinSock2.h>
#include <detours.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
FILE *pSendLogFile;
FILE *pRecvLogFile;
int (WINAPI *pSend)(SOCKET s, const char* buf, int len, int flags) = send;
int WINAPI MySend(SOCKET s, const char* buf, int len, int flags);
int (WINAPI *pRecv)(SOCKET s, char *buf, int len, int flags) = recv;
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags);
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pSend, MySend);
if(DetourTransactionCommit() == NO_ERROR)
MessageBox(0,"send() detoured successfully","asd",MB_OK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pRecv, MyRecv);
if(DetourTransactionCommit() == NO_ERROR)
MessageBox(0,"recv() detoured successfully","asd",MB_OK);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
int WINAPI MySend(SOCKET s, const char* buf, int len, int flags)
{
MessageBox(0,"sent","sent",MB_OK);
return pSend(s, buf, len, flags);
}
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)
{
MessageBox(0,"recvd","recvd",MB_OK);
return pRecv(s, buf, len, flags);
}
對於send
,一切正常,但我沒有得到任何 output 的recv
。 我在另一個應用程序中嘗試使用 1.1 版本的 Winsock,它工作正常。 嘗試掛鈎 WSARecv、WSARecvEx 但沒有任何運氣。
使用 WinAPIOverride32 檢查應用程序,它清楚地表明它使用recv
function,並成功記錄了使用情況。 Winsock 數據包編輯器也能很好地讀取數據。
有任何想法嗎?
您確定您掛接的是正確的 dll 嗎? 我會仔細檢查程序實際使用了哪個 dll:WSOCK32.dll 或 ws2_32.dll。
編輯:
也許嘗試這樣的事情:
typedef int (WINAPI *SendPtr)(SOCKET s, const char* buf, int len, int flags);
HMODULE hLib = LoadLibrary("wsock32.dll");
SendPtr pSend = (SendPtr)GetProcAddress(hLib, "send");
然后將pSend
與該值一起使用(recv 也是如此)。 不要忘記最后調用 FreeLibrary。 如果您確定 dll 已經加載,那么最好使用GetModuleHandle("wsock32.dll")
,因為在這種情況下您不必調用 FreeLibrary。
你的問題源於試圖寫出一個空的(甚至未初始化的緩沖區):
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)
{
fopen_s(&pRecvLogFile, "C:\\RecvLog.txt", "a+");
fprintf(pRecvLogFile, "%s\n", buf);
fclose(pRecvLogFile);
return pRecv(s, buf, len, flags); //you need to call recv first
}
而是做這樣的事情:
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)
{
int read = pRecv(s, buf, len, flags);
if(read <= 0)
{
//read error/connection closed
return read;
}
fopen_s(&pRecvLogFile, "C:\\RecvLog.txt", "a+");
fwrite(buf,sizeof(char),read,pRecvLogFile);
fclose(pRecvLogFile);
return read;
}
作為次要問題,您似乎假設發送或接收的數據是純粹基於字符串的,但通常數據包可能在這里和那里包含零字節,這將過早結束fprintf
output,您應該改用fwrite
,傳遞 send/接收大小(這也意味着以二進制模式打開文件)。
我認為您當然應該使用 GetProcAddress 來獲取要掛接的地址。
就像是:
int (WINAPI *pRecv)(SOCKET s, char *buf, int len, int flags) = GetProcAddress(GetModuleHandle("ws2_32.dll"), "recv");
編譯器可能會想出從您的“recv”到加載了 dll 的地址的各種瘋狂路由。因此這兩個地址可能會有所不同。 要測試是否是這種情況,只需使用來自 dll 的 recv。
您可能還想關注 ReadFile/WriteFile。
並且還期望掛鈎不可靠。 例如,目標可以隨意移除鈎子並做更多事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.