TCP/IP filtering question

Hey, guys
I am a newbie in this area and there is one thing I cannot quite comprehend:
My driver creates a device object and attaches this device object above \Device\Tcp. In my Dispatch routine I see all the IRPs directed to the tcpip.sys for it’s tcp device. The problem is however that sometimes I can’t find any user data in the IRP and in the currnet stack location. For example: IRP with
IRP_MJ_INTERNAL_DEVICE_CONTROL and IoControlCode == 3 /*METHOD_NEITHER */
has Parameters.DeviceIoControl.Type3InputBuffer = NULL
and Irp->UserBuffer = NULL which is kind of strange…
The problem I am trying to solve here is finding some data regarding TCP_SEND, BIND, etc…
Can anyone help please?

What is a Function code for such request? Check lengths of buffers. It may be that such IRP doesn’t require any input and output data.

Igor Sharovar

Lookup the topic “TDI Drivers” in the WDK Help. That’s about the only documentation you’ll find.

Data sent is found by referencing the IRP MdlAddress field. Study the Mm… functions associated with MDLs. Looking at NDIS samples may be helpful. When reading understand that a NDIS_BUFFER structure is identical to a MDL.

Examine the TDIkrnk.h headers in the WDK carefully. Understanding the MACROs may be helpful.

Good luck!!!

Thomas F. Divine
http://www.pcausa.com

Thomas, thanks a lot for an advice.

I am using the following pseudo code to extract the data in my Dispatch()
before forwarding the IRP to the tcpip driver:

PNDIS_BUFFER NdisBuffer =(PNDIS_BUFFER)Irp->MdlAddress;

NdisQueryBufferSafe(NdisBuffer, &VirtualAddress, &Length,
NormalPagePriority);

I am trying to walk the Buffer chain with NdisGetNextBuffer but there always
seem to be only one buffer in my case.

Now, as I understand I must be able to extract some useful information from
the VirtualAddress address.

I assumed that the IP packet is somewhere over there… But I still cannot
see any intelligible addresses…

I have modified the passthru sample to walk the NDIS_PACKET structure
starting with NdisGetFirstBufferFromPacketSafe

and I am rebuilding the full user buffer from the contained NDIS_BUFFERs.
This works just fine and I am seeing real IPs over there.

But in this case I am not quite sure how to reassemble the initial packet.

Can you please help? I feel the answer is excruciatingly near…

Regards,

Dmitry.

wrote in message news:xxxxx@ntdev…
> Hey, guys
> I am a newbie in this area and there is one thing I cannot quite
> comprehend:
> My driver creates a device object and attaches this device object above
> \Device\Tcp. In my Dispatch routine I see all the IRPs directed to the
> tcpip.sys for it’s tcp device. The problem is however that sometimes I
> can’t find any user data in the IRP and in the currnet stack location. For
> example: IRP with
> IRP_MJ_INTERNAL_DEVICE_CONTROL and IoControlCode == 3 /*METHOD_NEITHER */
> has Parameters.DeviceIoControl.Type3InputBuffer = NULL
> and Irp->UserBuffer = NULL which is kind of strange…
> The problem I am trying to solve here is finding some data regarding
> TCP_SEND, BIND, etc…
> Can anyone help please?
>

I appologize for the spacing in the previous message.
Maybe I should assume that different BUFFERs in fact comprise one
NDIS_PACKET?
But how can I know when does each packet end?

Dmitry.

