태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

TDI Filter Driver 기초 코드

Posted 2008/08/13 10:28


댓글 하나가 운영자에겐 커다란 힘이 됩니다!

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

출처 : http://www.osronline.com/showThread.cfm?link=22886

위의 정보가 도움이 되셨나요? 그렇다면 댓글 하나만 남겨주세요.
댓글 하나가 운영자에겐 커다란 힘이 됩니다!

Write your message and submit
« PREV : 1 : ... 209 : 210 : 211 : 212 : 213 : 214 : 215 : 216 : 217 : ... 436 : NEXT »