Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как поставить фильтр-драйвер на уже существующий в системе драйвер?  (Прочитано 20405 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Storm
Гость
« : 14-04-2005 11:43 » 

Как фильтр-драйвер поставить на уже существующий в системе драйвер?

Ставим с помощью inf файла.

--------------------------------------------------------
Как просто запихнуть драйвер в систему, в общем, понятно. Но как показать связку - что "Этот" фильтрует "Это" и оба они знали об этом.
Вроде бы надо в реестре в инфе о существующем драйвере создать поле UpperFilters (если верхний), а с каким значением, и где конкретно?

--------------------------------------------------------

Walter Oney читал - не понял.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #1 : 22-04-2005 10:33 » 

Если имеется в виду подсоединиться на лету к уже работающему драйверу- это одно, а если просто зарегистрировать- это другое. Тут разница в том, что зарегестрированный драйвер вызовут в AddDevice, а вот присоединиться к уже работающему надо самому.

На лету( то есть драйвер давно загрузился и работает) только - перечислив все DeviceObjectы того кого хотите фильтровать и пдсоединившись к ним.
Как грамотно перечислить объекты и какие неприятности могут возникнуть при подсоединеении не в AddDevice и как это обойти- тема отдельного очень большого разговора. А проблемы будут, это я обещаю.
« Последнее редактирование: 22-04-2005 10:36 от SlavaI » Записан
zss
Участник

ru
Offline Offline

« Ответ #2 : 25-04-2005 06:15 » 

Если имеется в виду подсоединиться на лету к уже работающему драйверу- это одно, а если просто зарегистрировать- это другое. Тут разница в том, что зарегестрированный драйвер вызовут в AddDevice, а вот присоединиться к уже работающему надо самому.

На лету( то есть драйвер давно загрузился и работает) только - перечислив все DeviceObjectы того кого хотите фильтровать и пдсоединившись к ним.
Как грамотно перечислить объекты и какие неприятности могут возникнуть при подсоединеении не в AddDevice и как это обойти- тема отдельного очень большого разговора. А проблемы будут, это я обещаю.

SlavaI, а можно немного подробнее - тоже очень интерисует этот вопрос Улыбаюсь
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #3 : 25-04-2005 07:38 » 

поподробнее неохота, очень много писать. Там целая статья выйдет.
Записан
zss
Участник

ru
Offline Offline

« Ответ #4 : 25-04-2005 08:24 » 

поподробнее неохота, очень много писать. Там целая статья выйдет.

Значит будет полезная статья для многих Улыбаюсь

ну можно не целиком, а по частям - а когда по ходу будут появляться вопросы - будет понятнее что спрашивать (можно прямо в этом топике - если ты не против:)

Если хочешь - то я могу начать Улыбаюсь

Итак - музыка sysinternals.com слова - народные Улыбаюсь (разбераем драйвер-вильтр ctrl2cap )


Для чего INIT - понятно, а зачем PAGE ?
Код:
#include "ntddk.h"
#include <ntddkbd.h>
#include "stdarg.h"
#include "stdio.h"
#include "ctrl2cap.h"
#include "ntddkbd.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, Ctrl2capDispatchGeneral)
#if WIN2K
#pragma alloc_text (PAGE, Ctrl2capAddDevice)
#pragma alloc_text (PAGE, Ctrl2capUnload)
#pragma alloc_text (PAGE, Ctrl2capPnP)
#pragma alloc_text (PAGE, Ctrl2capPower)
#endif // WIN2K
#endif // ALLOC_PRAGMA

Следующий код понятен
Инициализируем диспетчерские функции
Код:
NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    ULONG                  i;

    DbgPrint (("Ctrl2cap.SYS: entering DriverEntry\n"));

    //
    // Fill in all the dispatch entry points with the pass through function
    // and the explicitly fill in the functions we are going to intercept
    //
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {

        DriverObject->MajorFunction[i] = Ctrl2capDispatchGeneral;
    }

    //
    // Our read function is where we do our real work.
    //
    DriverObject->MajorFunction[IRP_MJ_READ] = Ctrl2capDispatchRead;

#if WIN2K
    //
    // Power IRPs are the only ones we have to handle specially under
    // Win2k since they require the special PoCallDriver and
    // PoStartNextPowerIrp function calls.
    //
    DriverObject->MajorFunction [IRP_MJ_POWER]  = Ctrl2capPower;

    //
    // The only reason we need to handle PnP IRPs is to know when
    // a device we've attached to disappears (is removed).
    //
    DriverObject->MajorFunction [IRP_MJ_PNP]  = Ctrl2capPnP;

    //
    // Under Win2K we get told about the presence of keyboard
    // devices through our AddDevice entry point.
    //
    DriverObject->DriverUnload = Ctrl2capUnload;
    DriverObject->DriverExtension->AddDevice = Ctrl2capAddDevice;

    return STATUS_SUCCESS;

#else  // WIN2K

    //
    // Under NT 4 we go out and hook the keyboard class device for
    // keyboard 0.
    //
    return Ctrl2capInit( DriverObject );
#endif // WIN2K
}

