Jump-start your project by learning from devs who
write Windows drivers and file systems every day.
Take an OSR seminar!

Upcoming OSR Seminars:
WDM Lab, Seattle, WA 16 August 2010
WDF Lab, Santa Clara, CA 27 September 2010
Debug Lab, Portland, OR 18 October 2010
Windows Internals & Software Drivers Lab, Santa Clara, CA 15 November 2010


Go Back   OSR Online Lists > ntdev
Welcome, Guest
You must login to post to this list
  Message 1 of 3  
26 Jan 02 01:37
ntdev member 7638
xxxxxx@connick.com
Join Date:
Posts To This List: 3
TDI Filter Driver, part II

Hello all, I posted here a few days ago asking for help with a TDI driver that would let me observe all TCP/IP traffic on my system. Several people pointed out that my initial approach -- trying to register an event handler with the lower level device -- would not work, and suggested I go with a TDI filter driver instead. (I've also been advised to look into WinPcap or NetMon. But WinPcap is too limited in that it can't see localhost traffic, and NetMon doesn't give me the capability to manipulate traffic -- something I'd like to look into later. Also, before someone suggests that I buy the TDI samples from PCAUSA, let me point out that I'm just doing this to learn more about Win2K drivers, so it's not something I really want to sink a lot of cash into.) Anyway, based on those suggestions plus some other random postings, I came up with the code at the end of this message. Right now it's just a passthrough -- it intercepts all the IRPs for \Device\Tcp, prints out a little message with DbgPrint(), and then passes the IRP down to the lower level device. This seems to work, sort of, in the sense that all networking-related functionality is still intact. However, I notice that I don't seem to be intercepting ALL the traffic on the system. For example, when I upload or download a huge file from somewhere, I expect to see a lot of TDI_SEND or TDI_RECEIVE IRPs corresponding to the increase in traffic. With my driver loaded, I don't see any of that. I see a TDI_SEND or TDI_RECEIVE every now and then but for the most part, those seem to be largely missing. As an experiment, I compared the debug output of my driver side-by-side with output from TDIMON (from SysInternals), and the IRPs that I _do_ intercept seem to be correct. I just seem to be missing a bunch of them. I realize that I'm only hooking into TCP right now, but all my test scenarios have been TCP-based traffic so that shouldn't be a factor. So, does anyone have some insight into this? It may have been discussed here before, but I wasn't able to find much in the archives. One other question -- is there a safe way to unload this type of driver? I'm currently doing an IoDetachDevice() and IoDeleteDevice(), but soon after unloading I get a BSOD (I think the message that comes up is IRQL_ NOT_LESS_OR_EQUAL or something like that). If I just start the driver once and leave it running, it seems to be fine. Thanks in advance for any suggestions. -chris --- START CODE #include "ntddk.h" #include "tdikrnl.h" #include "tdi_drv.h" #define DEBUG 1 typedef struct _DEVICE_EXTENSION { // the top of the stack before this filter was added, a.k.a. the location // to which all Irps should be directed PDEVICE_OBJECT TopOfStack; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; // globals PDEVICE_OBJECT ptcpfilterdevice; NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status; int i; #if DEBUG DbgPrint("\n.\n.\nBeginning driver initialization\n"); #endif for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++) DriverObject->MajorFunction[i] = tdi_Dispatch; DriverObject->DriverUnload = tdi_Unload; status = tdi_InitializeAndAttach(DriverObject); #if DEBUG DbgPrint("tdi_InitializeAndAttach() return code: %08X\n", status); #endif return status; } NTSTATUS tdi_InitializeAndAttach( IN PDRIVER_OBJECT DriverObject ) { NTSTATUS status; PDEVICE_EXTENSION pdev_ext; UNICODE_STRING u_name; RtlInitUnicodeString(&u_name, L"\\Device\\Tcp"); // note: need same device type and characteristics as the thing we're // filtering. // create the filter device status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, // no device name FILE_DEVICE_NETWORK, // same as \Device\Tcp FILE_DEVICE_SECURE_OPEN, // same as \Device\Tcp FALSE, // non-exclusive &ptcpfilterdevice); #if DEBUG DbgPrint("IoCreateDevice() return code: %08X\n", status); DbgPrint(" ptcpfilterdevice: %08X\n", ptcpfilterdevice); #endif if (status) { DbgPrint("IoCreateDevice() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(ptcpfilterdevice->DeviceExtension, sizeof(DEVICE_EXTENSION)); pdev_ext = (PDEVICE_EXTENSION) ptcpfilterdevice->DeviceExtension; // attach to the Tcp chain and put a pointer to \Device\Tcp in the device // extension structure status = IoAttachDevice(ptcpfilterdevice, &u_name, &pdev_ext->TopOfStack); #if DEBUG DbgPrint("IoAttachDevice() return code: %08X\n", status); DbgPrint(" pdev_ext->TopOfStack = %08X\n", pdev_ext->TopOfStack); #endif if (status) { DbgPrint("IoAttachDevice() failed\n"); IoDeleteDevice(ptcpfilterdevice); return STATUS_INSUFFICIENT_RESOURCES; } return STATUS_SUCCESS; } VOID tdi_Unload( IN PDRIVER_OBJECT DriverObject ) { #if DEBUG DbgPrint("Unloading driver\n"); #endif // detach from the Tcp chain IoDetachDevice(((PDEVICE_EXTENSION) ptcpfilterdevice->DeviceExtension)->TopOfStack); // delete the filter device IoDeleteDevice(ptcpfilterdevice); } NTSTATUS tdi_Dispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION pirp_stack; pirp_stack = IoGetCurrentIrpStackLocation(Irp); #if DEBUG if (pirp_stack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) DbgPrint("tdi_Dispatch(): Passing %s->%s (major %02X, minor %02X)\n", XlatedIrpMajor[pirp_stack->MajorFunction], XlatedMJInternal[pirp_stack->MinorFunction], pirp_stack->MajorFunction, pirp_stack->MinorFunction); else DbgPrint("tdi_Dispatch(): Passing %s (major %02X, minor %02X)\n", XlatedIrpMajor[pirp_stack->MajorFunction], pirp_stack->MajorFunction, pirp_stack->MinorFunction); #endif // // Pass the IRP to the target without touching the IRP // IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(((PDEVICE_EXTENSION) DeviceObject->DeviceExtension)->TopOfStack, Irp); } --- END CODE --- You are currently subscribed to ntdev as: $subst('Recip.EmailAddr') To unsubscribe send a blank email to leave-ntdev-$subst('Recip.MemberIDChar')@lists.osr.com
  Message 2 of 3  
