Пишем простой драйвер под Windows для блокировки USB-устройств

    Вряд ли пользователь домашнего ПК заинтересуется тем, чтобы блокировать устройства на своем ПК. Но если дело касается корпоративной среды, то все становится иначе. Есть пользователи, которым можно доверять абсолютно во всем, есть такие, которым можно что-то делегировать, и есть те, кому доверять совсем нельзя. Например, вы заблокировали доступ к Интернету одному из пользователей, но не заблокировали устройства этого ПК. В таком случае пользователю достаточно просто принести USB-модем, и Интернет у него будет. Т.е. простым блокированием доступа к Интернету дело не ограничивается.

    Однажды примерно такая задача и стояла передо мной. Времени на поиск каких-либо решений в Интернете не было, да и они, как правило, небесплатные. Поэтому мне было проще написать такой драйвер, и его реализация отняла у меня один день.

    В этой статье я расскажу немного теоретическую часть, на основе которой все строится, и расскажу принцип самого решения.

    Также полные исходные коды могут быть найдены в папке USBLock хранилища git по адресу: https://github.com/anatolymik/samples.git.

    Структура DRIVER_OBJECT


    Для каждого загруженного драйвера система формирует структуру DRIVER_OBJECT. Этой структурой система активно пользуется, когда отслеживает состояние драйвера. Также драйвер отвечает за ее инициализацию, в частности за инициализацию массива MajorFunction. Этот массив содержит адреса обработчиков для всех запросов, за которые драйвер может отвечать. Следовательно, когда система будет посылать запрос драйверу, она воспользуется этим массивом, чтобы определить, какая функция драйвера отвечает за конкретный запрос. Ниже представлен пример инициализации этой структуры.

    for ( ULONG i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
    	DriverObject->MajorFunction[i] = DispatchCommon;
    }
    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
    DriverObject->DriverUnload = DriverUnload;
    DriverObject->DriverExtension->AddDevice = DispatchAddDevice; 

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

    NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ); 

    Как видно из примера, сначала весь массив MajorFunction инициализируется одним и тем же обработчиком. В реальности типов запросов больше, чем в примере. Поэтому предварительно весь массив инициализируется так, чтобы запросы, которые не поддерживаются драйвером, обрабатывались корректно. Например, завершались с ошибкой. После инициализации массива обычно инициализируются обработчики для тех запросов, за которые драйвер отвечает.

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

    Обратите внимание на то, что в поле DriverExtension->AddDevice устанавливается адрес обработчика, который вызывается всякий раз, когда система обнаруживает новое устройство, за работу которого драйвер отвечает. Данное поле может быть оставлено непроинициализированным, в таком случае драйвер не сможет обрабатывать это событие.

    Более подробно данная структура описана по адресу: https://msdn.microsoft.com/en-us/library/windows/hardware/ff544174(v=vs.85).aspx.

    Структура DEVICE_OBJECT


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

    NTSTATUS Dispatch( PDEVICE_OBJECT DeviceObject, PIRP Irp ); 

    Массив MajorFunction ранее упомянутой структуры DRIVER_OBJECT содержит адреса обработчиков именно с таким прототипом.

    Сама структура DEVICE_OBJECT всегда создается драйвером при помощи функции IoCreateDevice. Если система посылает запрос драйверу, то она всегда направляет его какому-либо DEVICE_OBJECT, как это следует из вышепредставленного прототипа. Также, прототип принимает второй параметр, который содержит адрес IRP-структуры. Эта структура описывает сам запрос, и она существует в памяти до тех пор, пока драйвер не завершит его. Запрос отправляется драйверу на обработку при помощи функции IoCallDriver как системой, так и другими драйверами.

    Также со структурой DEVICE_OBJECT может быть связано имя. Таким образом, этот DEVICE_OBJECT может быть найден в системе.

    Более подробно структура DEVICE_OBJECT описана по адресу: https://msdn.microsoft.com/en-us/library/windows/hardware/ff543147(v=vs.85).aspx. А структура IRP описана по адресу: https://msdn.microsoft.com/en-us/library/windows/hardware/ff550694(v=vs.85).aspx.

    Фильтрация


    Фильтрация являет собой механизм, который позволяет перехватывать все запросы, направленные к конкретному DEVICE_OBJECT. Чтобы установить такой фильтр, необходимо создать другой экземпляр DEVICE_OBJECT и прикрепить его к DEVICE_OBJECT, запросы которого необходимо перехватывать. Прикрепление фильтра выполняется посредством функции IoAttachDeviceToDeviceStack. Все DEVICE_OBJECT, прикрепленные к перехватываемому DEVICE_OBJECT, вместе с ним формируют так называемый стек устройства, как это изображено ниже.


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

    Наличие такого механизма позволяет добавлять функционал, которого нет изначально в драйверах. Например, таким образом, без доработки файловой системы FAT, поставляемой в Windows, можно добавить проверку прав доступа к файлам этой файловой системы.

    PnP менеджер


    PnP менеджер отвечает за диспетчеризацию устройств всей системы. В его задачи входит обнаружение устройств, сбор информации о них, загрузка их драйверов, вызов этих драйверов, управление аппаратными ресурсами, запуск и остановка устройств и их удаление.

    Когда драйвер той или иной шины обнаруживает устройства на своих интерфейсах, то для каждого дочернего устройства он создает DEVICE_OBJECT. Этот DEVICE_OBJECT также называют Physical Device Object или PDO. Затем посредством функции IoInvalidateDeviceRelations он уведомляет PnP менеджер о том, что произошли изменения на шине. В ответ на это PnP менеджер посылает запрос с minor кодом IRP_MN_QUERY_DEVICE_RELATIONS с целью запросить список дочерних устройств. В ответ на этот запрос драйвер шины возвращает список PDO. Ниже изображен пример такой ситуации.


    Как отражено на рисунке, в данном примере в качестве шины выступает драйвер USB-хаба. Конкретные DEVICE_OBJECT стека устройства этого хаба не изображены для краткости и с целью сохранения последовательности пояснений.

    Как только PnP менеджер получит список всех PDO, он по отдельности соберет всю необходимую информацию об этих устройствах. Например, будет послан запрос с minor кодом IRP_MN_QUERY_ID. Посредством этого запроса PnP менеджер получит идентификаторы устройства, как аппаратные, так и совместимые. Также PnP менеджер соберет всю необходимую информацию о требуемых аппаратных ресурсах самим устройством. И так далее.

    После того, как вся необходимая информация будет собрана, PnP менеджер создаст так называемую DevNode, которая будет отражать состояние устройства. Также PnP создаст ветку реестра для конкретного экземпляра устройства или откроет существующую, если устройство ранее подключалось к ПК.

    Следующая задача PnP — это запуск драйвера устройства. Если драйвер не был ранее установлен, тогда PnP будет ожидать установки. Иначе, при необходимости, PnP загрузит его и передаст ему управление. Ранее упоминалось, что поле DriverExtension->AddDevice структуры DRIVER_OBJECT содержит адрес обработчика, который вызывается всякий раз, когда система обнаруживает новое устройство. Прототип этого обработчика изображен ниже.

    NTSTATUS DispatchAddDevice( 
    	PDRIVER_OBJECT DriverObject, 
    	PDEVICE_OBJECT PhysicalDeviceObject 
    ); 

    Т.е. всякий раз, когда PnP обнаруживает устройство, управлением которого занимается тот или иной драйвер, вызывается зарегистрированный обработчик этого драйвера, где ему передается указатель на PDO. Информация об установленном драйвере также хранится в соответствующей ветке реестра.

    В задачу обработчика входит создание DEVICE_OBJECT и его прикрепление к PDO. Прикрепленный DEVICE_OBJECT также называют Functional Device Object или FDO. Именно этот FDO и будет отвечать за работу устройства и представление его интерфейсов в системе. Ниже представлен пример, когда PnP завершил вызов драйвера, отвечающего за работу устройства.


    Как отражено на примере, кроме драйвера самого устройства также могут быть зарегистрированы нижние и верхние фильтры класса устройства. Следовательно, если таковые имеются, PnP также загрузит их драйвера и вызовет их AddDevice обработчики. Т.е. порядок вызова драйверов следующий: сначала загружаются и вызываются зарегистрированные нижние фильтры, затем загружается и вызывается драйвер самого устройства, и в завершении загружаются и вызываются верхние фильтры. Нижние и верхние фильтры являются обычным DEVICE_OBJECT, которые создают драйвера и прикрепляют их к PDO в своих обработчиках AddDevice. Количество нижних и верхних фильтров не ограничено.

    В этот момент стеки устройств полностью сформированы и готовы к работе. Поэтому PnP посылает запрос с minor кодом IRP_MN_START_DEVICE. В ответ на этот запрос все драйвера стека устройства должны подготовить устройство к работе. И если в этом процессе не возникло проблем, тогда запрос завершается успешно. В противном случае, если любой из драйверов не может запустить устройство, тогда он завершает запрос с ошибкой. Следовательно, устройство не будет запущено.

    Также, когда драйвер шины определяет, что произошли изменения на шине, он посредством функции IoInvalidateDeviceRelations уведомляет PnP о том, что следует заново собрать информацию о подключенных устройствах. В этот момент драйвер не удаляет ранее созданный PDO. Просто при получении запроса с minor кодом IRP_MN_QUERY_DEVICE_RELATIONS он не включит этот PDO в список. Затем PnP на основании полученного списка опознает новые устройства и устройства, которые были отключены от шины. PDO отключенных устройств драйвер удалит тогда, когда PnP пошлет запрос с minor кодом IRP_MN_REMOVE_DEVICE. Для драйвера этот запрос означает, что устройство более никем не используется, и оно может быть безопасно удалено.

    Более подробную информацию о модели драйверов WDM можно найти по адресу: https://msdn.microsoft.com/en-us/library/windows/hardware/ff548158(v=vs.85).aspx.

    Суть решения


    Суть самого решения заключается в создании верхнего фильтра класса USB-шины. Зарезервированные классы можно найти по адресу: https://msdn.microsoft.com/en-us/library/windows/hardware/ff553419(v=vs.85).aspx. Нас интересует класс USB с GUID равным 36fc9e60-c465-11cf-8056-444553540000. Как гласит MSDN, этот класс используется для USB хост контроллеров и хабов. Однако практически это не так, этот же класс используется, например, flash-накопителями. Это немного добавляет нам работы. Код обработчика AddDevice представлен ниже.

    NTSTATUS UsbCreateAndAttachFilter( 
    	PDEVICE_OBJECT PhysicalDeviceObject, 
    	bool UpperFilter 
    ) {
    
    	SUSBDevice*		USBDevice;
    	PDEVICE_OBJECT		USBDeviceObject = nullptr;
    
    	ULONG			Flags;
    
    	NTSTATUS		Status = STATUS_SUCCESS;
    
    	PAGED_CODE();
    
    	for ( ;; ) {
    
    		// если нижний фильтр уже прикреплен, тогда здесь больше делать нечего
    		if ( !UpperFilter ) {
    			USBDeviceObject = PhysicalDeviceObject;
    			while ( USBDeviceObject->AttachedDevice ) {
    				if ( USBDeviceObject->DriverObject == g_DriverObject ) {
    					return STATUS_SUCCESS;
    				}
    				USBDeviceObject = USBDeviceObject->AttachedDevice;
    			}
    		}
    
    		// создаем фильтр
    		Status = IoCreateDevice(
    			g_DriverObject,
    			sizeof( SUSBDevice ),
    			nullptr,
    			PhysicalDeviceObject->DeviceType,
    			PhysicalDeviceObject->Characteristics,
    			false,
    			&USBDeviceObject
    		);
    		if ( !NT_SUCCESS( Status ) ) {
    			break;
    		}
    
    		// инициализируем флаги созданного устройства, копируем их из объекта к 
    		// которому прикрепились
    		Flags = PhysicalDeviceObject->Flags & 
    		 (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);
    		USBDeviceObject->Flags |= Flags;
    
    		// получаем указатель на нашу структуру
    		USBDevice = (SUSBDevice*)USBDeviceObject->DeviceExtension;
    
    		// инициализируем деструктор
    		USBDevice->DeleteDevice = DetachAndDeleteDevice;
    
    		// инициализируем обработчики
    		for ( ULONG i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
    			USBDevice->MajorFunction[i] = UsbDispatchCommon;
    		}
    		USBDevice->MajorFunction[IRP_MJ_PNP] = UsbDispatchPnp;
    		USBDevice->MajorFunction[IRP_MJ_POWER] = UsbDispatchPower;
    
    		// инициализируем семафор удаления устройства
    		IoInitializeRemoveLock( 
    			&USBDevice->Lock, 
    			USBDEVICE_REMOVE_LOCK_TAG, 
    			0, 
    			0 
    		);
    
    		// заполняем структуру
    		USBDevice->SelfDevice = USBDeviceObject;
    		USBDevice->BaseDevice = PhysicalDeviceObject;
    		USBDevice->UpperFilter = UpperFilter;
    
    		// инициализируем paging семафор
    		USBDevice->PagingCount = 0;
    		KeInitializeEvent( &USBDevice->PagingLock, SynchronizationEvent, true );
    
    		// прикрепляем устройство к PDO
    		USBDevice->LowerDevice = IoAttachDeviceToDeviceStack( 
    			USBDeviceObject, 
    			PhysicalDeviceObject 
    		);
    		if ( !USBDevice->LowerDevice ) {
    			Status = STATUS_NO_SUCH_DEVICE;
    			break;
    		}
    
    		break;
    
    	}
    
    	// в зависимости от результата делаем
    
    	if ( !NT_SUCCESS( Status ) ) {
    
    		// отчистку
    
    		if ( USBDeviceObject ) {
    			IoDeleteDevice( USBDeviceObject );
    		}
    
    	} else {
    
    		// или сбрасываем флаг инициализации
    		USBDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    
    	}
    
    	return Status;
    
    }
    
    static NTSTATUS DispatchAddDevice( 
    	PDRIVER_OBJECT DriverObject, 
    	PDEVICE_OBJECT PhysicalDeviceObject 
    ) {
    
    	UNREFERENCED_PARAMETER( DriverObject );
    
    	return UsbCreateAndAttachFilter( PhysicalDeviceObject, true );
    
    }

    Как следует из примера, мы создаем DEVICE_OBJECT и прикрепляем его к PDO. Таким образом, мы будем перехватывать все запросы, направленные к USB-шине.

    В нашу задачу входит перехватывать запросы с minor кодом IRP_MN_START_DEVICE. Код обработчика этого запроса изображен ниже.

    static NTSTATUS UsbDispatchPnpStartDevice( SUSBDevice* USBDevice, PIRP Irp ) {
    
    	bool		HubOrComposite;
    	NTSTATUS	Status;
    
    	PAGED_CODE();
    
    	for ( ;; ) {
    
    		// проверить, позволено ли устройству работать, также обновить
    		// информацию об устройстве, является ли оно хабом или композитным
    		Status = UsbIsDeviceAllowedToWork( &HubOrComposite, USBDevice );
    		if ( !NT_SUCCESS( Status ) ) {
    			break;
    		}
    		USBDevice->HubOrComposite = HubOrComposite;
    
    		// продвинуть запрос
    		Status = ForwardIrpSynchronously( USBDevice->LowerDevice, Irp );
    		if ( !NT_SUCCESS( Status ) ) {
    			break;
    		}
    
    		break;
    
    	}
    
    	// завершаем запрос
    	Irp->IoStatus.Status = Status;
    	IoCompleteRequest( Irp, IO_NO_INCREMENT );
    
    	// и освобождаем устройство
    	IoReleaseRemoveLock( &USBDevice->Lock, Irp );
    
    	return Status;
    
    }

    Как изображено на рисунке, обработчик вызывает функцию UsbIsDeviceAllowedToWork. Эта функция выполняет все необходимые проверки, чтобы определить, разрешено ли устройству работать. В первую очередь функция позволяет всегда работать хабам и композитным устройствам, клавиатурам и мышам. А также тем устройствам, которые находятся в списке разрешенных. Если функция возвращает неуспешный код возврата, тогда запрос завершается с ошибкой. Таким образом, работа устройства будет заблокирована.

    Обратите внимание: функция определяет, является ли устройство хабом или композитным устройством. Это необходимо потому, что, как уже было упомянуто, класс устройств, который используется для хабов и хост контроллеров, используется не только этими устройствами. А нам в первую очередь необходимо контролировать дочерние устройства только хабов, хост контроллеров и композитных устройств. Т.е. для хабов и композитных устройств дополнительно перехватывается запрос перечисления дочерних устройств, на этом этапе, важно также прикрепить ко всем дочерним устройствам фильтр, и этот фильтр будет нижним. В противном случае контроль над дочерними устройствами будет потерян.

    Все упомянутые определения выполняются на основе идентификаторов устройств.

    Заключение


    Несмотря на свою простоту в моем случае данный драйвер достаточно эффективно решает поставленную задачу. Хотя из недостатков следует выделить обязательную перезагрузку после того, как список разрешенных устройств будет обновлен. Чтобы устранить этот недостаток, драйвер потребуется несколько усложнить. Еще большим недостатком является полное блокирование устройства, а не частичное. Описание, представленное выше, не раскрывает всех деталей реализации. Сделано это было намеренно, и упор был сделан больше на саму концепцию. Желающие разобраться во всем до конца могут ознакомиться с исходным кодом.
    Аладдин Р.Д. 81,65
    Информационная безопасность
    Поделиться публикацией
    Комментарии 88
    • НЛО прилетело и опубликовало эту надпись здесь
      • –1
        Очень интересное утверждение.

        На счет шаблонов, а где их нет?

        Я правильно понимаю что конфиг udev/devd не портит USB? Т.е. если это драйвер, значит портит, а если конфиг, который читает драйвер, то не портит. Так?

        Касательно конфигов, как уже было упомянуто, драйвер простой, его вполне можно доработать чтобы не требовалась перезагрузка. Более того, если идти дальше, можно много внести всяких гибкостей, например блокирование записи и т.д. У вас это получиться на других системах простой правкой конфига?
        • +3
          Функционала UDEV хватит, чтобы писать гибкие правила проверки и блокировки устройств, в том числе и с привязкой к временным промежуткам)
          • –1
            Хватит. Но когда речь идет о гибкости которая не заложена, по-моему, подобный подход решит эту проблему. Я не утверждал о простой блокировки записи. Безусловно мы его смешиваем с анализом и принятием решения динамически. В прошлом посте я выразился не точно. Извиняюсь.

            Ну и речь в статье, все-таки не об UDEV)))
            • +2
              Дорогой автор, успокойтесь)) Ваша статья, как «вводный краткий курс» в системное программирование под ОС семейства MS Windows, имеет место быть — в свое время она бы мне помогла. Вот если бы Вы в статье уделили внимание еще и написанию inf-файлов, было бы совсем хорошо. А вот мониторить и конфигурировать драйвер можно через WMI-интерфейс.
              • –1
                конфигурировать драйвер можно через WMI-интерфейс

                Расскажите, как с USB решить дело. Я решений не искал. Было бы интересно узнать.
                • +2
                  Приведу просто ссылку — вот
                  • –1
                    WMI будет работать только когда драйвер его поддерживает. Драйвер шины USB поддерживает соответствующий функционал и предоставляет для него интерфейсы? Вопрос заключался в этом.
                    • +2
                      Он будет поддерживаться, если вы в драйвере зарегистрируете соответствующего агента)) В DDK все описано и есть примеры.
                      • –1
                        Еще раз, драйвер USB в Windows, его поддерживает? И если да, то какие интерфейсы управления он предоставляет?
                        • +2
                          Еще раз отвечаю, зачем Вам знать, поддерживает ли этот интерфейс существующий драйвер USB? Вы в своем фильтр-драйвере его поддержите и настраиваете с помощью него свои «белые (черные)» списки)
                          • –1
                            Драйвер USB шины, должен зарегистрироваться с WMI как провайдер. Иначе он не будет управляться через WMI.

                            Вы в своем фильтр-драйвере его поддержите и настраиваете с помощью него свои «белые (черные)» списки)

                            А тогда фильтр зачем?
                            • +3
                              А Вы разве не фильтр-драйвер написали? В своей статье Вы так его и обозвали — фильтр верхнего уровня.
                              • –3
                                А это вопрос к вам был? Зачем фильтр, если через WMI управлять можно? Вы утверждали что в фильтре надо это сделать.
                                • +2
                                  Фух, устал я)) Ваш фильтр-драйвер Вам нужен для реализации Вашей логики блокировки подключения «ненужных» USB-устройств. А вот конфигурировать список «ненужных» USB-устройств предлагаю реализовать через WMI. Вот и все. Сами же писали, что в этом у вас недоработка, что при изменении списка «ненужных» USB-устройств требуется перезагрузить компьютер.
                                  • –5
                                    Недоработка и недостаток не одно и тоже.

                                    А прикрутив я WMI к своему фильтру, чтобы я выиграл стратегически? Кроме потерянного времени?
                                    • +4
                                      Вот за то время, которое Вы потратили на пререкания со мной, Вы могли бы уже прикрутить к своему драйверу провайдер WMI, и время не было бы потрачено зря — Вам новые знания, Вашим читателям польза. И, по моему сугубо-субъективному мнению, время, потраченное на приобретение новых знаний и применение этих знаний на практике, никогда не станет потерянным. Я не вижу смысла продолжать эту ветвь комментариев — засим откланиваюсь.
                                      • –4
                                        Ваша позиция понятна. «В интернете кто-то не прав» (С).
                            • 0
                              Тоже ссылку приведу: вот
            • НЛО прилетело и опубликовало эту надпись здесь
        • –8
          Автор начал с того, что существующие решения небесплатные, а затем сваял драйвер, который ещё нужно дорабатывать и — о чудо! — который нужно небесплатно подписать, чтобы он заработал на современных ОС.
          Я ничего не упустил?
          • +6
            Мне казалось, что заголовок гласит о написании, а не предложении абсолютно бесплатного решения.

            О каких современных ОС идет речь? Драйвер работает на всех ОС.
            • –8
              Любая статья предполагает обоснование необходимости.
              Если кодили just for fun — ок, но только Ваш fun малоинтересен. Уровня задачки начального курса программирования на уровне ядра. Да и справились Вы так себе — да и сами написали, что ещё пилить и пилить.
              Попробуйте использовать свой драйвер на любой поддерживаемой в настоящий момент 64-разрядной ОС Windows.
              • +5
                Использую, работает. Прежде чем утверждать подобное стоило бы проверить.

                Задача не just for fun, она вышла из практики, была реальная потребность. Если вам этот fun не интересен, поправьте, но по-моему, вас никто не заставляет давать какие-либо комментарии на этот счет. Если не интересно, зачем вообще читать?

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

                Справился безусловно так себе.

                А вообще, вы просто передергиваете мои слова, тем самым меняя смысл.
                • –8
                  Если задача из жизни, которую Вы не хотите, чтобы обсуждали — зачем о ней здесь писать? Хабр предполагает конструктивную критику, а не только восторженные вопли.
                  Вы пишите, что была реальная необходимость, и Вы задачу решили — эээ, в Вашей компании нет ни одного компьютера под управлением 64-разрядной ОС позже Windows 7 включительно? Вы так и не услышали: без подписи на этих системах драйвер работать не будет! Так в чём тогда интересность и ценность Вашего решения?
                  • +2
                    Например, вы заблокировали доступ к Интернету одному из пользователей, но не заблокировали устройства этого ПК. В таком случае пользователю достаточно просто принести USB-модем, и Интернет у него будет. Т.е. простым блокированием доступа к Интернету дело не ограничивается.

                    В самом начале, я написал практическую потребность, извиняюсь если написал размыто.

                    Вы пишите, что была реальная необходимость, и Вы задачу решили — эээ, в Вашей компании нет ни одного компьютера под управлением 64-разрядной ОС позже Windows 7 включительно?

                    Я драйвер подписываю.

                    Несмотря на свою простоту в моем случае данный драйвер достаточно эффективно решает поставленную задачу.

                    Я явно сказал что в моем случае.

                    Вы так и не услышали: без подписи на этих системах драйвер работать не будет!

                    Еще раз, я писал о разработке, а не об обходе проверки подписи.

                    Так в чём тогда интересность и ценность Вашего решения?

                    Решать вам, и остальным читателям.
                    • –8
                      То есть у Вас или Вашей компании есть деньги на сертификат для подписи драйвера, но нет денег на решение проблемы подключения сторонних устройств?
                      И в итоге специалист, имеющий доступ к сертификату, целый день тратит на написание драйвера, который к тому же потом требует доработки?
                      Извините, но если бы Вы работали в моей компании, после этого я бы Вас уволил.
                      Но Вы правы: всегда может быть иное мнение. Посмотрим, что скажут другие.
                      Для себя я всё понял, спасибо за диалог.
                      • +2
                        Вы прям стратег!
                        • +4
                          Не кажется глупым решением уволить человека, который справился с задачей, без дополнительных трат и проприетарного ПО? И потом искать замену? Странное решение на мой скромный взгляд.
                          • –10
                            Если решение на уровне учителя информатики в школе — тогда да. Но тут, как видите, не тот уровень.
                            Специалист на работе должен заниматься работой. Его рабочий день стоит дороже софта для блокировки.
                            Кроме того, если за день он не успел отладить простой драйвер до состояния «больше недостатков нет» — тогда он точно не на своём месте.
                          • +1
                            Вы правда не знаете что проверку подписи можно отключить?
                            • –2
                              Переводом в тестовый режим? Знаю, на рабочих станциях не использую. Лишняя брешь защиты.
                            • +5
                              Не подскажете название вашей компании? Просто на заметку.
                              • +3
                                Да нет у него никакой компании… И в компанию автора на место автора его бы не взяли
                                • +2
                                  Может и есть, просто он там один, на должности генерального директора. Увольняет всех.
                                • –3
                                  Извините, вакансий нет. Спросите автора статьи — судя по всему, работа у них не пыльная.
                                  • +1

                                    Ну да, не пыльная. С киркой и отбойным молотком ходить не надо. Кнопочки там всякие нажимаю.

                        • 0
                          Во-первых, проверка подписи отключается в Windows штатно, во-вторых, не секрет (вы это точно знаете), что в сети гуляет утилита, позволяющая подписать особым просроченным сертификатом любой драйвер, а MS закрыть уязвимость, используемую этим сертификатом не может, предпочитая игнорировать проблему.
                          • –1
                            Штатно — это перевод в тестовый режим. Слово «тестовый» Вам ничего не говорит? Да, на своём личном компьютере я для разработки могу включить такой режим, могу отключить UAC и постоянно работать под админом — но это не есть решение для рабочих станций, где необходима нормальная работа ОС и нормальный, штатный уровень безопасности.
                            «Утилита в сети» — это украденый сертификат с китайской программой для подписи.
                            Ребята, мы здесь обсуждаем решения для компании или пиратские обходы дома на завалинке? Давайте мухи — отдельно, котлеты — отдельно.
                            • 0
                              А можете дать ссылку на эту утилиту с просроченным сертификатом или более полную информацию? Спасибо.
                      • 0
                        Спасибо, очень интересно. На прошлой работе стояла похожая задача — надо было запретить подключение к определённому usb хабу всех устройств, кроме usb накопителей. Т. к. это было ПО для терминалов, я просто сделал перехват сообщений WM_DEVICECHANGE, и принудительно отрубал все устройства с требуемого хаба, которые не являются usbstorage.
                        • 0
                          Вырубали через SetupAPI?
                          • 0
                            Насколько я помню, да, давненько уже было. В крайнем случае можно devcon'ом рубить.
                            • 0
                              О таком решении я и не думал. В целом хорошее. Но в моем случае оно бы не подошло.
                              • 0
                                У такого решения есть проблема с открытыми хэндлами. SetupApi не отключит девайс с открытыми хэндлами, а устройство (та же флэшка) может, например, быть занята при запущенном приложении автозапуска. До появления уведомления о новом устройстве можно успеть много чего на нем открыть. Вариант — перебирать хэндлы и закрывать их вручную, что не очень хорошо сказывается на стабильности работы приложений.
                                • 0
                                  Не понимаю, о каких открытых хэндлах в данном случае идёт речь, если честно. Сообщение WM_DEVICECHANGE передаётся до тех пор, пока не обработается. Чисто теоретически, на замусоренной системе, кто-то может успеть его обработать раньше. Но тогда моя программа его не получит. Или мы говорим о разных вещах.
                                  P.S. в моём конкретном случае было допустимо рубить устройства devcon'ом (издержки производства, иногда, например, на уже поставленных терминалах отходит питание от купюроприёмника, и devcon — единственный способ программно вернуть устройство в рабочее состояние).
                        • +1

                          Безотносительно кода, решение весьма странное.
                          Если у пользователя нет прав администратора, то задачу можно решить проще, стандартными средствами контроля доступа, а если права есть, то он может просто использовать обычный драйвер, разве нет?

                          • +1
                            Приведите пример стандартных средств.
                            • 0
                              Извините, я давно usb-свистками не пользовался, но разве они уже могут устанавливать свои драйвера и софт, который требуется им для работы, без прав админа?
                              • 0
                                Ну тут разграничение прав, админ ставит софт, пользователь использует
                                • 0
                                  0_о А зачем админу сначала ставить софт для работы usb-модема, а затем писать драйвер, чтобы этот usb-модем не мог работать?
                                  • +1
                                    А дело только в модемах? Во-вторых, много драйверов в современных Windows предустановлены.
                                    • 0
                                      Пример то был с модемом. И очевидно, что он не очень удачный. На моей практике, когда пользователи пытались подобным образом обойти блокировку на развлекательные ресурсы, то они обломались.Операционные системы win-7, win-8 на тот момент были.
                                      • 0
                                        У USB устройств есть классы, у этих классов устройств часто бывает стандартный интерфейс. Для этого стандартного интерфейса есть предустановленный драйвер в системе. И?
                                        • 0
                                          Вы на практике сталкивались с тем, чтобы удалось использовать usb-модем без установки дополнительного ПО?
                                          • 0
                                            Именно так. Не надо только путать современные модемы, с модемами времен Windows XP.
                                            Еще раз, для стандартного класса USB устройства в системе может присутствовать драйвер. Сейчас сетевые адаптеры есть работающие по USB. И никакого спец. софта для них не нужно.
                                            • 0
                                              Ни один Yota модем, которыми я к сожалению — вынужден с завидной периодичностью пользоваться — не устанавливает никакие драйвера. Windows 7 — 10. На XP говорят приходится что то ставить, но к сожалению возможности проверить — нет.
                                              • 0
                                                Таких подавляющее большинство.
                                  • 0

                                    Возможно я не прав, но чтобы модем заработал, ему надо создать новое подключение (обычно это делает ПО модема при установке).


                                    Без прав администратора пользователь во-первых, не сможет установить драйвер модема, а во-вторых, если драйвер уже есть и не нужен, не сможет создать новое сетевое подключение.


                                    В крайнем случае, можно, например, явно запретить пользователю создание новых подключений через групповые политики.

                                    • 0
                                      В том и прелесть, что люди подключили модем без прав админа.
                                      • 0
                                        А можете модель модема озвучить?
                                        • 0
                                          Не могу, знаю только сам факт. Т.к. ИТ'шники обращались с такой просьбой.
                                          • +1
                                            Тогда не факт, что это факт. Вполне вероятно либо прошляпили админский доступ, либо юзер оказался достаточно продвинутым и упорным, чтобы ломануть учетку локального админа, например включил встроенного администратора. Беглый поиск по интернету не выявил модель usb-модема, которую можно установить без прав админа. Так что вполне вы занимались написание велосипеда из за не отлаженных должным образом политик и регламентов.Если пользователь установивший вопреки правилам модем не понес никакого наказания, и не было подробного расследования для выявления факта халатности админов, где гарантия, что тот же самый юзер в следующий раз не получит снова права админа и не удалит из системы этот самописный драйвер?
                                            • 0
                                              Я написал, а ваше дело мне верить или нет. Есть люди которым вы верите, есть которым я.

                                              Я еще раз подчеркну, в Windows предустановленных драйверов огромная масса. Полагаться на то что устройство потребует особой установки, не очень верно. Т.к. не дает максимальной гарантии.

                                              P.S. На счет наказаний немного ставит в ступор. Вы встречали когда-нибудь человека которого всегда наказывали только по делу?
                                              • 0
                                                А в чем ступор? Первая превентивная мера защиты от несанкционированного доступа это письменное уведомление о санкциях за этот доступ под роспись. Выпуск соответствующего документа это первое, что я прошу от руководства клиента, когда они хотят в чем то ограничить пользователей. Как я и указал выше вопрос правильных политик и регламентов.

                                                И лично я не ставлю под сомнение лично Вашу честность. Но вот сама предыстория вызывает сомнения.

                                                Главную мысль, которую я пытаюсь озвучить, что не нужно начинать искать решение задач администрирования чисто техническими средствами.
                                                • +1
                                                  Как показывает практика, в регламентах любой компании всегда есть дыры. Если цель ходить и заниматься справедливостью, тогда да. Хороший подход. Если ликвидировать вариант угрозы на корню, тогда технически. Пусть техника думает. Человеческий фактор никто не отменял. Да и ходить и заниматься воспитанием людей не самое интересное занятие. Лучше, если они не будут иметь технической возможности.
                                                  • +1
                                                    Вы не поняли. Вопрос не в абстрактной справедливости, а в рациональности. Где гарантия что, использование вашего решения по обходу подписи драйверов не нанесет значительный урон безопасности? Или что не создаст проблем при подключении устройств, драйвера к которому писали «индусы», но вот именно их и нужно подключить именно к этому рабочему месту? Конечно надежней запретить использование металлических кухонных ножей, но заставлять всех использовать одноразовые пластиковые не рационально.
                                                    • 0
                                                      Вы не поняли. Вопрос не в абстрактной справедливости, а в рациональности. Где гарантия что, использование вашего решения по обходу подписи драйверов не нанесет значительный урон безопасности?

                                                      В каком месте я обхожу подпись драйверов?

                                                      Или что не создаст проблем при подключении устройств, драйвера к которому писали «индусы», но вот именно их и нужно подключить именно к этому рабочему месту?

                                                      С таким подходом лучше тогда вообще ничего не делать, т.к. любое решение может нанести вред. Какие проблемы может породить фильтрация обычных запросов PnP, который писала Microsoft?

                                                      Конечно надежней запретить использование металлических кухонных ножей, но их заставлять всех использовать не рационально.

                                                      По-моему, вы перевернули все с ног на голову.

                                                      • 0
                                                        В каком месте я обхожу подпись драйверов?


                                                        За это извиняюсь, про обход подписи это был не ваш комментарий.

                                                        Какие проблемы может породить фильтрация обычных запросов PnP, который писала Microsoft?
                                                        Вам разве не приходилось еще сталкиваться с тем что «это не должно приводить к проблемам» не обязательно означает, что «это действительно не привело к проблемам». Особенно когда дело касается Microsoft. :)

                                                        По-моему, вы перевернули все с ног на голову.
                                                        там опечатка была, поэтому фраза действительно получилась бессмысленной. Возможно Вам приходилось читать притчу «про хакера и начальника столовой»?

                                                        Ну опять же вернусь к тому, что Ваше решение в итоге не защищает от того, кто будет специально искать как его обойти\сломать, т.к. нужно не только совершенствовать замки, но и ловить взломщиков.

                                                        • +1
                                                          Вам разве не приходилось еще сталкиваться с тем что «это не должно приводить к проблемам» не обязательно означает, что «это действительно не привело к проблемам». Особенно когда дело касается Microsoft. :)

                                                          Я много с чем сталкивался. И Microsoft последняя в списке. Статистически. Вообще когда говорят «особенно Microsoft» — все становиться ясно.

                                                          Ну опять же вернусь к тому, что Ваше решение в итоге не защищает от того, кто будет специально искать как его обойти\сломать

                                                          Ну сломайте kernel mode драйвер. Обойдите его механизмы. Вы сейчас сказали в целом правильную вещь, но бессмысленную. Т.к. из такого утверждения следует что не надо ничего писать, потому что это сломают.
                                              • –5
                                                Сдаётся мне, что отсутствие модели модема, отсутствие понимания автором защиты драйверов подписью, откровенно высосанные из пальца детали истории, отсутствие исходников и скомпилированного детища, а также активность на Хабре в рабочее время намекает, что статья — копипаста, не имеющая ничего общего с реальностью.
                                                В принципе, согласен в этом с Ivan_83.
                                                • –2

                                                  "А чё они говорят что у меня бомбит, когда у меня не бомбит"(С)

                                                • 0
                                                  Я очень давно не видел этих модемов, но те что видел лет 5 назад были обычно составными устройствами состоящими из диска с дрова и ком порта(CDC). иногда с возможность работы как USB сетевуха. Многие из них требовали спец софт для активации CDC/Сетевухи. Однако их можно было потом заставить остаться в этом состоянии. В Win7 и выше вроде бы есть дрова для CDC COM порта. Насчёт USB сетевухи не уверен. Остаётся только вопрос можно ли с неадминской учеткой создавать сетевое подключение.
                                                  • +1
                                                    Дрова для некоторых USB сетевых карт есть изначально в windows 7 и более новых. Если нужно модемное подключение, то с неадминской учётки можно создать новое подключение, но нельзя запомнить пароль для всех пользователей — только для своего. Чего вполне хватает для получения интернета на устройстве. Чаще всего, новое подключение не нужно вообще, хватит стандартного сетевого подключения, создаваемого windows для каждой сетевой карты.
                                                  • 0

                                                    Многие модемы умеют прикидываться сетевой картой и прав админа для них не нужно, в системе уже все есть, сам в универе так делал.
                                                    Если у вас телефон на android подключите его как usb модем, думаю вы удивитесь.
                                                    Технология называется ndis

                                                    • –1
                                                      Отличное замечание! Да действительно, для подключение смартфона ( я проверял Android)
                                                      в качестве модема на win10 никаких драйверов и ПО не требуется.Но это меня натолкнуло на мысль, что мы слишком зациклились на модемах и подключению по usb. Действительно пользователь может подрубить к компу и usb-wifi( современные свистки большей частью тоже без установки драйверов), а смартфон превратить в точку доступа одним нажатием, и воткнуть сетевую карту wi-fi в pci слот на материнке, и принести роутер, который может использвать в качестве wan подключения wi-fi со смартфона либо также подключать usb-модем в роутер, а компьютер подключить по Ethernet. Соответственно в двух последних случаях метод защиты автора не будет действовать, но зато будет действовать банальное отключение Dhcp на брэндмауре.
                                                      • 0
                                                        Можно фильтровать и PCI. Как вы себе представляете что пользователь рабочего ПК вставил плату? Нет можно конечно. Вы такое видели, среди не разработчиков?
                                                        • 0
                                                          Я видел когда юзер чтобы поставить игру переустановил виндовс, т.к. ему не давали прав администратора для этого. А воткнуть плату для человека хоть раз собиравшего-разбиравшего комп не проблема и таких людей среди пользователей достаточно.
                                                          • 0
                                                            А как же ваши ранее упомянутые регламенты компании, расследования инцидентов и система наказаний? На которые, как я понял, надо ставить приоритет, а не на технические решения.

                                                            А воткнуть плату для человека хоть раз собиравшего-разбиравшего комп не проблема и таких людей среди пользователей достаточно.

                                                            Сколько я видел людей работающих за ПК, они кнопки с трудом нажимают. Что уж говорить о подключении сетевой платы.

                                                            И потом, PCI это все-таки не hot-plug. Когда USB массовый. Даже если и так, вы слишком много уделяете внимания вещам, которые по своей натуре маловероятны. Целесообразно ли тратить на защиту от таких случаев много сил?
                                                            • 0
                                                              А как же ваши ранее упомянутые регламенты компании, расследования инцидентов и система наказаний? На которые, как я понял, надо ставить приоритет, а не на технические решения.

                                                              Человека уволили в этот же день. Он как раз на испытательном сроке был.

                                                              Два правила на брендмауре это быстрее чем писать драйвер по всевозможные варианты usb и pci устройств.
                                                              • 0
                                                                Ну понятно. Без комментариев.
                                                • 0
                                                  Yota WLTUBA-107, например.
                                        • +1
                                          Штука интересная, однако, мне кажется, что где-то видел бесплатное ПО для решения подобного вопроса, так сходу название вспомнить не могу.
                                          • –3
                                            Вполне может быть. Я не утруждал себя поисками.
                                          • 0
                                            Вряд ли пользователь домашнего ПК заинтересуется тем, чтобы блокировать устройства на своем ПК

                                            Полезные применения тоже есть, чтобы в комп не совали всякое.

                                            • 0
                                              Домашнего ПК да. А если у вас есть терминал МФУ — например, вы печатаете с USB, будет очень неприятно, если какой-нибудь умник подойдёт к вашему терминалу с USB клавиатурой.
                                            • 0
                                              Чего-то я упустил тему Ring0 за последние года 4.
                                              Сейчас в студии уже можно компилить в .sys без бубна? После подключения WDK ессно…

                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                              Самое читаемое