Далее интереснее...
Продолжение следует...
« Последнее редактирование: 20-12-2007 18:02 от Алексей1153++ » Записан
zss
Участник

ru
Offline Offline

« Ответ #5 : 25-04-2005 08:56 » 

Итак

Код:
NTSTATUS Ctrl2capInit( 
    IN PDRIVER_OBJECT DriverObject
    )
{
    CCHAR       ntNameBuffer[64];
    STRING       ntNameString;
    UNICODE_STRING    ntUnicodeString;
    PDEVICE_OBJECT    device;
    NTSTATUS          status;
    PDEVICE_EXTENSION devExt;
    WCHAR             messageBuffer[]  = L"Ctrl2cap Initialized\n";
    UNICODE_STRING    messageUnicodeString;

    //
    // Создаем UNICODE строку \\Device\\KeyboardClass0
    //
    sprintf( ntNameBuffer, "\\Device\\KeyboardClass0" );
    RtlInitAnsiString( &ntNameString, ntNameBuffer );
    RtlAnsiStringToUnicodeString( &ntUnicodeString, &ntNameString, TRUE );

    //
    // создаем объект-устройство
    //
    status = IoCreateDevice( DriverObject,
                             sizeof(DEVICE_EXTENSION),
                             NULL,
                             FILE_DEVICE_KEYBOARD,
                             0,
                             FALSE,
                             &device );

    if( !NT_SUCCESS(status) ) {

        // Если неудачно - то подчищаем за собой
        DbgPrint(("Ctrl2cap: Keyboard hook failed to create device!\n"));
        RtlFreeUnicodeString( &ntUnicodeString );
        return STATUS_SUCCESS;
    }


// А вот далее не все понятно. Я попробую предположить - а пусть меня кто-нибудь поправит если я неправ
//1. Подчищаем DeviceExtension (правдо непонятно зачем) и получаем на него указатель
    RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION));
    devExt = (PDEVICE_EXTENSION) device->DeviceExtension;

//2. Для чего эти флаги ?   
    device->Flags |= DO_BUFFERED_IO;
    device->Flags &= ~DO_DEVICE_INITIALIZING;

// 3. Подрубаемся к вершине стека драйверов
    status = IoAttachDevice( device, &ntUnicodeString, &devExt->TopOfStack );

    if( !NT_SUCCESS(status) ) {

   // еСли неудачно - подчищаем
        DbgPrint(("Ctrl2cap: Connect with keyboard failed!\n"));
        IoDeleteDevice( device );
        RtlFreeUnicodeString( &ntUnicodeString );
        return STATUS_SUCCESS;
    }

    // Если все удачно - все равно убираем мусор :)
    RtlFreeUnicodeString( &ntUnicodeString );
    DbgPrint(("Ctrl2cap: Successfully connected to keyboard device\n"));

    // Выводи сообщение
    RtlInitUnicodeString (&messageUnicodeString,
                          messageBuffer );
    ZwDisplayString( &messageUnicodeString );
    return STATUS_SUCCESS;
}

Или это все оффтоп ?
« Последнее редактирование: 25-04-2005 08:59 от zss » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #6 : 27-04-2005 16:34 » 