“Dmitry Geskin” wrote in message news:xxxxx@ntdev…
> Thomas, thanks a lot for an advice.
>
> I am using the following pseudo code to extract the data in my Dispatch()
> before forwarding the IRP to the tcpip driver:
>
>
>
> PNDIS_BUFFER NdisBuffer =(PNDIS_BUFFER)Irp->MdlAddress;
>
> NdisQueryBufferSafe(NdisBuffer, &VirtualAddress, &Length,
> NormalPagePriority);
>
>
>
> I am trying to walk the Buffer chain with NdisGetNextBuffer but there
> always seem to be only one buffer in my case.
>
>
>
> Now, as I understand I must be able to extract some useful information
> from the VirtualAddress address.
>
> I assumed that the IP packet is somewhere over there… But I still cannot
> see any intelligible addresses…
>
>
>
> I have modified the passthru sample to walk the NDIS_PACKET structure
> starting with NdisGetFirstBufferFromPacketSafe
>
> and I am rebuilding the full user buffer from the contained NDIS_BUFFERs.
> This works just fine and I am seeing real IPs over there.
>
>
>
> But in this case I am not quite sure how to reassemble the initial packet.
>
> Can you please help? I feel the answer is excruciatingly near…
>
>
>
> Regards,
>
> Dmitry.
>
>
>
> wrote in message news:xxxxx@ntdev…
>> Hey, guys
>> I am a newbie in this area and there is one thing I cannot quite
>> comprehend:
>> My driver creates a device object and attaches this device object above
>> \Device\Tcp. In my Dispatch routine I see all the IRPs directed to the
>> tcpip.sys for it’s tcp device. The problem is however that sometimes I
>> can’t find any user data in the IRP and in the currnet stack location.
>> For example: IRP with
>> IRP_MJ_INTERNAL_DEVICE_CONTROL and IoControlCode == 3 /*METHOD_NEITHER */
>> has Parameters.DeviceIoControl.Type3InputBuffer = NULL
>> and Irp->UserBuffer = NULL which is kind of strange…
>> The problem I am trying to solve here is finding some data regarding
>> TCP_SEND, BIND, etc…
>> Can anyone help please?
>>
>
>
>

You may find it useful to research what is referred to as a “TDI Filter” (or “TDI Firewall”).

The interface to the device objects created by TCPIP.SYS and other “Transport Drivers” in Windows NT5 (2K/XP/2K3) is a bit unusual and not the easiest set of semantics to learn let alone design a I/O filtering mechanism for.

As Thomas has suggested, you must learn about TDI and the overall operation of a TDI Client & TDI Transport with respect to how they interact. At that point some of what you are seeing in the I/O Request path will make sense.

But understand that you will never see “IP Packets” or anything remotely like them across this interface. The you will see (often a subset of) the application - i.e., if you have simple winsock application that creates and connects a TCP socket then writes “Hello, I am a winsock application” into the socket data stream, you will see a the data “Hello …” go by but nothing of the ‘packets’ generated to carry that on the wire.

So while it might be a very fun and curious endeavor to create “yet another TDI filter” - perhaps you might in parallel ask us how one might go about doing what it is you are trying to accomplish at a high level. Maybe a TDI filter is the anwer. Maybe not.

Bottom line? What is it you are attempting to accomplish by attaching to \Device\TCP and filtering (in the I/O Manager sense) the I/O Requests across this interface?

Good Luck,
Dave Cattley

Why do you think there is an address there?

Think of socket send and recv. Is the address in the data buffer? I don’t
think so. Same with TDI.

Continue examining the TDI documentation. Before trying to filter TDI, write
a few (read “many”) TDI clients. See how they create connections and send
data. Then you will begin to understand what you are filtering. If you don’t
understand TDI clients first you will never be able to write a TDI filter.

Thomas


From: “Dmitry Geskin”
Sent: Sunday, August 22, 2010 5:21 AM
Newsgroups: ntdev
To: “Windows System Software Devs Interest List”
Subject: Re:[ntdev] TCP/IP filtering question

