Search code examples
c++socketsdetoursoverlapped-io

WSARecv hook: prevent packet from being recieved by the executable


I am working on dll which hooks winsock2 functions, using C++ and detours. My goal is to modify TCP traffic that goes from and to the original executable. At some point, I need to stop certain packet delivery (so that original executable has no idea about that packet at all, but still keeps the connection).

With WSASend hook, it's clear (you just don't call original WSASend and return 0). But I have no idea how to make it in WSARecv hook using WSAOVERLAPPED structure.

I hope this code below demonstrates what do I want:

__declspec(dllexport) int WINAPI WSARecv_hook(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
    // Recieve real data
    int ret = WSARecv_real(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);

    // Loop over lpBuffers and analyze it
    for(int i=0; i < dwBufferCount; i++)
    {
        // analyze it
        if(packet_should_be_blocked(lpBuffers[i].buf, lpBuffers[i].len))
        {
            // Do or return what?
        } else {
            // Otherwise, just process as usual
        }
    }
    return ret;
}

How do I pretend that nothing happened and no packet was recieved (like fake WSA_IO_PENDING)? Any ideas/thoughts?

P.S. From what I know, executable is not using completion routine (lpCompletionRoutine is always NULL), only overlapped structure.


Solution

  • The main hurdle is that overlapped operations are meant to be performed in the background after the calling function has exited with a pending status. If the caller asks WSARecv() to perform an overlapped read, it is expecting the data to arrive in the background, and you won't be able to validate the data inside of your hook directly because it has not been received yet. You will have to use your own private WSAOVERLAPPED to perform your own overlapped read, using a thread or completion callback to detect when that read finishes so that you can then analyze the data. If the data is acceptable, copy it into the caller's buffer and signal the caller's WSAOVERLAPPED. Otherwise, post another read and wait for that data to arrive, repeating as needed until you finally receive some data that you want to give to the caller.