Это оФФтоп
Этот кривяк написал Руссинович?
Объясняю по пунктам -
PAGED значит страницы кода этой секции могут быть скинуты в pagefile( именно туда, а не просто убраны как в случае обыкновенных исполняемых файлов ).
Обнуляют выделенную память- на всякий случай, чего в этом странного?
Флаги- DO_BUFFERED_IO смотри в DDK, это про буфера. Хотя по уму флаги работы с буферами надо наследовать. DO_DEVICE_INITIALIZING означает что устройство проинициализировано.
 А на самом деле код содержит багу, очень тонкий момент в винде есть, касающийся атаченья к стеку, функция для исправления которго появилась по моему только в XP, хотя меры предосторожности можно и самому предпринять, хотя бы в синяк не упадет и даже работать будет. Ну нельзя так аттачиться на уже инициализированном стеке!  Плюс ко всему нужны меры пердосторожности при копировании IO_STACK_LOCATION, особенно удивится тот кто сделает это в TDI фильтре- очень редко но он будет стабильно получать BSOD с ошикой no more stack locations.
 К сожалению даже авторы из Microsoft не всегда следуют своим советам. Винда к сожалению уже представляет из себя набор неочевиндных правил с большим числом исключений. Вот он результат скрытия исходного кода и информации о системе.
« Последнее редактирование: 27-04-2005 16:40 от SlavaI » Записан
zss
Участник

ru
Offline Offline

« Ответ #7 : 28-04-2005 04:40 » 

Это оФФтоп

очень жаль Жаль
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #8 : 28-04-2005 07:11 » 

да я пошутил
Записан
zss
Участник

ru
Offline Offline

« Ответ #9 : 05-05-2005 11:24 » 

тоесть можно продолжать задавать вопросы Улыбаюсь
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #10 : 08-05-2005 17:08 » 

можно
Записан
zss
Участник

ru
Offline Offline

« Ответ #11 : 10-05-2005 05:53 » 

Приатачился так
Код:
NTSTATUS NTAPI AttachDevice (IN PDRIVER_OBJECT driverObject){

NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING deviceName = {0};
PFILTER_EXTENSION extension = NULL;
PDEVICE_OBJECT device = NULL;

if (filterDevice) return STATUS_SUCCESS;

status = IoCreateDevice (driverObject, FILTER_EXTENSION_, NULL,
FILE_DEVICE_UNKNOWN, 0, TRUE, &filterDevice);

if (!NT_SUCCESS (status)){

    #ifdef DBG
    DbgPrint(("WPC: Couldn't create filter device (AttachDevice)\n"));
    #endif
    return status;
}

extension = (PFILTER_EXTENSION) filterDevice->DeviceExtension;
RtlZeroMemory(extension, FILTER_EXTENSION_);

RtlInitUnicodeString(&deviceName, FILTER_DEVICE_NAME);
status = IoGetDeviceObjectPointer (&deviceName, FILE_READ_DATA, &extension->fileObject, &device);

if (!NT_SUCCESS (status)){

    #ifdef DBG
    DbgPrint(("WPC: Couldn't get target device object pointer (AttachDevice)\n"));
    #endif
    IoDeleteDevice(filterDevice);
    return status;
}

driverObject->DriverUnload = NULL;
extension->topStack = IoAttachDeviceToDeviceStack (filterDevice, device);
if (!extension->topStack){

    #ifdef DBG
    DbgPrint(("WPC: Couldn't attach filter device (AttachDevice)\n"));
    #endif
    ObDereferenceObject (extension->fileObject);
    IoDeleteDevice(filterDevice);
    driverObject->DriverUnload = DriverUnload;
    return status;
}

filterDevice->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
filterDevice->Flags &= ~DO_DEVICE_INITIALIZING;

return status;
}

Вроде все пашет Улыбаюсь

Вопрос:
1. Они атачатся к уже существующему девайсу драйвера по его имени. А можно ли получить указатель на драйвер, а после посмотреть все созданные им девайсы ?
2. А если девайсы неименованные ?
« Последнее редактирование: 20-12-2007 18:07 от Алексей1153++ » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #12 : 14-05-2005 07:58 » 