28 Jan 02 05:42
foxgen@yandex
xxxxxx@yandex.ru
Join Date: 26 Oct 2001
Posts To This List: 66
Re: TDI Filter Driver, part II

1. If you want to intercept all data, you should also intercept callbacks, that protocol driver(tcpip) registers ... (see help for TDI_SET_EVENT_HANDLER) if you dont intercept these callbacks you will be able to get OUTGOING data and very very little of INCOMING data ... 2. your driver crashes, because there are some open connections ... If you close all connections and stop the driver It wont crash ... ----- Original Message ----- From: "Chris Eng" <xxxxx@connick.com> To: "NT Developers Interest List" <xxxxx@lists.osr.com> Sent: Saturday, January 26, 2002 9:37 AM Subject: [ntdev] TDI Filter Driver, part II > Hello all, > > I posted here a few days ago asking for help with a TDI driver that would > let me observe all TCP/IP traffic on my system. Several people pointed > out that my initial approach -- trying to register an event handler with > the lower level device -- would not work, and suggested I go with a TDI > filter driver instead. > <...excess quoted lines suppressed...> Win2K > drivers, so it's not something I really want to sink a lot of cash into.) > > Anyway, based on those suggestions plus some other random postings, I > came up with the code at the end of this message. Right now it's just a > passthrough -- it intercepts all the IRPs for \Device\Tcp, prints out a > little message with DbgPrint(), and then passes the IRP down to the lower > level device. > > This seems to work, sort of, in the sense that all networking-related > functionality is still intact. However, I notice that I don't seem to be location > // to which all Irps should be directed > PDEVICE_OBJECT TopOfStack; > > } DEVICE_EXTENSION, *PDEVICE_EXTENSION; > > // globals > PDEVICE_OBJECT ptcpfilterdevice; > > > NTSTATUS DriverEntry( \Device\Tcp > FILE_DEVICE_SECURE_OPEN, // same as \Device\Tcp > FALSE, // non-exclusive > &ptcpfilterdevice); > #if DEBUG > DbgPrint("IoCreateDevice() return code: %08X\n", status); > DbgPrint(" ptcpfilterdevice: %08X\n", ptcpfilterdevice); > #endif > if (status) { > DbgPrint("IoCreateDevice() failed\n"); > return STATUS_INSUFFICIENT_RESOURCES; > } sizeof(DEVICE_EXTENSION)); > pdev_ext = (PDEVICE_EXTENSION) ptcpfilterdevice->DeviceExtension; > > // attach to the Tcp chain and put a pointer to \Device\Tcp in the device > // extension structure > status = IoAttachDevice(ptcpfilterdevice, &u_name, &pdev_ext->TopOfStack); > #if DEBUG > DbgPrint("IoAttachDevice() return code: %08X\n", status); > DbgPrint(" pdev_ext->TopOfStack = %08X\n", pdev_ext->TopOfStack); > #endif > if (status) { > DbgPrint("IoAttachDevice() failed\n"); > IoDeleteDevice(ptcpfilterdevice); > return STATUS_INSUFFICIENT_RESOURCES; > } > %02X)\n", > XlatedIrpMajor[pirp_stack->MajorFunction], > XlatedMJInternal[pirp_stack->MinorFunction], > pirp_stack->MajorFunction, pirp_stack->MinorFunction); > else > DbgPrint("tdi_Dispatch(): Passing %s (major %02X, minor %02X)\n", > XlatedIrpMajor[pirp_stack->MajorFunction], > pirp_stack->MajorFunction, pirp_stack->MinorFunction); > #endif > > // --- You are currently subscribed to ntdev as: $subst('Recip.EmailAddr') To unsubscribe send a blank email to leave-ntdev-$subst('Recip.MemberIDChar')@lists.osr.com
  Message 3 of 3  