> Thomas, thanks a lot for an advice.
>
> I am using the following pseudo code to extract the data in my Dispatch()
> before forwarding the IRP to the tcpip driver:
>
>
>
> PNDIS_BUFFER NdisBuffer =(PNDIS_BUFFER)Irp->MdlAddress;
>
> NdisQueryBufferSafe(NdisBuffer, &VirtualAddress, &Length,
> NormalPagePriority);
>
>
>
> I am trying to walk the Buffer chain with NdisGetNextBuffer but there
> always seem to be only one buffer in my case.
>
>
>
> Now, as I understand I must be able to extract some useful information
> from the VirtualAddress address.
>
> I assumed that the IP packet is somewhere over there… But I still cannot
> see any intelligible addresses…
>
>
>
> I have modified the passthru sample to walk the NDIS_PACKET structure
> starting with NdisGetFirstBufferFromPacketSafe
>
> and I am rebuilding the full user buffer from the contained NDIS_BUFFERs.
> This works just fine and I am seeing real IPs over there.
>
>
>
> But in this case I am not quite sure how to reassemble the initial packet.
>
> Can you please help? I feel the answer is excruciatingly near…
>
>
>
> Regards,
>
> Dmitry.
>
>
>
> wrote in message news:xxxxx@ntdev…
>> Hey, guys
>> I am a newbie in this area and there is one thing I cannot quite
>> comprehend:
>> My driver creates a device object and attaches this device object above
>> \Device\Tcp. In my Dispatch routine I see all the IRPs directed to the
>> tcpip.sys for it’s tcp device. The problem is however that sometimes I
>> can’t find any user data in the IRP and in the currnet stack location.
>> For example: IRP with
>> IRP_MJ_INTERNAL_DEVICE_CONTROL and IoControlCode == 3 /*METHOD_NEITHER */
>> has Parameters.DeviceIoControl.Type3InputBuffer = NULL
>> and Irp->UserBuffer = NULL which is kind of strange…
>> The problem I am trying to solve here is finding some data regarding
>> TCP_SEND, BIND, etc…
>> Can anyone help please?
>>
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

Why do you think there is an address there?

Think of socket send and recv. Is the address in the data buffer? I don’t
think so. Same with TDI.

Continue examining the TDI documentation. Before trying to filter TDI, write
a few (read “many”) TDI clients. See how they create connections and send
data. Then you will begin to understand what you are filtering. If you don’t
understand TDI clients first you will never be able to write a TDI filter.

Thomas


From: “Dmitry Geskin”
Sent: Sunday, August 22, 2010 5:21 AM
Newsgroups: ntdev
To: “Windows System Software Devs Interest List”
Subject: Re:[ntdev] TCP/IP filtering question

> Thomas, thanks a lot for an advice.
>
> I am using the following pseudo code to extract the data in my Dispatch()
> before forwarding the IRP to the tcpip driver:
>
>
>
> PNDIS_BUFFER NdisBuffer =(PNDIS_BUFFER)Irp->MdlAddress;
>
> NdisQueryBufferSafe(NdisBuffer, &VirtualAddress, &Length,
> NormalPagePriority);
>
>
>
> I am trying to walk the Buffer chain with NdisGetNextBuffer but there
> always seem to be only one buffer in my case.
>
>
>
> Now, as I understand I must be able to extract some useful information
> from the VirtualAddress address.
>
> I assumed that the IP packet is somewhere over there… But I still cannot
> see any intelligible addresses…
>
>
>
> I have modified the passthru sample to walk the NDIS_PACKET structure
> starting with NdisGetFirstBufferFromPacketSafe
>
> and I am rebuilding the full user buffer from the contained NDIS_BUFFERs.
> This works just fine and I am seeing real IPs over there.
>
>
>
> But in this case I am not quite sure how to reassemble the initial packet.
>
> Can you please help? I feel the answer is excruciatingly near…
>
>
>
> Regards,
>
> Dmitry.
>
>
>
> wrote in message news:xxxxx@ntdev…
>> Hey, guys
>> I am a newbie in this area and there is one thing I cannot quite
>> comprehend:
>> My driver creates a device object and attaches this device object above
>> \Device\Tcp. In my Dispatch routine I see all the IRPs directed to the
>> tcpip.sys for it’s tcp device. The problem is however that sometimes I
>> can’t find any user data in the IRP and in the currnet stack location.
>> For example: IRP with
>> IRP_MJ_INTERNAL_DEVICE_CONTROL and IoControlCode == 3 /*METHOD_NEITHER */
>> has Parameters.DeviceIoControl.Type3InputBuffer = NULL
>> and Irp->UserBuffer = NULL which is kind of strange…
>> The problem I am trying to solve here is finding some data regarding
>> TCP_SEND, BIND, etc…
>> Can anyone help please?
>>
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

