Winsock recv hooking with Detours

I have an application that uses the Winsock 2.0 recv

feature and I can catch the output of the Redox Packet Editor, for example, it confirms that version is 2.0.

I have this code to connect a 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);
}

      

For send

everything works fine, but I am not getting any output for recv

. I tried in another application using Winsock version 1.1 and it works fine. Tried to hook WSARecv, WSARecvEx with no luck.

Verified the app using WinAPIOverride32, it clearly states that it is using the function recv

and logs use successfully. The Winsock Package Editor is also good at reading data.

Any ideas?

+3


source to share


3 answers


Are you sure you have included the correct DLL? I would double check which DLL is actually being used by the program: WSOCK32.dll or ws2_32.dll.

Edit:

Maybe try something like this:



typedef int (WINAPI *SendPtr)(SOCKET s, const char* buf, int len, int flags);
HMODULE hLib = LoadLibrary("wsock32.dll");
SendPtr pSend = (SendPtr)GetProcAddress(hLib, "send");

      

And then use pSend

with that value (same for recv). Remember to call FreeLibrary at the end. If you are sure that the DLL is already loaded, then it is probably best to use GetModuleHandle("wsock32.dll")

, since in this case you do not need to call FreeLibrary.

+3


source


the problem comes from trying to write out an empty (or even uninitialized buffer):

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
}

      

instead do something like this:



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;
}

      

as a secondary issue, you assume that the data sent or received is purely string, but usually packets may contain null bytes here and there that prematurely end the output fprintf

, you should use fwrite

instead passing the send / receive size (this also assumes opening the file in binary ).

+1


source


I think you should definitely use GetProcAddress to get the interception address.

Something like:

int (WINAPI *pRecv)(SOCKET s, char *buf, int len, int flags) = GetProcAddress(GetModuleHandle("ws2_32.dll"), "recv");

The compiler can come up with all kinds of wild routes from your "recv" to the one loaded with the dll. Thus, the two addresses can be different. To check if this is the case, just use recv from your dll.

You can also watch out for ReadFile / WriteFile.

And also expect the binding to be unreliable. For example, the target can remove the hook at will and do much more.

+1


source







All Articles