<Вроде все пашет >-
тем не менее ненадежный код, ну да ладно.
По первому вопросу- да можно, но до Windows XP очень осторожно. Драйвер референсиш по имени через ObReferenceObjectByName (ObReferenceObjectByName(&usDriverName,OBJ_CASE_INSENSITIVE,NULL,FILE_READ_ACCESS,*IoDriverObjectType,KernelMode,NULL,&pDriverObject)), потом в поле DeviceObject берешь указатель на первый созданный им девайс, дале все девайсы для данного драйвера связаны в список через поле NextDevice. Но для безопасного хождения по списку надо захватить блокировку- она не экспортируется, поэтому начиная с Windows XP есть функция IoEnumerateDeviceObjectList.
По пункту 2 - смотри пункт 1. Кстати это случай файловых систем.
Записан
zss
Участник

ru
Offline Offline

« Ответ #13 : 16-05-2005 09:08 » 

Спасибо за ответ - вроде все понятно

тем не менее ненадежный код, ну да ладно.

Можно привести причины и последствия
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #14 : 17-05-2005 10:06 » 

Вот твой код

extension->topStack = IoAttachDeviceToDeviceStack (filterDevice, device);
!!!!!!!!!!!!!!!!!!
А вот тут вызывается планировщик и переключает на другой поток( или SMP машина и параллельный поток), который уже имеет указатель на самый нижний девай в стеке, вызывает IoGetAttachedDeviceReference а потом IoBuild_какой-то-там_Irp, а потом IoCallDriver, все BSOD гарантирован, так как у твоего объекта еще не проинициализировано поле filterDevice->Flags  а возможно и указатель extension->topStack, так как ты, надеюсь, понимаешь что между подсоединением к стеку и инициализацией extension->topStack может пройти достаточно много по меркам системы времени.

!!!!!!!!!!!!!!!!!!
if (!extension->topStack){

    #ifdef DBG
    DbgPrint(("WPC: Couldn't attach filter device (AttachDevice)\n"));
    #endif
    ObDereferenceObject (extension->fileObject);
    IoDeleteDevice(filterDevice);
    driverObject->DriverUnload = DriverUnload;
    return status;
}

filterDevice->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
« Последнее редактирование: 20-12-2007 18:08 от Алексей1153++ » Записан
zss
Участник

ru
Offline Offline

« Ответ #15 : 17-05-2005 10:38 » 

А если поднять IRQL до DISPATH_LEVEL, тогда планировщик не запустится
Но правда это сработает только на однопроцессорной машише - значит надо как-то еще блокировать планировщик
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #16 : 17-05-2005 11:12 » 

Полумера, но тоже вариант.
HyperThread очень распространен сейчас.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #17 : 17-05-2005 11:13 » 

Безопасно аттачиться только в AddDevice.
Записан
zss
Участник

ru
Offline Offline

« Ответ #18 : 15-07-2005 10:22 » 

Безопасно аттачиться только в AddDevice.

Но разве AddDevice вызывается не для PNP-устройств ? А если это не PNP драйвер - как быть ?
Записан
Viktor Denk
Участник

de
Offline Offline

« Ответ #19 : 07-09-2005 11:43 » 

поподробнее неохота, очень много писать. Там целая статья выйдет.

Значит будет полезная статья для многих Улыбаюсь

ну можно не целиком, а по частям - а когда по ходу будут появляться вопросы - будет понятнее что спрашивать (можно прямо в этом топике - если ты не против:)

Если хочешь - то я могу начать Улыбаюсь
...
Далее интереснее...
Продолжение следует...

Ну молодец!!! Гигант!!! Да и СлавеИ прибавит славы. А то он уже сколько времени грозится... Слав, просто воьзмешь ветку, дополнишь и, как по волшебству, статья готова!
Ураган! Держи до конца...
И вопросы:
1. PAGE тоже "криво"? Если "ДА", то как не криво?
2. "Хотя ао уму флаги надо наследовать..." - почему и как?
3. "Полумера, но тоже вариантююю" - а как должна "МЕРА" выгляветь?

Спасибо ВСЕМ!
Viktor
vetoshkin@mail333.com
Записан

A u nas v Sibiri!
AlexArt
Гость
« Ответ #20 : 09-09-2005 04:30 » 

У Numega Driver Studio есть примерчик как это делать.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines