Делаю перехват ClientEventReceive.. Но почему-то при вызове оригинальной функции: Код (Text): ntStatus = OldClientEventReceive(pBlockFromPagedLookasideList->EventContext, ConnectionContext, ReceiveFlags, BytesIndicated, BytesAvailable, BytesTaken, Tsdu, IoRequestPacket); выскакивает BSOD.. Подскажите пожалуйста, немогу я разобраться.. анализ дампа показывает следующее: tdifilter_testdriver.sys это и есть мой драйвер.. Никак не пойму почему ошибка на IoRequestPacket???
Похоже, OldClientEventReceive у Вас указывает куда то в неправильное место, иначе мы бы видели в стеке драйвер afd.sys или netbt.sys. Попробуйте трассировать в отладчике место вызова OldClientEventReceive. )) отладчик Вам указывает на вызов ф. OldClientEventReceive, это же ее последний параметр, не так ли?
Правильно указывает.. перед тем как сделать перехват, выводил адрес в DbgPrint, а потом при вызове оригинала опять выводил адрес OldClientEventReceive.. Они совпадают!
Вообще в TDI_SET_EVENT_HANDLER в IrpSp->Parameters содержится структура Код (Text): struct _TDI_REQUEST_KERNEL_SET_EVENT { LONG EventType; PVOID EventHandler; PVOID EventContext; } TDI_REQUEST_KERNEL_SET_EVENT, *PTDI_REQUEST_KERNEL_SET_EVENT; в EventHandler содержится адрес оригинальной ClientEventReceive? Собственно я и задаю в TDI_SET_EVENT_HANDLER адрес своей функции в EventHandler: Код (Text): ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventHandler = HookedClientEventReceive; А в EventContext задаю адрес на свою структуру, в которой хранится адрес оригинального контекста и функции: Код (Text): ((PTDI_REQUEST_KERNEL_SET_EVENT)&irpStack->Parameters)->EventContext = pBlockFromPagedLookasideList; Сам перехват проихродит.. данные Tsdu вывожу и все принятые данные показывается в DbgPrint, но при вызове оригинальной ClientEventReceive система падает... Вот никак не могу понять почему...
Блин!!! Разобрался TarasCo все правильно сказал, я действительно неправильно адрес передавал.. Подскажите пожалуйста еще про TDI_EVENT_RECEIVE_DATAGRAM, когда это устанавливается? Что за датаграммы? Используются ли они при обычном лазании по сайтам, использования аськи, всяких других программ общения и всяких почтовых программ? Что-то не совсем понимаю что за датаграммы такие..
перехватываю еще ClientEventChainedReceive сам перехват срабатывает, но данные почему-то из Tsdu немогу вытянуть.. Делаю так: Код (Text): NTSTATUS HookedClientEventChainedReceive(IN PVOID TdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG ReceiveLength, IN ULONG StartingOffset, IN PMDL Tsdu, IN PVOID TsduDescriptor) { UCHAR *sduBuffer; DbgPrint("tdi_sniffer: -------***BEGIN TDI_EVENT_CHAINED_RECEIVE***-------\n"); sduBuffer = MmGetSystemAddressForMdlSafe (Tsdu, LowPagePriority); DbgPrint(sduBuffer); DbgPrint("tdi_sniffer: --------***END TDI_EVENT_CHAINED_RECEIVE***--------\n"); return ((OLDCLIENTEVENTCHAINEDRECEIVE)((PCLIENTEVENTRECEIVECONTEXT)TdiEventContext)->EventHandler)(((PCLIENTEVENTRECEIVECONTEXT)TdiEventContext)->EventContext, ConnectionContext, ReceiveFlags, ReceiveLength, StartingOffset, Tsdu, TsduDescriptor); } т.к. в Tsdu содержится MDL адрес, вытягиваю данные функцией MmGetSystemAddressForMdlSafe.. и почему-то никакие принятые данные не отображаются..
TDI_EVENT_RECEIVE_DATAGRAM - этот обработчик используют датаграммные протоколы. Обычно это UDP или IP ( сырой сокет ). Соотвественно, при "обычном лазании по сайтам" используется TCP протокол, который не является датаграммным и данный обработчик не нужен По поводу ClientEventChainedReceive: Вы берете данные сразу сначала буфера, а там скорее всего заголовки протоколов. К началу буфера нужно прибавить параметр StartingOffset, чтобы получить указатель на данные.
Если хоть даже и заголовки протоколов, отображаться то они должны же... А еще я так делал, прибавлял: Код (Text): sduBuffer = MmGetSystemAddressForMdlSafe (Tsdu + StartingOffset, LowPagePriority); BSOD сразуже..
По Вашему DbgPrint волшебная функция, отображающая любые типы данных? Она всего лишь выводит строку печтатаемых символов, заканчивающуюся нулем-терминатором. Если StartingOffset != 0, начало буфера можно считать случайным и первым символом может быть например ноль ( это, кстати, очень-очень вероятно ) - что должно выводиться? Еще бы не было BSOD а . Нужно делать примерно так: Код (Text): UCHAR *sduBuffer; sduBuffer = MmGetSystemAddressForMdlSafe (Tsdu, LowPagePriority); sduBuffer += StartingOffset;
TarasCo Подскажи еще пожалуйста, а в каких случаях возникает TDI_EVENT_CHAINED_RECEIVE? Что-то я не пойму никак из DDK.. Скажи пример пожалуйста.. И тоже касается TDI_EVENT_RECEIVE_EXPEDITED.. Вот при лазании по сайтам, использования аськи и всяких других программ для общения, и всяких там почтовых клиентов.. Какие event-ы используются и в каких именно событиях и при каких именно приеме данных? Подскажи пожалуйста, т.к. я не очень это понимаю из DDK..
Всю механику описывать долго. Вам нужно перехватывать данные, передаваемые по TCP соединению? ТОгда Вам нужны три перехватчика: 1. Диспетчерский запрос TDI_RECEIVE. Его засылает драйвер afd, если клиентское приложение вызвало ф. recv и драйвер afd знает, что у tcpip есть данные ( до этого срабатывали нотификаторы типа ClientEventReceive ). 2. ClientEventReceive - драйвер tcpip зовет этот нотификатор для извещения о том, что есть принятые данные 3. ClientEventChainedReceive - вызывается в тех же случаях, что и ClientEventReceive, служит для оптимизации. Упрощенно говоря, если пришел TCP пакет, который не требует дополнительной обработки для сборки потока данных, его могут сразу прокинуть вверх клиенту - и если клиент не ступит, это позволит избежать лишних копирований данных. Что нужно учитывать: 1. Драйвер afd очень часто возвращает STATUS_DATA_NOT_ACCEPTED - это не значит, что ему не нужны данные, это значит, что он заберет их позже с помощью запроса TDI_RECEIVE. 2. Нотификаторы вызваются только в том случае, если у драйвера tcpip нет необработанного запроса TDI_RECEIVE. Т.е если наблюдать только за ClientEventReceive и ClientEventChainedReceive - можно не увидеть всех данных. Запрос TDI_RECEIVE может передаваться в возвращаемом параметре ф. ClientEventReceive, а может и через диспетчер IRP_MJ_INTERNAL_DEVICE_CONTROL
Я делал перехват TDI_RECEIVE: Код (Text): switch (irpStack->MajorFunction) { case IRP_MJ_INTERNAL_DEVICE_CONTROL: if (irpStack->MinorFunction == TDI_RECEIVE) { ntStatus = OldTcpIrpMjDeviceControl(DeviceObject, Irp); // вызов оригинальной функции DbgPrint("tdi_sniffer: -------***BEGIN TDI_RECEIVE***-------\n"); mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority); DbgPrint(mdlBuffer); DbgPrint("\n"); DbgPrint("tdi_sniffer: --------***END TDI_RECEIVE***--------\n"); return ntStatus; } Токо у меня ничего не пишется.. Скажи еще пожалуйста, а как тогда выводить строки в которых есть нули-терминанты, но которые не заканчиваются на них? Вот например с использованием моего этого драйвера при открытии странички в браузере, я почему-то вижу только HTTP заголовки, а принятую html-ку(которая по идее должна идти после заголовка) не вижу, иногда, очень редко проскочит какой-нибудь маленький кусочек html-ки.. А еще часто бывает просто абра-кадабра какая-то пишется...
TarasCo, еще как-то не понятно как скачиваются сами картинки.. вот к примеру html-ка скачивается а сами фотки и др. как?
картинки обычно скачиваются через другие соединения. Т.е броузер скачав главный html файл начинает его парсить и подгружать дополнительный контент. Разные броузеры это делают по разному - открывают различное количество соединений ( по одному соединению могут и несколько картинок передать ).
Сравнил я что у меня приходит в ethereal-е (сниффере) и что отображает мой драйвер.. а принципе все тоже самое(по TCP трафику) но у меня все также не полностью высвечиваются данные, вот например: при открытии в IE www-страницы мой драйвер пишет: и все, на этом обрыв данных хотя дальше тоже должно все быть.. а в ethereal-е все тоже самое т.е. начало тоже но там и продолжение есть..