TDI FILTER driver

Home Forums Discussions General TDI FILTER driver

Viewing 15 posts - 1 through 15 (of 62 total)
  • Author
    Posts
  • #5108
    Dmitry_177
    Participant

      У меня в драйвере не создается девайс и не аттачится потом к драйверу Tcp.. А перехватывается функция MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] драйвера Tcp. Исходящий трафик(MinorFunction=TDI_SEND) ловится отлично, а вот входящий почему-то нет..:( У кого есть какие соображения?

      #6277
      Vadim Smirnov
      Keymaster

        Ну так а что сделано чтобы получать входящий траффик? Обычно входящие данные идут через callbacks, соответственно нужно перехватывать их установку.

        ЗЫ К суппорту тема не имеет отношения, для подобных вопросов есть отдельная борда Windows Internals

        ЗЗЫ Тему отредактировал, следите за кодировкой…

        #6278
        Dmitry_177
        Participant

          Собственно сам перехват:

          в *.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 страничка.. Но этого почему-то нету..=(

          #6279
          Vadim Smirnov
          Keymaster

            Во-первых, до того как будет вызван оригинальный обработчик никаких данных в IRP TDI_RECEIVE нет и быть не может, так как IRP перехвачен на пути от приложения к сети, а не наоборот. Так можно только TDI_SEND поймать.

            Ну а во вторых, большинство TDI клиентов используют не IRPs с TDI_RECEIVE, а устанавливают callbacks на события с использованием TDI_SET_EVENT_HANDLER (в случае с receive это ClientEventReceive). В DDK все написано.

            #6280
            Dmitry_177
            Participant

              По поводу первого я уже сам догадался.. и попробовал вызывать оригинальную функцию в начале, а потом уже смотреть в IRP TDI_RECEIVE..=) Но всеравно и так не работает..

              Спасибо за наводку, буду разбираться..

              #6281
              Dmitry_177
              Participant

                В 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 содержатся принятые данные.. Как можно их вытащить от туда? Подскажите пожалуйста..

                #6282
                Dmitry_177
                Participant

                  Нужно перехватывать регистрацию 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?

                  #6283
                  Vadim Smirnov
                  Keymaster

                    IrpSp->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

                    #6284
                    Dmitry_177
                    Participant

                      Что-то я не пойму.. а как тогда хранить для каждого address object свой оригинал callback функции? и потом еще в самой callback функции определять какой оригинал вызывать..

                      tdi_fw-а я смотрел исходники..

                      #6285
                      Vadim Smirnov
                      Keymaster

                        Что-то я не пойму.. а как тогда хранить для каждого address object свой оригинал callback функции? и потом еще в самой callback функции определять какой оригинал вызывать..

                        Честно говоря, если после моего предыдущего пояснения остались вопросы, то может тогда не стоит и браться за подобный проект? Лучше возьмите за основу что-нибудь готовое, иначе на написание первого стабильного драйвера потратите уйму времени Да и TDI в Vista уже depreciated, так что стоит ли напрягаться…
                        🙄

                        Распишу что я имел ввиду. Для каждого address object аллокируем некую структуру, которую храним у себя например в списке. В этой структур помимо прочих полей, которые могут понадобится, мы сохраняем оригинальный адрес ClientEventReceive и оригинальный контекст, который должен быть в нее передан. В обработчике TDI_SET_EVENT_HANDLER с TDI_EVENT_RECEIVE подменяем оригинальную ClientEventReceive и контекст заменяем на адрес той структуры, которая у нас оборачивает address object. Соответсвенно, в новом обработчике ClientEventReceive имеем указатель на структуру с оригинальным обработчиком и контекстом. Теперь понятно? 8)

                        #6286
                        Dmitry_177
                        Participant

                          Спасибо за разъяснение…

                          Я уже спрашивал, так правильно будет перехватывать?

                          OldClientEventReceive = ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler;
                          if (OldClientEventReceive)
                          {
                             ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler = HookedClientEventReceive;
                          }

                          Ну и соответственно и контекст еще так же присвоить…

                          А еще, подскажете пожалуйста как в драйвере хранить список? Вроде как на уровне ядра подругому все, другие функции и т.д…

                          З.Ы. я не так давно изучаю ring0, многого еще не знаю.. 😳

                          #6287
                          Vadim Smirnov
                          Keymaster

                            Я уже спрашивал, так правильно будет перехватывать?

                            Да

                            Ну и соответственно и контекст еще так же присвоить…

                            Да

                            А еще, подскажете пожалуйста как в драйвере хранить список

                            Можешь свой список сделать. Можешь использовать встроенные односвязные или двухсвязные. Смотри функции:


                            InitializeListHead, ExInterlockedInsertHeadList, ExInterlockedInsertTailList, ExInterlockedRemoveHeadList, ExInterlockedPopEntryList, ExInterlockedPushEntryList, InsertHeadList, InsertTailList, IsListEmpty, KeInitializeSpinLock, PopEntryList, PushEntryList, RemoveEntryList, RemoveHeadList, RemoveTailList
                            #6288
                            Dmitry_177
                            Participant

                              Спасибо большое 🙂 Вы очень добры.. Буду разбираться..

                              #6289
                              Dmitry_177
                              Participant

                                Реализовал что-то наподобии, но у меня опять же таки не ловятся входящие пакеты и еще синий экран появляется.. Выложу весь код:

                                в *.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?

                                #6290
                                Dmitry_177
                                Participant

                                  SerpentFly, помоги пожалуйста.. Все что я смог сделать я отобразил это в коде.. Я реально зашел в тупик.. Помоги пожалуйста..

                                Viewing 15 posts - 1 through 15 (of 62 total)
                                • You must be logged in to reply to this topic.