簡體   English   中英

Winsock recv hooking with Detours

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM