Storm
Гость
|
|
« : 14-04-2005 11:43 » |
|
Как фильтр-драйвер поставить на уже существующий в системе драйвер?
Ставим с помощью inf файла.
-------------------------------------------------------- Как просто запихнуть драйвер в систему, в общем, понятно. Но как показать связку - что "Этот" фильтрует "Это" и оба они знали об этом. Вроде бы надо в реестре в инфе о существующем драйвере создать поле UpperFilters (если верхний), а с каким значением, и где конкретно?
--------------------------------------------------------
Walter Oney читал - не понял.
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #1 : 22-04-2005 10:33 » |
|
Если имеется в виду подсоединиться на лету к уже работающему драйверу- это одно, а если просто зарегистрировать- это другое. Тут разница в том, что зарегестрированный драйвер вызовут в AddDevice, а вот присоединиться к уже работающему надо самому.
На лету( то есть драйвер давно загрузился и работает) только - перечислив все DeviceObjectы того кого хотите фильтровать и пдсоединившись к ним. Как грамотно перечислить объекты и какие неприятности могут возникнуть при подсоединеении не в AddDevice и как это обойти- тема отдельного очень большого разговора. А проблемы будут, это я обещаю.
|
|
« Последнее редактирование: 22-04-2005 10:36 от SlavaI »
|
Записан
|
|
|
|
zss
Участник
Offline
|
|
« Ответ #2 : 25-04-2005 06:15 » |
|
Если имеется в виду подсоединиться на лету к уже работающему драйверу- это одно, а если просто зарегистрировать- это другое. Тут разница в том, что зарегестрированный драйвер вызовут в AddDevice, а вот присоединиться к уже работающему надо самому.
На лету( то есть драйвер давно загрузился и работает) только - перечислив все DeviceObjectы того кого хотите фильтровать и пдсоединившись к ним. Как грамотно перечислить объекты и какие неприятности могут возникнуть при подсоединеении не в AddDevice и как это обойти- тема отдельного очень большого разговора. А проблемы будут, это я обещаю.
SlavaI, а можно немного подробнее - тоже очень интерисует этот вопрос
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #3 : 25-04-2005 07:38 » |
|
поподробнее неохота, очень много писать. Там целая статья выйдет.
|
|
|
Записан
|
|
|
|
zss
Участник
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
Участник
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
Главный специалист
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
Участник
Offline
|
|
« Ответ #7 : 28-04-2005 04:40 » |
|
Это оФФтоп
очень жаль
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #8 : 28-04-2005 07:11 » |
|
да я пошутил
|
|
|
Записан
|
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #10 : 08-05-2005 17:08 » |
|
можно
|
|
|
Записан
|
|
|
|
zss
Участник
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
Главный специалист
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
Участник
Offline
|
|
« Ответ #13 : 16-05-2005 09:08 » |
|
Спасибо за ответ - вроде все понятно тем не менее ненадежный код, ну да ладно.
Можно привести причины и последствия
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
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
Участник
Offline
|
|
« Ответ #15 : 17-05-2005 10:38 » |
|
А если поднять IRQL до DISPATH_LEVEL, тогда планировщик не запустится Но правда это сработает только на однопроцессорной машише - значит надо как-то еще блокировать планировщик
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #16 : 17-05-2005 11:12 » |
|
Полумера, но тоже вариант. HyperThread очень распространен сейчас.
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
Offline
|
|
« Ответ #17 : 17-05-2005 11:13 » |
|
Безопасно аттачиться только в AddDevice.
|
|
|
Записан
|
|
|
|
zss
Участник
Offline
|
|
« Ответ #18 : 15-07-2005 10:22 » |
|
Безопасно аттачиться только в AddDevice.
Но разве AddDevice вызывается не для PNP-устройств ? А если это не PNP драйвер - как быть ?
|
|
|
Записан
|
|
|
|
Viktor Denk
Участник
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 есть примерчик как это делать.
|
|
|
Записан
|
|
|
|
|