0

I'm writing a packet encryption for a friends gameserver. Client is using ws2_32 recv/send but server uses WSARecv/WSASend.

I've managed to encrypt/decrypt send/recv/WSASend, but WSARecv seems impossible. I'm using the same method as on recv, but it doesn't seem to work.

int WINAPI MyWSARecv(SOCKET socket, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
         LPWSABUF buffers = lpBuffers;
        int ret = pWSARecv(socket, buffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);

        cryptPacket(buffers->buf, buffers->len);
        lpBuffers = buffers;
        return ret;
}

Any ideas would be appreciated.

Asmo
  • 27
  • 1
  • 9
  • 1
    Why use Detours instead of just invoking `MyWSARecv` directly? Also, can show your code where you create the hook to WSARecv? – selbie Apr 21 '15 at 11:49
  • I'm pretty sure the hook works because I've managed to log buffers. http://pastebin.com/NzE66TWD here's the code. – Asmo Apr 21 '15 at 12:00
  • So what exactly is the problem? You need to more descriptive than just saying, "it doesn't seem to work". – selbie Apr 21 '15 at 12:04
  • The client sents a packet encrypted to the server so I need to intercept the WSARecv and decrypt the incoming packet to fit the program's packet handler. Even if I "return 0;" the packet is already processed before decryption when calling pWSARecv. – Asmo Apr 21 '15 at 12:09

1 Answers1

0

A handful of things to consider.

You are not actually checking the return value from pWASRecv before calling your cryptPacket function. You need to start with that fix first before any other assumptions can be made about how the detour hooks work with the socket code. If the call indicates an error, it's probably not well defined what buffers->len is going to be or what is going to be in those buffers.

Also, you are likely assuming that the socket was initialized to be synchronous. If the socket was initialized for overlapped I/O, then the lpOverlapped and lpCompletionRoutine parameters become very relevant. You may need to hook the completion routine or WSAGetOverlappedResult to actually intercept the socket data.

Finally, may I suggest another approach. Rather than trying to "detour" the socket API calls, run a "proxy socket". That is, when the server socket is created (via a call to "socket"), you change it to listen on a different port. Then you create a separate listen socket that listens on the original port. When an incoming connection comes into your socket, you make a separate "proxy" connection to the actual port the game server is listening on. You can have a dedicated thread that just calls send and recv on the client socket that encrypts/decrypts data as needed.

selbie
  • 100,020
  • 15
  • 103
  • 173
  • I didn't manage to hook WSAGetOverlappedResult. Could you explain a little bit more your suggestion with an example? From what I understood I need to create a socket listen on a xPort and then forward the traffic to gameserverPort like client->xPort->gameserver port and vice-versa? Wouldn't that cause all players using the same IP(GameServer IP)? – Asmo Apr 22 '15 at 04:56
  • This is a client-server game, correct? And do the clients connect over TCP or UDP? In any case, a dedicated loop to proxy packets would be fine. – selbie Apr 22 '15 at 05:08
  • The clients connect over TCP. However I'd prefer to intercept WSARecv to avoid gameserver recognising all players as using the same IP. Any suggestions regarding this are welcome. – Asmo Apr 22 '15 at 05:58
  • A well written game server should expect clients with identical IPs. Think of the case where two or more people are playing behind the same NAT/router in their home. Or a group of people at the same office are playing and connecting to the same server. If you use a socket per client connection, each one will have same IP, but different port. – selbie Apr 22 '15 at 06:06
  • btw - what are you *really trying to do*? – selbie Apr 22 '15 at 06:08
  • All I'm trying to do is encrypt traffic between client and server. – Asmo Apr 22 '15 at 06:13
  • You could always use VPN. – selbie Apr 22 '15 at 06:33
  • That's not the point. I need to encrypt the packets to avoid packet injectors to be used for hacking. Looking forward to suggestions regarding on intercepting WSARecv. – Asmo Apr 22 '15 at 06:51
  • As I said above, I suspect the server is using [overlapped I/O](https://msdn.microsoft.com/en-us/library/windows/desktop/ms741582(v=vs.85).aspx) with their sockets. Quite possibly could be using [IO Completion ports](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx). You should read up on these APIs and ascertain if the server code is using either approach. Then modify your hooks to keep track of socket state. btw, how do you exchange keys between client/server. What prevents a *determined hacker* from just encrypting his packets too? – selbie Apr 22 '15 at 18:37
  • I'm using AES256 encryption and using XOR to encrypt the key. However I've read a little about WSARecv and understood what you were saying also I'll use vmprot to protect the dll. pastebin.com/LbiHUVbD I've used this code to verify it uses overlapped I/O and it always prints "WSARecv (2) (Overlapped)". It won't call WSAGetOverlappedResult but GetQueuedCompletionStatus. How Should I handle that? – Asmo Apr 22 '15 at 19:44