Recently I started to receive some rather strange error messages from some .NET programs I had written that made use of the WebRequest class. The exception was something like this:

System.IO.IOException: Unable to read data from the transport connection: 
Attempted to read or write protected memory. This is often an indication that other memory is corrupt..
---> System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Net.UnsafeNclNativeMethods.OSSOCK.recv(IntPtr socketHandle, Byte* pinnedBuffer, Int32 len, SocketFlags socketFlags)
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError& errorCode) 

This means that the native recv method was trying to muck with protected memory: a fairly bad and low level failure! This kind of thing shouldn’t really be able to happen because the .NET Socket class is very robust and well tested, so I broke out the native code debugging features of Visual Studio to try and figure out what was going on. This involved allowing native code debugging on the project, and turning off “Just My Code” in the VS debugging options. Furthermore, I turned on automatic debugging symbol loading using the MS symbol server (located here). This done, I reran the application and look what I saw:

ntdll.dll!_NtWaitForSingleObject@12()  + 0xc bytes
kernel32.dll!_WaitForSingleObjectEx@12()  + 0x84 bytes
ntdll.dll!ExecuteHandler2@20()  + 0x26 bytes
ntdll.dll!ExecuteHandler@20()  + 0x24 bytes
ntdll.dll!_KiUserExceptionDispatcher@8()  + 0xf bytes
[Frames below may be incorrect and/or missing, no symbols loaded for imon.dll]
kernel32.dll!_MultiByteToWideChar@24()  + 0x76 bytes
[Managed to Native Transition]
System.dll!System.Net.Sockets.Socket.Receive(byte[] buffer = {Dimensions:[2]}, int offset = 0, int size, System.Net.Sockets.SocketFlags socketFlags = None, out System.Net.Sockets.SocketError errorCode = Success) + 0x139 bytes
System.dll!System.Net.Sockets.Socket.Receive(byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags) + 0x1d bytes
System.dll!System.Net.Sockets.NetworkStream.Read(byte[] buffer, int offset, int size) + 0x78 bytes

I wasn’t expecting to see this because recv is actually located in Ws2_32.dll! It looked like the imon DLL was actually hooking this call and then blowing up internally due to some bug. I happened to know that this was part of the NOD32 internet protection suite I have installed, and indeed once that was disabled my programs no longer threw the exception! This is a clear case of a bug in their product, so I reported it to them. Unfortunately, their response was not particularly helpful:

In our next major release (3.0), we are doing away with IMON after many years and replacing it with two more utilities.

In 1992, when NOD32 was introduced, very few programs operated at the Winsock level. Today, in addition to Google and Microsoft, 100’s of other developers are creating software in this manner. That would be fine, except for the fact that any app that operates here needs the top spot in the stack, and only one program can have it.

As it is now, it can’t be enabled at all on a server.

IMON was just the first layer of defense, a supplement. The strengths of NOD32 are AMON, which scans every file that performs an action, as it performs that action and the advanced heuristics which is stopping 90%+ of all new threats, before a definition is even written.

By quitting IMON now, you’ll not only allow both programs to operate together, but you’ll also lose no coverage.

So what I’m taking away from this experience is that NOD32s IMON is just broken, and potentially dangerous: from now on I’ll be turning it off on all my installations of NOD32, and I recommend you do the same.