Dave, thanks for the quick answer. I’ve been trying to solve the following problem for quite a while: Filtering the network traffic(outbound and hopefully also inbound) on WinXP SP3 within a minifilter file-system driver. I have tried all these methods whith none to moderate success:

  1. Modification of the PassThru driver. This actually gave great results; in MPSendPackets() and in PtReceivePacket() I was able to see inbound and outbound ethernet packekts with all the data. This solution, however included adding a full-blown driver to an existing project and writing a monstrous installer using INetCfg.
  2. Some dirty hooking of ndis MJ functions - no results
  3. Attaching to \Device\Tcp or \Device\NDIS - mediocre, unstable results. I was able to see only raw ip (ICMP packets) and nothing more.
  4. Trying to register a TDI client with notification callbacks - a lot of code, connection objects, socket objects, etc - all the obscurity of the TDI was upon me - nothing worked.
  5. Thinking of hooking NDIS interrupts - crazy, unstable idea by itself.
  6. Registering with a filter driver included with XP - worked great but allows only one client.

So, as you see, I am pretty desperate. Is it possible to do what I am trying to do? I just wanted to add here my experience in NDIS drivers and networking is rather limited.

Regards,
Dmitry.

Dimitry,

Those answers are all ‘solutions’ to some problem you have not yet stated :slight_smile:

So let’s start from what you did add with this answer:

  • You have (or have need for a FS filter).

  • In your FS filter you need to either know something about the network traffic to/from the box or need to be able to *modify* the network traffic to/from the box. Which ?

Some specific points about what you say below:

(1) without knowing the answer to the root question, this is probably the correct path for you. Regarding INetCfg - geez, come one, you write a FS filter and you think that hacking the SNETCFG sample to install your IM driver or just using DIFx (way easy) is somehow burdensome? It concerns me when I see the architecture of a solution that will live inserted into a critical bit of the OS compromised by how one must robustly install it.

(2) Yeah, a friend and colleague whom I respect greatly for pioneering such efforts on NT4 & 9x will likely concur that on NT5 that is a really bad idea. :wink:

(3) Attaching to \Device\NDIS is, well, not likely to get you much unless you want to watch INetCfg tell NDIS to bind & unbind stuff and be barraged with requests for packet counts to update the UI from. There is not *network data plane* operation across this device object. It is for control & status of the network system. \Device\TCP is another story as you are learning.

(4) I don’t think you want to be a TDI client. You seem to be interested in watching or modifying what *other* TDI clients are doing. Perhaps the network redirector?

(5) So NDIS does not have any interrupts… Devices that are serviced by drivers which themselves are NDIS miniports might have interrupts. Not so subtle distinction but you are right, CRAZY (unless you are a former Numega person responsible for the network support in SoftIce - then, only half crazy).

(6) Yeah, sadly, not a good choice. It seems like it would have been the perfect choice and it only took another what, 9 years to get such a choice created (WFP in NT6). But seriously, is the packet filter interface the correct semantics for what you are trying to accomplish? Meaning, that you can inspect and block IP packets (but not modify them) and we are talking IP packets (not IP datagrams)?

Cheers,
Dave Cattley

Date: Sun, 22 Aug 2010 09:21:54 -0400
From: xxxxx@gmail.com
To: xxxxx@lists.osr.com
Subject: RE:[ntdev] TCP/IP filtering question

Dave, thanks for the quick answer. I’ve been trying to solve the following problem for quite a while: Filtering the network traffic(outbound and hopefully also inbound) on WinXP SP3 within a minifilter file-system driver. I have tried all these methods whith none to moderate success:

  1. Modification of the PassThru driver. This actually gave great results; in MPSendPackets() and in PtReceivePacket() I was able to see inbound and outbound ethernet packekts with all the data. This solution, however included adding a full-blown driver to an existing project and writing a monstrous installer using INetCfg.
  2. Some dirty hooking of ndis MJ functions - no results
  3. Attaching to \Device\Tcp or \Device\NDIS - mediocre, unstable results. I was able to see only raw ip (ICMP packets) and nothing more.
  4. Trying to register a TDI client with notification callbacks - a lot of code, connection objects, socket objects, etc - all the obscurity of the TDI was upon me - nothing worked.
  5. Thinking of hooking NDIS interrupts - crazy, unstable idea by itself.
  6. Registering with a filter driver included with XP - worked great but allows only one client.

So, as you see, I am pretty desperate. Is it possible to do what I am trying to do? I just wanted to add here my experience in NDIS drivers and networking is rather limited.

Regards,
Dmitry.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

“Filtering” is a pretty broad topic.

What operations do you need to perform on the network stream?