30 Jan 02 01:11
ntdev member 7638
xxxxxx@connick.com
Join Date:
Posts To This List: 3
Re: TDI Filter Driver, part II

bryan, i appreciate the suggestion and i will definitely get around to messing with NDIS at some point. however, one thing i want to avoid is binding to a specific adapter because i want to see traffic on localhost as well as traffic on various ethernet adapters. i'm really interested to get some feedback on the specific TDI issues i described in my original post -- there must be a good way to fix the problem, since TDIMON seems to be able to capture everything. i just don't know why mine doesn't! -chris ----- Original Message ----- From: "Bryan Burgin" <xxxxx@microsoft.com> To: <xxxxx@connick.com> Sent: Saturday, January 26, 2002 1:57 AM Subject: RE: [ntdev] TDI Filter Driver, part II > You could try writing a NDIS intermediate driver that sits between TCP/IP and the adapter miniport. See the PASSTHRU sample in the XP DDK. > > An intermediate driver has a miniport upper edge and a protocol lower edge. Where TCPIP's protocol edge normally binds to the miniport, you would sit in between. TCPIP would bind to your IM driver's miniport edge, there's an internal binding inside the driver. And then your driver's lower protocol edge binds to the original adapter/miniport. Basically, you just snap in between; all packets would flow through you. > > The NDIS library is not IRP based, but is call-back based. You would register your protocol and miniport via NdisRegisterProtocol and NdisMRegisterMiniport. Both of these calls inform NDIS of all your handler functions. NDIS then calls approprate handlers based on what's going on. > > I think you'll learn a lot about the internals of the system by going this route. > > Best of luck. > > Bryan S. Burgin > xxxxx@microsoft.com > > -----Original Message----- > From: Chris Eng [mailto:xxxxx@connick.com] > Sent: Fri 1/25/2002 10:37 PM > To: NT Developers Interest List <...excess quoted lines suppressed...> sizeof(DEVICE_EXTENSION)); > pdev_ext = (PDEVICE_EXTENSION) ptcpfilterdevice->DeviceExtension; > > // attach to the Tcp chain and put a pointer to \Device\Tcp in the device > // extension structure > status = IoAttachDevice(ptcpfilterdevice, &u_name, &pdev_ext->TopOfStack); > #if DEBUG > DbgPrint("IoAttachDevice() return code: %08X\n", status); > DbgPrint(" pdev_ext->TopOfStack = %08X\n", pdev_ext->TopOfStack); > #endif > if (status) { --- You are currently subscribed to ntdev as: $subst('Recip.EmailAddr') To unsubscribe send a blank email to leave-ntdev-$subst('Recip.MemberIDChar')@lists.osr.com
Posting Rules  
You may not post new threads
You may not post replies
You may not post attachments
You must login to OSR Online AND be a member of the ntdev list to be able to post.

All times are GMT -5. The time now is 13:51.


Copyright ©2005, OSR Open Systems Resourcs, Inc.
Based on vBulletin Copyright ©2000 - 2005, Jelsoft Enterprises Ltd.
Modified under license