How can I trigger a WSAOVERLAPPED event? (C++)

2019-09-08 03:26发布

问题:

Note: The particular case I'm having troubles with is when lpCompletionRoutine is null and lpOverlapped is not.

I'm trying to write a packet sniffer. I'm hooking WSARecv and replacing it with my own code. If lpOverlapped is not null, I create my own LPWSAOVERLAPPED variable and call the real WSARecv. I receive and log the packet just fine, but the problem is, the client that I'm sniffing seems to wait for it's WSAOVERLAPPED thing to be triggered.

So the question is, how do I trigger the initial lpOverlapped? I've tried things like WSASetEvent. I've tried doing inline asm and doing something like this:

__asm{
  push InFlags
  push lpOverlapped
  push BytesTransferred
  push Error
  call lpOverlapped
}

Neither of those things worked. I'm thinking there should be a simple way to trigger the wsaoverlapped so the game knows that the i/o operation is complete, but I just don't know how.

Any and all help is appreciated.

Thanks!

edit:

I've tried signaling the code by doing the following, but I get an ERROR_INVALID_HANDLE error.

WSAOVERLAPPED overlapped = *lpOverlapped;
HANDLE hEvent = overlapped.hEvent;
if(!SetEvent(hEvent)){
    int error = GetLastError();
    Write(error);
}

Is there something special I need to do to prepare the event?

Thanks!

回答1:

Agree with Eugene Homyakov, with one little addition. Actually there are 3 ways the OS may notify the process about overlapped I/O completion.

  • Setting the event specified by hEvent member of the OVERLAPPED structure
  • Invoking the completion routine (specified in the call to WSAxxxx).
  • Posting a completion to the completion port.

About the completion routine - you should note that it's scheduled to the caller thread's APC queue when the I/O completes. It actually gets called only when the thread calls an alertable wait procedure, such as SleepEx or WaitForMultipleObjectsEx.

The OS will post the completion to the completion port if the socket/file handle has been associated with it. See CreateIoCompletionPort and PostQueuedCompletionStatus for more info.



回答2:

There is no special way to trigger it.

You need to remember original LPOVERLAPPED and completion routine parameters, and issue your own call passing a completion routine. In that completion routine, when you have received the packet, examine the original parameters: if there was a completion routine, call it; otherwise, there is hEvent in LPOVERLAPPED — signal it.



回答3:

You shouldn't be hooking Winsock APIs directly. Use the Layered Service Provider framework. Here's an example: http://www.netresec.com/?page=Blog&month=2011-01&post=Proxocket---A-Winsock-Proxy-Sniffer



标签: c++ winsock