Подскажите пожалуйста с реализацией TDI драйвера-фильтра.. У меня что-то не получается.. Приведу весь свой код TDI фильтра. Это мой первый драйвер, если что плиз не пинайте сильно.. Код (Text): #include <ntddk.h> #include <tdikrnl.h> PDEVICE_OBJECT g_TcpDeviceObject = NULL, // \Device\Tcp g_TcpOldDeviceObject = NULL, g_DeviceObject = NULL; // control device NTSTATUS DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); if (IrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL) { switch (IrpStack->MinorFunction) { case TDI_SEND: if (Irp->MdlAddress) { UCHAR mdlBuffer[IrpStack->Parameters.SendLength]; mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); if (mdlBuffer) { DbgPrint ("TDI_Driver[DROP]: Send: 0x%x\n", mdlBuffer); } } break; //case TDI_RECEIVE: // break; } } // IoSkipCurrentIrpStackLocation(Irp); // return IoCallDriver(g_TcpOldDeviceObject, Irp); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject) { #if DBG DbgPrint ("TDI_Driver: UnloadRoutine called\n"); #endif } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; int i; UNICODE_STRING usDeviceName; UNICODE_STRING usDeviceLinkName; UNICODE_STRING usTcpDeviceName; RtlInitUnicodeString (&usDeviceName, L"\\Device\\tdifilter"); RtlInitUnicodeString (&usDeviceLinkName, L"\\??\\tdifilter"); status = IoCreateDevice (DriverObject, 0, // sizeof(DEVICE_EXTENSION) &usDeviceName, 0, // FILE_DEVICE_UNCNOWN 0, TRUE, &g_DeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: g_DeviceObject IoCreateDevice error\n"); #endif return status; } status = IoCreateSymbolicLink (&usDeviceLinkName, &usDeviceName); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: IoCreateSymbolicLink error\n"); #endif IoDeleteDevice (g_DeviceObject); return status; } RtlInitUnicodeString (&usTcpDeviceName, L"\\Device\\Tcp"); status = IoCreateDevice (DriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, TRUE, // FALSE &g_TcpDeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: g_TcpDeviceObject IoCreateDevice error\n"); #endif IoDeleteDevice (g_DeviceObject); return status; } g_TcpDeviceObject->Flags |= DO_DIRECT_IO; // DO_BUFFERED_IO status = IoAttachDevice (g_TcpDeviceObject, &usTcpDeviceName, &g_TcpOldDeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: g_TcpOldDeviceObject IoAttachDevice error\n"); #endif IoDeleteDevice (g_TcpDeviceObject); IoDeleteDevice (g_DeviceObject); return status; } for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) DriverObject->MajorFunction[i] = DeviceDispatch; DriverObject->DriverUnload = UnloadRoutine; return status; } У меня возник ряд вопросов: 1. Правильная ли сама реализация? 2. Почему-то компилятор ругается на: UCHAR mdlBuffer[IrpStack->Parameters.SendLength]; по идее в IrpStack->Parameters.SendLength содержится длина.. 3. Как правильно передавать IPR далее по стеку? так: Код (Text): IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(g_TcpOldDeviceObject, Irp); или так: Код (Text): Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS;
эксперимент покажет как почему, ему же неизвестно значение IrpStack->Parameters.SendLength, и он не знает сколько памяти нужно выделить в стеке под локальную переменную.
Я имел ввиду правильно ли я вообще подключаю свой фильтр к TDI и tcp драйверу чтобы ловить IRP пакеты? А какой тогда размер выделять? что-то я не пойму тогда..
А что насчет этого вопроса? И еще, в функции выгрузки драйвера UnloadRoutine нужно ли удалять созданные девайсы? и нужно ли удалять символьный линк который я создаю?
А как еще реализовать динамический массив в драйвере? сделал так: Код (Text): CHAR *mdlBuffer; mdlBuffer = (CHAR *)malloc (IrpStack->Parameters.SendLength); mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); ... free(mdlBuffer); компилятор ругается: 1: 'malloc' undefined; assuming extern returning int 2: 'SendLength' : is not a member of '_unnamed' 3: 'free' undefined; assuming extern returning int
Сделал я, создался у меня драйвер.. Создал программку для его запуска. И.. Полего его загрузки сразуже синий экран выскочил, я даже не успел прочитать что там у меня на экране, как сразу же перезагрузился компьютер.. С тех пор у меня драйвер почему-то больше не запускается.. Ошибка на функции CreateService..
Dmitry_177 А номер ошибки посмотри... Скорее всего у тебя сервис существует... Открой реестр ветку HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services и удали папку с названием твоего сервиса... А чтобы винда не перегружалась открой свойства системы и найди настройки для выпадания в синий экран...
Разобрался я с запуском драйвера и с перезагрузкой компьютера, спасибо за помощь Переписал что там было написано на синем экране: *** STOP 0x0000007E (0xC0000005, 0xF70C86F6, 0xFA8A17E4, 0xFA8A14E0) *** tcpip.sys - Address F70C86F6 base at F70C0000, DateStamp 444775d3 может что-то и ненужное переписал, например первую строку.. Я же новичек Я как понимаю мой драйвер как-то неправильно подключается к tcpip драйверу.. Подскажите пожалуйста что я не так делаю.. Код вверху..
Код самого драйвера или ошибки который пишется на синем экране? Код драйвера в моем самом первом сообщении в этой теме.. А вот код ошибки я не знаю где пишется, что-то я ничего такого там не нашел..
код из первого сообщения в принципе не компилируем. как я выше написал 0x0000007E - это AFAIR UNHANDLED_KERNEL_EXEPTION, а 0xC0000005 - ошибка при доступе к памяти.
Вот код который у меня скомпилировался и вызывает синий экран.. Код (Text): #include <ntddk.h> #include <tdikrnl.h> PDEVICE_OBJECT g_TcpDeviceObject = NULL, // \Device\Tcp g_TcpOldDeviceObject = NULL, //g_udpfltobj = NULL, // \Device\Udp //g_udpoldobj = NULL, //g_ipfltobj = NULL, // \Device\RawIp //g_ipoldobj = NULL, g_DeviceObject = NULL; // control device //KSPIN_LOCK g_traffic_guard; NTSTATUS DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); char *mdlBuffer = 0; char usBuffer; //if (DeviceObject == g_TcpDeviceObject || DeviceObject == g_udpfltobj || DeviceObject == g_ipfltobj) if (IrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL) { switch (IrpStack->MinorFunction) { case TDI_SEND: if (Irp->MdlAddress) { mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); if (mdlBuffer) RtlCopyMemory (&usBuffer, mdlBuffer, 10); //(ULONG)IrpStack->Parameters.SendLength); if (usBuffer) { DbgPrint ("TDI_Driver[DROP]: Send: 0x%x\n", usBuffer); } } break; //case TDI_RECEIVE: // break; } } // IoSkipCurrentIrpStackLocation(Irp); // return IoCallDriver(g_TcpOldDeviceObject, Irp); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject) { #if DBG DbgPrint ("TDI_Driver: UnloadRoutine called\n"); #endif } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; int i; UNICODE_STRING usDeviceName; UNICODE_STRING usDeviceLinkName; UNICODE_STRING usTcpDeviceName; RtlInitUnicodeString (&usDeviceName, L"\\Device\\tdifilter"); RtlInitUnicodeString (&usDeviceLinkName, L"\\??\\tdifilter"); status = IoCreateDevice (DriverObject, 0, // sizeof(DEVICE_EXTENSION) &usDeviceName, 0, // FILE_DEVICE_UNCNOWN 0, TRUE, &g_DeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: g_DeviceObject IoCreateDevice error\n"); #endif return status; } status = IoCreateSymbolicLink (&usDeviceLinkName, &usDeviceName); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: IoCreateSymbolicLink error\n"); #endif IoDeleteDevice (g_DeviceObject); return status; } RtlInitUnicodeString (&usTcpDeviceName, L"\\Device\\Tcp"); status = IoCreateDevice (DriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, TRUE, // FALSE &g_TcpDeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: g_TcpDeviceObject IoCreateDevice error\n"); #endif IoDeleteDevice (g_DeviceObject); return status; } g_TcpDeviceObject->Flags |= DO_DIRECT_IO; // DO_BUFFERED_IO status = IoAttachDevice (g_TcpDeviceObject, &usTcpDeviceName, &g_TcpOldDeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("DriverEntry: g_TcpOldDeviceObject IoAttachDevice error\n"); #endif IoDeleteDevice (g_TcpDeviceObject); IoDeleteDevice (g_DeviceObject); return status; } for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) DriverObject->MajorFunction[i] = DeviceDispatch; DriverObject->DriverUnload = UnloadRoutine; return status; } Я хотел посмотреть в DebugView хотябы какие-нибудь сообщения, но там ничего не отобразилось, или не успело отобразиться как выскочил синий экран..
char *mdlBuffer = 0; mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); RtlCopyMemory (&usBuffer, mdlBuffer, 10) запись в нулевой указатель? не шарю ф сях....
Даже если абстрагироваться от теории написания драйверов, то результатом работы данного RtlCopyMemory() будет банальный buffer-overflow, с вероятной перезаписью сохраненного в стеке адреса возврата из DeviceDispatch(). А уж если и не дотянется до сохраненного EIP'a, то вполне себе перезапишет указатели mdlBuffer и IrpStack, что в последующем вызовет крах системы. Компилятор выделяет под переменную типа char 1 байт на стеке(выравнивание не рассматриваем здесь), как можно копировать в нее 10?
Сделал так: Код (Text): #include <ntddk.h> #include <tdikrnl.h> PDEVICE_OBJECT g_TcpDeviceObject = NULL, // \Device\Tcp g_TcpOldDeviceObject = NULL, //g_udpfltobj = NULL, // \Device\Udp //g_udpoldobj = NULL, //g_ipfltobj = NULL, // \Device\RawIp //g_ipoldobj = NULL, g_DeviceObject = NULL; // control device KSPIN_LOCK g_SpinLock; NTSTATUS DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); UCHAR *mdlBuffer; UCHAR usBuffer; KIRQL irql; KeAcquireSpinLock(&g_SpinLock, &irql); if (DeviceObject == g_TcpDeviceObject) // || DeviceObject == g_udpfltobj || DeviceObject == g_ipfltobj) { if (IrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL) { switch (IrpStack->MinorFunction) { case TDI_SEND: if (Irp->MdlAddress) { mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); if (mdlBuffer) { DbgPrint ("tdifilter: Send[DROP]: %x\n", mdlBuffer); } } KeReleaseSpinLock(&g_SpinLock, irql); Irp->IoStatus.Status = STATUS_SUCCESS; //Irp->IoStatus.Information = 0; if (Irp->PendingReturned) IoMarkIrpPending(Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); //return IoCallDriver (g_TcpOldDeviceObject, Irp); break; //case TDI_RECEIVE: // break; } } } KeReleaseSpinLock (&g_SpinLock, irql); Irp->IoStatus.Status = STATUS_SUCCESS; //Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject) { UNICODE_STRING usDeviceLinkName; #if DBG DbgPrint ("tdifilter: UnloadRoutine called\n"); #endif IoDeleteDevice (g_TcpOldDeviceObject); IoDeleteDevice (g_TcpDeviceObject); RtlInitUnicodeString (&usDeviceLinkName, L"\\??\\tdifilter"); IoDeleteSymbolicLink(&usDeviceLinkName); IoDeleteDevice (g_DeviceObject); #if DBG DbgPrint ("tdifilter: UnloadRoutine successfully comleted\n"); #endif } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; int i; UNICODE_STRING usDeviceName; UNICODE_STRING usDeviceLinkName; UNICODE_STRING usTcpDeviceName; #if DBG DbgPrint ("tdifilter: In DriverEntry\n"); DbgPrint ("tdifilter: RegistryPath = %ws\n", RegistryPath->Buffer); #endif DriverObject->DriverUnload = UnloadRoutine; for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) DriverObject->MajorFunction[i] = DeviceDispatch; RtlInitUnicodeString (&usDeviceName, L"\\Device\\tdifilter"); status = IoCreateDevice (DriverObject, 0, //sizeof(DEVICE_EXTENSION), &usDeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &g_DeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("tdifilter: g_DeviceObject IoCreateDevice error\n"); #endif return status; } RtlInitUnicodeString (&usDeviceLinkName, L"\\??\\tdifilter"); status = IoCreateSymbolicLink (&usDeviceLinkName, &usDeviceName); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("tdifilter: IoCreateSymbolicLink error\n"); #endif IoDeleteDevice (g_DeviceObject); return status; } RtlInitUnicodeString (&usTcpDeviceName, L"\\Device\\Tcp"); status = IoCreateDevice (DriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_TcpDeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("tdifilter: g_TcpDeviceObject IoCreateDevice error\n"); #endif IoDeleteSymbolicLink(&usDeviceLinkName); IoDeleteDevice (g_DeviceObject); return status; } g_TcpDeviceObject->Flags |= DO_DIRECT_IO; //DO_BUFFERED_IO; status = IoAttachDevice (g_TcpDeviceObject, &usTcpDeviceName, &g_TcpOldDeviceObject); if (!NT_SUCCESS(status)) { #if DBG DbgPrint ("tdifilter: g_TcpOldDeviceObject IoAttachDevice error\n"); #endif IoDeleteDevice (g_TcpDeviceObject); IoDeleteSymbolicLink(&usDeviceLinkName); IoDeleteDevice (g_DeviceObject); return status; } KeInitializeSpinLock(&g_SpinLock); #if DBG DbgPrint ("tdifilter: DriverEntry successfully comleted\n"); #endif return status; } Драйвер запускается, все нормальтно.. Но стоит только зайти на какойнибудь сайт или еще что-то, ну вобщем чтобы TCPIP трафик пошел, как вылетает сразу синий экран..=( Подскажите пожалуйста что не так?
Кстати вопрос интересный. Но я бы поставил его по другому: где можно найти реализацию примитивного TDI драйвера фильтра?
В TDI firewall я поразбирался.. Еще почитал я про физическую и вирткальную память.. Чисто теоретически я представляю себе как прочитать данные, а вот практически, что-то до меня не дойдет как это сделать программно..