Home › Forums › Discussions › General › TDI FILTER driver
- This topic has 61 replies, 2 voices, and was last updated 17 years, 4 months ago by Dmitry_177.
-
AuthorPosts
-
June 19, 2007 at 1:29 pm #5108
У меня в драйвере не создается девайс и не аттачится потом к драйверу Tcp.. А перехватывается функция MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] драйвера Tcp. Исходящий трафик(MinorFunction=TDI_SEND) ловится отлично, а вот входящий почему-то нет..:( У кого есть какие соображения?
June 19, 2007 at 1:51 pm #6277Ну так а что сделано чтобы получать входящий траффик? Обычно входящие данные идут через callbacks, соответственно нужно перехватывать их установку.
ЗЫ К суппорту тема не имеет отношения, для подобных вопросов есть отдельная борда Windows Internals
ЗЗЫ Тему отредактировал, следите за кодировкой…
June 19, 2007 at 3:49 pm #6278Собственно сам перехват:
в *.h файле:
PFILE_OBJECT pFile_tcp; PDEVICE_OBJECT pDev_tcp; PDRIVER_OBJECT pDrv_tcpip; typedef NTSTATUS (*OLDTCPIRPMJDEVICECONTROL)(IN PDEVICE_OBJECT, IN PIRP); OLDTCPIRPMJDEVICECONTROL OldTcpIrpMjDeviceControl;
в *.с файле:
UNICODE_STRING deviceTCPUnicodeString; WCHAR deviceTCPNameBuffer[] = L"\\Device\\Tcp"; RtlInitUnicodeString (&deviceTCPUnicodeString, deviceTCPNameBuffer); ntStatus = IoGetDeviceObjectPointer(&deviceTCPUnicodeString, FILE_READ_DATA, &pFile_tcp, &pDev_tcp); if(!NT_SUCCESS(ntStatus)) return ntStatus; pDrv_tcpip = pDev_tcp->DriverObject; OldTcpIrpMjDeviceControl = pDrv_tcpip->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]; if (OldTcpIrpMjDeviceControl) InterlockedExchange ((PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL], (LONG)HookedTcpDeviceControl); ... NTSTATUS HookedTcpDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION irpStack; UCHAR *mdlBuffer; irpStack = IoGetCurrentIrpStackLocation (Irp); switch (irpStack->MajorFunction) { case IRP_MJ_INTERNAL_DEVICE_CONTROL: if (irpStack->MinorFunction == TDI_SEND) { DbgPrint("tdifilter TDI_SEND"); mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); DbgPrint (mdlBuffer); } if (irpStack->MinorFunction == TDI_RECEIVE) { DbgPrint("tdifilter TDI_RECEIVE"); mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); DbgPrint (mdlBuffer); } break; default: break; } return OldTcpIrpMjDeviceControl(DeviceObject, Irp); }
по идее все должно ловиться и TDI_RECEIVE тоже.. Но почему-то этого не происходит.. Если я захожу на какойнибудь сайт, по идее там должны быть http-пакеты и html страничка.. Но этого почему-то нету..=(
June 19, 2007 at 8:04 pm #6279Во-первых, до того как будет вызван оригинальный обработчик никаких данных в IRP TDI_RECEIVE нет и быть не может, так как IRP перехвачен на пути от приложения к сети, а не наоборот. Так можно только TDI_SEND поймать.
Ну а во вторых, большинство TDI клиентов используют не IRPs с TDI_RECEIVE, а устанавливают callbacks на события с использованием TDI_SET_EVENT_HANDLER (в случае с receive это ClientEventReceive). В DDK все написано.
June 19, 2007 at 8:22 pm #6280По поводу первого я уже сам догадался.. и попробовал вызывать оригинальную функцию в начале, а потом уже смотреть в IRP TDI_RECEIVE..=) Но всеравно и так не работает..
Спасибо за наводку, буду разбираться..
June 20, 2007 at 10:49 am #6281В HookedTcpDeviceControl делаю так:
if (irpStack->MinorFunction == TDI_SET_EVENT_HANDLER) { if (((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventType == TDI_EVENT_RECEIVE) { ..... } }
Вот где точки, там в ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler по идее содержится адрес callback функции ClientEventReceive. В ней на сколько я понял в параметре Tsdu содержатся принятые данные.. Как можно их вытащить от туда? Подскажите пожалуйста..
June 20, 2007 at 9:12 pm #6282Нужно перехватывать регистрацию TDI_EVENT_RECEIVE event’а и менять указатель на свой…
Ловим:
MajorFunction=IRP_INTERNAL_DEVICE_CONTROL
MinorFunction=TDI_SET_EVENT_HANDLER
Parameters->EventType=TDI_EVENT_RECEIVEИз DDK я как понял в Parameters->EventHandler будет указатель на callback функцию ClientEventReceive, но как его поменять на свой? может так?:
OldClientEventReceive = ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler; if (OldClientEventReceive) { ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler = HookedClientEventReceive; }
А еще тогда в HookedClientEventReceive нужно вызывать оригинал:
return OldClientEventReceive(TdiEventContext, ConnectionContext, ReceiveFlags, BytesIndicated, BytesAvailable, BytesTaken, Tsdu, IoRequestPacket);
Как тогда все оригинальные адреса callback функций сохранять для разных потоков вызвавших TDI_SET_EVENT_HANDLER чтобы потом их вызывать в HookedClientEventReceive? Или может есть какойнибудь способ передавать этот адрес в саму функцию HookedClientEventReceive?
June 21, 2007 at 8:38 am #6283IrpSp->FileObject
Pointer to an open file object representing a local-node address. The transport uses the FsContext and, possibly, FsContext2 fields to access the state it maintains about this address.
Depending on the type of ClientEventXxx handler to be registered, this address might be or become associated with an established endpoint-to-endpoint connection made by this client.Хендлеры ставятся в контексте address object, то есть сохранять подменять нужно не для разных потоков, а для разных address object.
IrpSp->Parameters
Pointer to a TDI_REQUEST_KERNEL_SET_EVENT structure, defined as follows:
struct _TDI_REQUEST_KERNEL_SET_EVENT {
LONG EventType;
PVOID EventHandler;
PVOID EventContext;
} TDI_REQUEST_KERNEL_SET_EVENT, *PTDI_REQUEST_KERNEL_SET_EVENT;
The transport uses the members of this structure as follows:EventType
Specifies the type of ClientEventXxx handler to be registered (see Comments).
EventHandler
Specifies the entry point of the ClientEventXxx routine to be called when this type of event occurs. This member can be NULL if the client is deregistering a previously registered event handler.
EventContext
Specifies a pointer to be passed, uninterpreted by the transport, to the given ClientEventXxx routine whenever it is called. This member is NULL if EventHandler is NULL.Можно подменить EventContext на некую собственную структуру оборачивающую address object и содержащую указатель на оригинальный ClientEventReceive.
P.S. А вообще вместо изобретения велосипеда стоило заглянуть в Resources и сходить по ссылке http://sourceforge.net/projects/tdifw
June 21, 2007 at 3:47 pm #6284Что-то я не пойму.. а как тогда хранить для каждого address object свой оригинал callback функции? и потом еще в самой callback функции определять какой оригинал вызывать..
tdi_fw-а я смотрел исходники..
June 21, 2007 at 4:20 pm #6285Что-то я не пойму.. а как тогда хранить для каждого address object свой оригинал callback функции? и потом еще в самой callback функции определять какой оригинал вызывать..
Честно говоря, если после моего предыдущего пояснения остались вопросы, то может тогда не стоит и браться за подобный проект? Лучше возьмите за основу что-нибудь готовое, иначе на написание первого стабильного драйвера потратите уйму времени Да и TDI в Vista уже depreciated, так что стоит ли напрягаться…
🙄Распишу что я имел ввиду. Для каждого address object аллокируем некую структуру, которую храним у себя например в списке. В этой структур помимо прочих полей, которые могут понадобится, мы сохраняем оригинальный адрес ClientEventReceive и оригинальный контекст, который должен быть в нее передан. В обработчике TDI_SET_EVENT_HANDLER с TDI_EVENT_RECEIVE подменяем оригинальную ClientEventReceive и контекст заменяем на адрес той структуры, которая у нас оборачивает address object. Соответсвенно, в новом обработчике ClientEventReceive имеем указатель на структуру с оригинальным обработчиком и контекстом. Теперь понятно? 8)
June 21, 2007 at 5:19 pm #6286Спасибо за разъяснение…
Я уже спрашивал, так правильно будет перехватывать?
OldClientEventReceive = ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler; if (OldClientEventReceive) { ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler = HookedClientEventReceive; }
Ну и соответственно и контекст еще так же присвоить…
А еще, подскажете пожалуйста как в драйвере хранить список? Вроде как на уровне ядра подругому все, другие функции и т.д…
З.Ы. я не так давно изучаю ring0, многого еще не знаю.. 😳
June 21, 2007 at 6:16 pm #6287Я уже спрашивал, так правильно будет перехватывать?
Да
Ну и соответственно и контекст еще так же присвоить…
Да
А еще, подскажете пожалуйста как в драйвере хранить список
Можешь свой список сделать. Можешь использовать встроенные односвязные или двухсвязные. Смотри функции:
InitializeListHead, ExInterlockedInsertHeadList, ExInterlockedInsertTailList, ExInterlockedRemoveHeadList, ExInterlockedPopEntryList, ExInterlockedPushEntryList, InsertHeadList, InsertTailList, IsListEmpty, KeInitializeSpinLock, PopEntryList, PushEntryList, RemoveEntryList, RemoveHeadList, RemoveTailListJune 21, 2007 at 6:26 pm #6288Спасибо большое 🙂 Вы очень добры.. Буду разбираться..
June 26, 2007 at 10:02 pm #6289Реализовал что-то наподобии, но у меня опять же таки не ловятся входящие пакеты и еще синий экран появляется.. Выложу весь код:
в *.h файле:
typedef NTSTATUS (*OLDCLIENTEVENTRECEIVE)(IN PVOID, IN CONNECTION_CONTEXT, IN ULONG, IN ULONG, IN ULONG, OUT ULONG, IN PVOID, OUT PIRP); // структура про которую мы говорили typedef struct _CLIENTEVENTRECEIVECONTEXT { LIST_ENTRY ListEntry; PVOID EventHandler; PVOID EventContext; } CLIENTEVENTRECEIVECONTEXT, *PCLIENTEVENTRECEIVECONTEXT;
полный код драйвера в *.c файле
#include "ntddk.h" #include "TdiKrnl.h" #include "main.h" PPAGED_LOOKASIDE_LIST g_pPagedLookasideList; LIST_ENTRY g_ClientEventReceiveListHead; KSPIN_LOCK g_ClientEventReceiveListLock; NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { OldTcpIrpMjDeviceControl = NULL; g_pPagedLookasideList = ExAllocatePool(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST)); ExInitializePagedLookasideList(g_pPagedLookasideList, NULL, NULL, 0, sizeof(CLIENTEVENTRECEIVECONTEXT), 'tdis', 0); InitializeListHead(&g_ClientEventReceiveListHead); KeInitializeSpinLock(&g_ClientEventReceiveListLock); DriverObject->DriverUnload = OnUnload; return InstallDriverHook(); } NTSTATUS InstallDriverHook() { NTSTATUS ntStatus; UNICODE_STRING deviceTCPUnicodeString; WCHAR deviceTCPNameBuffer[] = L"\\Device\\Tcp"; pFile_tcp = NULL; pDev_tcp = NULL; pDrv_tcpip = NULL; RtlInitUnicodeString (&deviceTCPUnicodeString, deviceTCPNameBuffer); ntStatus = IoGetDeviceObjectPointer(&deviceTCPUnicodeString, FILE_READ_DATA, &pFile_tcp, &pDev_tcp); if(!NT_SUCCESS(ntStatus)) return ntStatus; pDrv_tcpip = pDev_tcp->DriverObject; OldTcpIrpMjDeviceControl = pDrv_tcpip->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]; if (OldTcpIrpMjDeviceControl) pDrv_tcpip->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HookedTcpDeviceControl; //InterlockedExchange ((PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL], (LONG)HookedTcpDeviceControl); return STATUS_SUCCESS; } NTSTATUS HookedTcpDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION irpStack; UCHAR *mdlBuffer; PCLIENTEVENTRECEIVECONTEXT pBlockFromPagedLookasideList; KIRQL irql; irpStack = IoGetCurrentIrpStackLocation (Irp); switch (irpStack->MajorFunction) { case IRP_MJ_INTERNAL_DEVICE_CONTROL: if (irpStack->MinorFunction == TDI_SEND) { DbgPrint("tdi_sniffer TDI_SEND:"); mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); DbgPrint (mdlBuffer); } if (irpStack->MinorFunction == TDI_SET_EVENT_HANDLER) { if (((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventType == TDI_EVENT_RECEIVE) { DbgPrint("tdi_sniffer TDI_SET_EVENT_HANDLER -> TDI_EVENT_RECEIVE"); pBlockFromPagedLookasideList = ExAllocateFromPagedLookasideList(g_pPagedLookasideList); memset(pBlockFromPagedLookasideList, 0, sizeof(CLIENTEVENTRECEIVECONTEXT)); KeAcquireSpinLock(&g_ClientEventReceiveListLock, &irql); InsertHeadList(&g_ClientEventReceiveListHead, &pBlockFromPagedLookasideList->ListEntry); // ñîõðàíÿåì îðèãèíàë ôóíêöèè â ñòðóêòóðå pBlockFromPagedLookasideList->EventHandler = ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler; // ñîõðàíÿåì îðèãèíàë êîíòåêñòà â ñòðóêòóðå pBlockFromPagedLookasideList->EventContext = ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventContext; ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler = HookedClientEventReceive; ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventContext = pBlockFromPagedLookasideList; KeReleaseSpinLock(&g_ClientEventReceiveListLock, irql); DbgPrint("tdi_sniffer ClientEventReceive Hooked..."); } } break; default: break; } return OldTcpIrpMjDeviceControl(DeviceObject, Irp); } NTSTATUS HookedClientEventReceive(IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT ULONG *BytesTaken, IN PVOID Tsdu, OUT PIRP *IoRequestPacket) { UCHAR *sduBuffer; PCLIENTEVENTRECEIVECONTEXT pBlockFromPagedLookasideList; OLDCLIENTEVENTRECEIVE OldClientEventReceive; pBlockFromPagedLookasideList = TdiEventContext; // â TdiEventContext ïî èäåå ñîäåðæèòñÿ óêàçàòåëü íà ìîþ ñòðóêòóðó OldClientEventReceive = pBlockFromPagedLookasideList->EventHandler; sduBuffer = Tsdu; DbgPrint("tdi_sniffer TDI_RECEIVE:"); DbgPrint(sduBuffer); // íåçíàþ êàê âûòàùèòü ïðèíÿòûå ïàêåòû èç Tsdu, åñëè îíè òàì íàõîäÿòñÿ èëè åùå ãäå, èç DDK ÿ ÷òî-òî íå ïîíÿë ãäå èìåííî îíè ñîäåðæàòñÿ // âûçûâàåì îðèãèíàë ôóíêöèè return OldClientEventReceive(pBlockFromPagedLookasideList->EventContext, ConnectionContext, ReceiveFlags, BytesIndicated, BytesAvailable, *BytesTaken, Tsdu, *IoRequestPacket); } NTSTATUS OnUnload(IN PDRIVER_OBJECT DriverObject) { if (OldTcpIrpMjDeviceControl) InterlockedExchange ((PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL], (LONG)OldTcpIrpMjDeviceControl); if (pFile_tcp != NULL) ObDereferenceObject(pFile_tcp); pFile_tcp = NULL; return STATUS_SUCCESS; }
Выгрузку списка и проверку на существующий в нем элемент я еще пока не делал, так что не обращайте на это внимания.. Подскажите пожалуйста правильно ли я понял суть со своей структурой и правильно ли я делаю? Почему-то всеравно не показываются входящие пакеты, даже DbgPrint(“tdi_sniffer TDI_RECEIVE:”); не показывается.. И подскажите пожалуйста как вытащить принятые пакеты и от куда их вообще нужно вытаскивать, из Tsdu?
June 28, 2007 at 11:48 am #6290SerpentFly, помоги пожалуйста.. Все что я смог сделать я отобразил это в коде.. Я реально зашел в тупик.. Помоги пожалуйста..
-
AuthorPosts
- You must be logged in to reply to this topic.