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!
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.
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.
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