Answered by:
NDIS 5.1 intermediate driver for packet encryption/decryption not working with HTTP.sys

Question
-
Hello,
I've modified WDK's Passthru example to encrypt/decrypt outgoing/incoming packets. It works fine but the following issue: when testing it on Windows Server 2008 R2 x64 with IIS (so the driver proccesses packets with HTTP traffic) I've noticed that when http request is malformed and the server is giving back a "Bad request" error I get a BSOD with ATTEMPTED TO WRITE TO READ_ONLY MEMORY in my encryption routine. When I've attached a debugger I've verified that this bug check appears when I try to modify NDIS_BUFFER which contains just the tcp payload with "bad request" (without tcp header, it is in previous NET_BUFFER). I've did some research and found that IIS isn't working with Winsock but special kernel-mode driver HTTP.sys. I've looked into the hex-code of the driver and found that these standard errors are hard-coded as constants in there. So the point is when data comes from user-space (either winsock or IIS-generated response), everything works, but when the payload is taken from one of the constants in HTTP.sys, bug check ATTEMPTED TO WRITE TO READ_ONLY MEMORY occurs, however NET_BUFFER's flags indicate that memory is fully writable.
Never tried it on other OSes, but my guess is the result would be the same.
Please help.
Wednesday, October 5, 2011 6:20 PM
Answers
-
It's useful to differentiate between the packet datastructure (NDIS_PACKET, or NET_BUFFER) and the actual buffer containing the packet payload. Cloning gets you your own datastructure, which you can modify freely. (Including being able to add/remove MDLs from the chain, so you can prepend MDLs pointing to your own buffers). But what you shouldn't do is actually write to somebody else's buffer.
Much of the time, you CAN get away with writing to somebody else's buffer (and I'm sure that there are shipping drivers out there in the wild that do), but as you've noticed, it causes problems.
By the way — there are no MDL flags. :) If you look at the official documentation, only the MDL's Next field is accessible. A few other fields are exposed through macros (e.g., MmGetMdlByteCount), but a modern and correct driver does not read or write Mdl->Flags directly.
- Marked as answer by Ignat12 Friday, October 7, 2011 8:47 AM
Friday, October 7, 2011 8:12 AM
All replies
-
Sound like you've already figured out the problem -- don't write to somebody else's memory. Allocate your own, and encrypt into that.
- Proposed as answer by Thomas F. Divine Wednesday, October 5, 2011 9:58 PM
Wednesday, October 5, 2011 9:56 PM -
I would like to somehow detect if the memory is writable and if it is not, make a deep copy, but when it is, change it on the fly. It is for perfomance reasons. I wanted to monitor memory flags, but they indicate that memory is writable. Is there any other function/macros that can help me to detect read-only memory at runtime? After all, the whole point in cloning NDIS_PACKET is to own this object without copying the underlying buffers.
- Edited by Ignat12 Thursday, October 6, 2011 9:25 AM
Thursday, October 6, 2011 9:23 AM -
As already said in this thread, don't write to memory on somebody else's NDIS_PACKETs.
If you have performance concers, have you profiled your code (e.g. using xperf) and found out that memory allocations/copying is the best place to optimize performance? Have you considered porting your NDIS5 driver to NDIS6 LWF? Using NDIS5 in Server 2008 R2 includes a translation layer, which also has a little impact on performance.
-- Antti
Thursday, October 6, 2011 1:44 PM -
Read-only memory is not the only reason to avoid messing with somebody else's memory. What if that piece of memory is shared amongst multiple packets? Writing to one would mess up the others. What if that memory is mapped into usermode? Usermode gets to tamper with your encryption buffer during the encryption process. Do you know if your encryption algorithm is able to keep its keying material safe if a third party can observe its working buffer during the encryption process?
As Antti pointed out, you must not be too concerned with performance, since you're running your filter in 6-5-6 translation mode.
Thursday, October 6, 2011 7:02 PM -
The idea is not with 6-5-6. I've pointed it out since I discovered this issue on 2008 platform (because it was the first server platform I've tested my driver on). Of course, I'll rewrite the driver on NDIS 6.0. But this solution also has to work on XP and Server 2003, so NDIS 5.1 driver remains. I'll have two driver versions. The thing is I don't get the point of cloning NDIS_PACKETS and dropping the original ones if I still can't modify the underlying memory (because cloning is supposed to give ownership of the object to the driver). The WDK's PassThru example is said to be ready to modify packets, but it just doesn't do it. And what is the point of having mdl flags which describe memory incorrectly? If it is readonly than the readonly flag should be set. If I have to allocate my own buffers here I'll do it, but I would like to get the basic idea.Friday, October 7, 2011 7:43 AM
-
It's useful to differentiate between the packet datastructure (NDIS_PACKET, or NET_BUFFER) and the actual buffer containing the packet payload. Cloning gets you your own datastructure, which you can modify freely. (Including being able to add/remove MDLs from the chain, so you can prepend MDLs pointing to your own buffers). But what you shouldn't do is actually write to somebody else's buffer.
Much of the time, you CAN get away with writing to somebody else's buffer (and I'm sure that there are shipping drivers out there in the wild that do), but as you've noticed, it causes problems.
By the way — there are no MDL flags. :) If you look at the official documentation, only the MDL's Next field is accessible. A few other fields are exposed through macros (e.g., MmGetMdlByteCount), but a modern and correct driver does not read or write Mdl->Flags directly.
- Marked as answer by Ignat12 Friday, October 7, 2011 8:47 AM
Friday, October 7, 2011 8:12 AM -
Thank you for your help and explanation. I've read the documentation, but this confused me about the flags.Friday, October 7, 2011 8:45 AM
-
Er, that documentation page does seem to contradict what I said. I'd better not challenge the docs, especially when it's past midnight in Redmond. :) Perhaps somebody else will jump in and clarify to what extent drivers can manipulate the flags field.Friday, October 7, 2011 9:16 AM