Be a little more specific. In particular, do you simply need to monitor
(observe) the packets or do you need to modify or block the packets of
interest?

Attaching to \Device\Tcp is above the kernel TCP/IP driver. Does this mean
that you could actually use a “simple” kernel-mode TDI client instead of a
filter?

Procedure 3.) below probably doesn’t work for you because you don’t handle
TDI event handlers, and to filter those you must keep a history of all
operations on each AO/CO starting with their creation. Really messy.

Good luck,

Thomas F. Divine


From:
Sent: Sunday, August 22, 2010 9:21 AM
To: “Windows System Software Devs Interest List”
Subject: RE:[ntdev] TCP/IP filtering question

> Dave, thanks for the quick answer. I’ve been trying to solve the following
> problem for quite a while: Filtering the network traffic(outbound and
> hopefully also inbound) on WinXP SP3 within a minifilter file-system
> driver. I have tried all these methods whith none to moderate success:
> 1. Modification of the PassThru driver. This actually gave great results;
> in MPSendPackets() and in PtReceivePacket() I was able to see inbound and
> outbound ethernet packekts with all the data. This solution, however
> included adding a full-blown driver to an existing project and writing a
> monstrous installer using INetCfg.
> 2. Some dirty hooking of ndis MJ functions - no results
> 3. Attaching to \Device\Tcp or \Device\NDIS - mediocre, unstable results.
> I was able to see only raw ip (ICMP packets) and nothing more.
> 4. Trying to register a TDI client with notification callbacks - a lot of
> code, connection objects, socket objects, etc - all the obscurity of the
> TDI was upon me - nothing worked.
> 5. Thinking of hooking NDIS interrupts - crazy, unstable idea by itself.
> 6. Registering with a filter driver included with XP - worked great but
> allows only one client.
>
> So, as you see, I am pretty desperate. Is it possible to do what I am
> trying to do? I just wanted to add here my experience in NDIS drivers and
> networking is rather limited.
>
> Regards,
> Dmitry.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

I only need to monitor and maybe block some ip packets. No ip packet/ip datagram modification is required. Dave, I need the FS filter since it monitors (and filters) some file-system and registry activity.

If you can work at the packet level then a NDIS 5 IM driver should work.

See the “Extending the Passthru…” series of articles at
http://www.wd-3.com.

Good luck,

Thomas F. Divine
http://www.pcausa.com


From:
Sent: Sunday, August 22, 2010 10:08 AM
To: “Windows System Software Devs Interest List”
Subject: RE:[ntdev] TCP/IP filtering question

> I only need to monitor and maybe block some ip packets. No ip packet/ip
> datagram modification is required. Dave, I need the FS filter since it
> monitors (and filters) some file-system and registry activity.
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

Thomas’ advice (as always) is right on.

If all you need to do is monitor (aka, ‘inspect’) and possibly block IP packets - and you do not need to correlate the IP packet ‘flows’ to specific activity to a TDI client or process on the local machine, then an NDIS IM Filter driver is the way to go on NT5.

Good Luck,
Dave Cattley

From: xxxxx@pcausa.com
To: xxxxx@lists.osr.com
Subject: Re: RE:[ntdev] TCP/IP filtering question
Date: Sun, 22 Aug 2010 10:19:25 -0400

If you can work at the packet level then a NDIS 5 IM driver should work.

See the “Extending the Passthru…” series of articles at
http://www.wd-3.com.

Good luck,

Thomas F. Divine
http://www.pcausa.com

> My driver creates a device object and attaches this device object above \Device\Tcp.

Does not work properly on Vista+, where half or more of clients do not use this DO.

The problem I am trying to solve here is finding some data regarding TCP_SEND

Read the TDI documentation.

->MdlAddress is used to pass the data.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Thanks for very useful inputs.
I guess I am back to that old passthru sample mutation!
Regards,
Dmitry

“Maxim S. Shatskih” wrote in message
news:xxxxx@ntdev…
> My driver creates a device object and attaches this device object above
> \Device\Tcp.

Does not work properly on Vista+, where half or more of clients do not use
this DO.

> The problem I am trying to solve here is finding some data regarding
> TCP_SEND

Read the TDI documentation.

->MdlAddress is used to pass the data.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com