58 / 57 / 15
Регистрация: 15.09.2012
Сообщений: 557
|
|
Зачем нужен драйвер и как написать простейший драйвер23.09.2012, 14:50. Показов 86349. Ответов 38
Метки нет Все метки)
(
Хотя в интернете и есть на русском языке некоторые обяснения что такое драйвер для его програмирования считаю это довольно узко. Рускоязычные книги тоже не совсем понятно написаны. Вобщем мои рассуждения ( правильны ли они). Расссматриваю написания драйверов под виндовс. Для стабильности ОС програмисты разделиль функционирование ОС на две части - пользовательский режим и режим ядра, так как в пользовательском режиме возможности малы, то и испортить систему меньше шансов разным софтом. Драйвера работают в режиме ядра. Соответственно есть уже готовые функции API которые реализуют низкоуровневые операции и с помощью которых в основном и пишутся драйвера. Думаю что почти любой драйвер можна написать на основании этих функций + некоторые созданные собственно + асемблерные вставки. Соответственно драйвер считаю - это добавка до кода ОС, которая обясняяет как ей общаться с ОС. А как это делается ? Предполагаю что драйвер указывает какие низкоуровневые функции мы можем применить по отношению до даного устройства, указать какой приоритет у даного устройства. Неукладывается в голове что конкретно он делает. Вот подключаем мы какое-то неизвестное устройство до ПК. Оно подает какие то сигналы, и должно обрабатывать входящие. Для того чтобы просто работать с устройством ( ближе до человеческого языка) думаю что драйвер - это "образ" устройства в програмной форме - что то наподобе применения обектов в пользовательских приложениях (ООП). Тоесть мы создаем клас даного устройства, который описывает функции которые имеет даный обект и его свойства - не знаю какие. Кто как понимает - что делает драйвер. С чего начинается создание драйвера. Если допустим управлять внешним контроллером как выключателем. Почему написания драйверов кардинально отличается от написания пользовательського кода. Эсть ли какая то аналогичность. Очень хотелось бы чтобы человек который уже писал драйвера и четко все себе уяснил постарался по простому тезисно обяснить суть, самые важные аспекты по написанию драйверов.
2
|
23.09.2012, 14:50 | |
Ответы с готовыми решениями:
38
Как написать драйвер для COM-порта Как написать драйвер для флешки, шифрующий данные Помогите написать драйвер клавиатуры! |
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
|
26.09.2012, 06:12 | |
ASDFD12,
хороший цикл статей «Драйверы режима ядра», написанный Four-F, почитай его. Написание драйвера ничем кардинально не отличается от написания пользовательского кода, просто требует дополнительных усилий по отладке и наличие отладчиков для программ режима ядра и прежде чем "тезисно объяснять суть, самые важные аспекты по написанию драйверов" хотелось бы узнать какие книги прочел ТС, чтобы опереться на что-то, а не объяснять ВСЁ подряд...
2
|
58 / 57 / 15
Регистрация: 15.09.2012
Сообщений: 557
|
|
26.09.2012, 19:08 [ТС] | |
Спасибо за ответ, почитаю. Нащет книг - С++, C# (в основном по консольным приложениям). Изучал электронику (цыфровую как раз неизучал). Прочел азы асемблера (половину книги). Захотелось создавать устройства на МК, и как их связать с ПК. Прочел пару статей в интернете, пробежался 70% книги Комисарова (по драйверам) - изучить по такой книге нереально, пример драйвера дается сразу с потолка - вот так нада и все. Искал разную литературу и понял что ее почти нет на русском языке. Все на английском, а я его знаю плохо, чтобы читать книги. Книг по DDK тоже нет. Сейчас начал читать книгу по разработке операционной системы. Таких книг немного есть на русском и вижу, что они могут дать неплохую базу. Что скажете?
0
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
10.10.2012, 10:25 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() РешениеДоступ к командам In/Out через драйвер режима ядра Вообще то, здесь должна была быть статья с рабочим названием «Доступ к портам ввода/вывода под Windows XP». «Иллюстрациями» к статье должны были kernel-mode драйвера, но так как статья до сих пор не готова, а драйвера уже есть, начну с них. Все драйвера, которые будут приводится в этом топике, будут открывать порты 42h, 43h, 61h, чтобы сыграть системным динамиком «Марш клоунов» Нино Ротта. Переделаем драйвер beeper из KmdTutor by Four-F. Драйвер собирается при помощи следующих строк в bat-файле
Теория На материнской плате находится перепрограммируемый интервальный таймер ― система, состоящая из трех каналов, каждый из которых можно запрограммировать для работы в одном из шести режимов. На многих современных материнских платах расположено два таких таймера, следовательно, число каналов равно шести.
Практика Выводим в порт 43h число 0B6h=10.11.011.0b, мы помещаем в управляющий регистр таймера значение, определяющее:
Первый вариант user-mode приложения, которое запускает драйвер scp00.sys user-mode приложение, которое запускает scp00.sys драйвер, используя API-функции Service Control Manager'a: OpenSCManager, CreateService, StartService, CloseServiceHandle и DeleteService. Этот способ очень прост и хорошо документирован, он подходит для постоянной установки драйверов. Для запуска и управления драйвером необходимы следующие компоненты:
На конечном этапе загрузки системы перед появлением диалога регистрации пользователя запускается SCM (\%SystemRoot%\System32\Services.exe), который, просматривая раздел реестра HKEY_LOCAL_MASHINE\SYSTEM\CurentControlS et\Service\, создает свою внутреннюю базу данных (ServiceActive database или SCM database). Далее SCM находит в созданной базе все драйвера устройств и службы, помеченные для автоматического запуска, и загружает их. Рассмотрим процесс запуска и управления драйвером более подробно. Помещаем драйвер в сервисную базу. База должна быть предварительно открыта функцией OpenSCManager:
Параметры: lpMachineNameУказатель на строку (завершающуюся нулём), содержащую имя компьютера. Этот параметр мы сразу устанавливаем в NULL, так как будем открывать канал связи с SCM только на локальном компьютере. lpDatabaseName Указатель на строку (завершающуюся нулём), которая содержит имя открываемой базы данных менеджера управления сервисами. Этот параметр должен быть равен SERVICES_ACTIVE_DATABASE. Если этот параметр приравнять NULL, то по умолчанию будет открыта база SERVICES_ACTIVE_DATABASE. Так как мы не собираемся открывать никакую другую базу данных SCM, кроме активной в данный момент, просто, установим этот параметр в NULL. dwDesiredAccess Права доступа к менеджеру управления сервисами. Сообщает SCM, что мы собственно намереваемся делать с его базой данных. Нам могут быть полезны три значения:
Получив доступ к базе SCM, мы регистрируем в ней свой драйвер, с помощью функции CreateService. Функция CreateService создает объект службы и добавляет его в указанную базу данных диспетчера управления службами.
hSCManager Дескриптор базы данных диспетчера управления службой. Этот дескриптор возвращается функцией OpenSCManager и должен иметь право доступа SC_MANAGER_CREATE_SERVICE. Определяет в какую именно базу мы добавляем сведения о новом драйвере. lpServiceName Указатель на строку с завершающим нулем, которая задает устанавливаемое имя службы. Максимальная длина строки ― 256 символов. База данных диспетчера управления службами сохраняет регистр символов, но при сравнении имени службы ― всегда без учета регистра. Прямой слэш (/) и обратный слэш (\) ― неприменяемые символы в имени службы. lpDisplayName Указатель на строку с завершающим нулем, которая имеет в своем составе отображаемое имя, которое используется пользовательскими программами интерфейса, чтобы идентифицировать службу. Эта строка имеет максимальную длину 256 символов. Имя сохраняется с учетом регистра в диспетчере управления службами. Сравнения отображаемого имени всегда не чувствительны к регистру. dwDesiredAccess Доступ к службе. Перед предоставлением требуемого доступа, система проверяет маркер доступа вызывающего процесса.
dwServiceType Типы службы. Для драйвера может быть только SERVICE_KERNEL_DRIVER (Соответствует параметру Type в реестре) dwStartType Варианты запуска службы. Этот параметр может быть SERVICE_DEMAND_START Служба, запускается диспетчером управления службами, когда процесс вызывает функцию StartService. (Соответствует параметру Start в реестре) dwErrorControl Серьезность ошибки и предпринимаемое действие, если эта служба не в состоянии запуститься. Этот параметр может быть одним из следующих значений.
Указатель на строку с завершающим нулем, которая имеет в своем составе полный путь доступа к двоичному файлу службы. Если путь имеет в своем составе пробел, он должен быть заключен в кавычки. Соответствует параметру ImagePath в реестре lpLoadOrderGroup Указатель на строку с завершающим нулем, именующую группу очередности загрузки, членом которой является эта служба. Задайте значение NULL или пустую строку, если служба не принадлежит группе. Программа запуска использует очередность загрузки групп, чтобы загрузить группы служб в указанном порядке по отношению к другим группам. Список очередности загрузки групп содержатся в следующем значении реестра: HKEY_LOCAL_MACHINE\System\CurrentControl Set\Control\ServiceGroupOrder lpdwTagId Указатель на переменную, которая получает значение признака, являющееся уникальным в группе, заданной в параметре lpLoadOrderGroup. Задайте значение ПУСТО (NULL), если Вы не изменяете существующий признак. Вы можете использовать признак для того, чтобы упорядочить запуск службы в пределах очередности загрузки группы, определяя вектор очередности признака в следующем значении реестра: HKEY_LOCAL_MACHINE\System\CurrentControl Set\Control\GroupOrderList Признаки вычисляются только для служб драйвера, которые имеют типы пуска SERVICE_BOOT_START или SERVICE_SYSTEM_START. lpDependencies Указатель на массив имен служб, разделенных нулем, с двойным символом нуля в конце или очередности загрузки групп, которую система должна запустить перед этой службой. Задайте значение NULL или пустую строку, если служба не имеет никаких зависимостей. Зависимость от группы означает, что эта служба может запуститься тогда, если по крайней мере один член группы запущен после попытки запустить все члены группы. Вы должны ставить в начале имен группы SC_GROUP_IDENTIFIER так, чтобы они могли отличаться от имени службы, потому что службы и группы служб совместно используют то же самое пространство имен. Если драйвер не зависит от других драйверов, то в этом параметре можно указать NULL или указатель на пустую строку. lpServiceStartName Указатель на строку с завершающим нулем, которая задает имя учетной записи, с правами которой будет запущен драйвер. Если тип службы SERVICE_KERNEL_DRIVER, то этот параметр должен содержать имя объекта драйвера, которое используется системой для загрузки. Если используется имя объекта "драйвер" созданное подсистемой ввода-вывода, то этот параметр устанавливается равным NULL. lpPassword Указатель на строку с завершающим нулем, которая имеет в своем составе пароль к имени учетной записи, заданному параметром lpServiceStartName. Для служб драйвера пароли игнорируются, поэтому NULL Вызовом функции GetFullPathName, мы формируем строку с полным путем к файлу драйвера, состоящую из текущего каталога и имени файла драйвера, и передаем ее функции CreateService. CreateService регистрирует в базе данных SCM новый драйвер, и заполняет соответствующий подраздел реестра. Запуск драйвера осуществляется функцией StartService
hService Дескриптор службы. Этот дескриптор возвращается функцией OpenService или CreateService, и он должен иметь право доступа SERVICE_START. dwNumServiceArgs Число строк в массиве lpServiceArgVectors. Если lpServiceArgVectors имеет значение NULL, этот параметр может быть нулем. Для драйверов это всегда так. lpServiceArgVectors Указатель на массив указателей на строки с завершающим нулем, который передается службе как параметры. Службы драйвера не получают эти параметры, поэтому мы устанавливаем этот параметр в NULL. Функция StartService заставляет систему произвести действия, очень сильно напоминающие загрузку обыкновенной DLL. Образ файла драйвера проецируется на системное адресное пространство. При этом, возможности управлять адресом загрузки нет никакой. Да это и не нужно. Предопределенный адрес загрузки (preferred base address) у всех наших драйверов будет равен 10000h, что значительно ниже начала системного диапазона адресов. Пытаться установить его в какое-то другое значение не имеет смысла, так как система, все равно, будет загружать драйвер по случайному (для нас) адресу. Поскольку фактический адрес загрузки не совпадает с предопределенным, система производит настройку адресов пользуясь таблицей перемещений (relocation table), находящейся в секции .reloc файла драйвера. Затем производится связывание (fix-up) импорта. Кстати, импорт в файле драйвера раскинут в секции INIT и .idata. В .idata находится таблица адресов импорта (import address table, IAT). В ней содержатся адреса функций во внешних модулях. Она нужна драйверу постоянно. А в секции INIT содержится остальная часть импорта, необходимая только на этапе загрузки (имена внешних модулей и имена импортируемых функций), после которой, память занимаемая этой секцией освобождается. Когда образ драйвера подготовлен, управление передается на точку входа (entry point), которая находится в процедуре DriverEntry. Принципиальная разница, не считая уровня привилегий, в том, что код процедуры DriverEntry всегда выполняется одним из потоков процесса System, и, естественно, в адресном контексте этого процесса. Вызов StartService синхронный. Это значит, что она не вернет управление до тех пор, пока не отработает процедура DriverEntry в драйвере. Если инициализация драйвера прошла успешно, DriverEntry должна вернуть STATUS_SUCCESS, а функция StartService вернет значение отличное от нуля. И мы вновь окажемся в контексте потока вызвавшего StartService, то есть в контексте нашей SCP. Вызов StartService может завершиться неудачей, если база данных SCM заблокирована. Последующий вызов функции GetLastError вернет ERROR_SERVICE_DATABASE_LOCKED. Как написано в документации, в этом случае, следует подождать несколько секунд, и повторить попытку, но мы этого делать не будем, так как такая ситуация крайне маловероятна. И вообще, в данном случае, нас не интересует возвращаемое функцией StartService значение, так как драйвер уже проиграл свою мелодию и вернул код ошибки. То есть мы заранее знаем, что вызов StartService даст ошибку. Осталось привести систему в исходное состояние. Вызовом функции DeleteService мы удаляем сведения о драйвере из базы данных SCM и из реестра. Странно, но передавать описатель самой базы данных SCM в функцию DeleteService не нужно. Функция DeleteService отмечает указанную службу для удаления из базы данных диспетчера управления службами.
hService Дескриптор службы. Этот дескриптор возвращается функцией OpenService или CreateService и он должен иметь право доступа DELETE. На самом деле, функция DeleteService ничего ниоткуда не удаляет. Она только сообщает системе, что это можно сделать, когда наступит благоприятный момент. А он наступит тогда, когда все описатели службы будут закрыты. Так как мы все еще держим описатель hService открытым, то удаления не происходит. Если попытаться вызвать DeleteService повторно, то он завершится неудачей, а последующий вызов функции GetLastError вернет ERROR_SERVICE_MARKED_FOR_DELETE. Вызовом функции CloseServiceHandle мы закрываем описатель диспетчера управления службами hService.
hSCObject Дескриптор объекта диспетчера управления службами или объекта службы, который закрывается. Дескрипторы объектов менеджера управления службами возвращаются функцией OpenSCManager, а дескрипторы объектов служб возвращаются или функцией OpenService или функцией CreateService. Поскольку больше открытых описателей службы нет, то именно в этот момент система приводит базу данных SCM в исходное состояние. Второй вызов CloseServiceHandle закрывает описатель самого SCM.
Предварительно прописываем драйвер scp00.sys в реестре «вручную» (используем функции RegOpenKey, RegCreateKey, RegSetValue) и загружаем драйвер scp00.sys с помощью функции ZwLoadDriver. В реестре создается минимум необходимых записей, запускаем драйвер, выгружаем драйвер функцией ZwUnloadDriver и удаляем его раздел из реестра (используем функции RegCloseKey, SHDeleteKey). Этот способ позволяет запускать драйвер быстро и незаметно и подходит для маленьких программ не требующих установки, но требующих запуска своего драйвера.
Собственно это модифицированный второй вариант. Произошла замена функций из advapi32.dll и других динамических библиотек на Zw-функции из ntdll.dll, а далее замена Zw-функций на вызов 2Eh прерывания, поэтому за исключением функции RtlGetFullPathName_U наша программа не использует импорт
вызовом функции ZwCreateKey, создаем новый подраздел «scp00» в ветке «HKEY_LOCAL_MACHINE\SYSTEM\CurrentContro lSet\Services» После успешного вызова ZwCreateKey по значению переменной dwDisposition можно определить, был ли создан новый подраздел (REG_CREATED_NEW_KEY) или такой подраздел уже существовал в реестре (REG_OPENED_EXISTING_KEY) и поэтому был открыт При помощи ZwSetValueKey создадим в нашем подразделе:
при использовании sysenter вместо Zw-функций размер файла 789 байт, при использовании call ds:[7FFE0300h] ― размер файла 762 байта, при использовании int 2Eh ― размер 699 байт
Используя функцию ZwSetSystemInformation с параметром SystemLoadAndCalllmage можно за одно действие загрузить и запустить драйвер в системе Windows NT. При этом не требуется никакой регистрации драйвера. Однако возникнет «побочный эффект» ― после такой загрузки драйвер невозможно выгрузить «Обычный» (написанный по всем правилам драйвер) будет находиться в памяти до следующей перезагрузки компьютера. Но наш-то драйвер после выполнения возвратит системе STATUS_DEVICE_CONFIGURATION_ERROR (код фиктивной ошибки) и благополучно будет «самовыпилен» (удален системой из памяти) . Другой побочный эффект заключается в том, что мы можем за один сеанс загрузить драйвер несколько раз. Обычно драйвер может загружаться только один раз, но применив наш специальный системный вызов, мы можем загружать и запускать столько копий драйвера, сколько нам нужно. 8-байтовая локальная переменная GregsImage представляет из себя структуру UNICODE_STRING используемую для работы с UNICODE-строками в нулевом кольце
________________________________________ _________________________ Для написания данной главы использовались работы следующих авторов: Программирование и устройство таймера:
________________________________________ _________________________
© Mikl___ 2011
24
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
||
11.10.2012, 03:24 | ||
Vadimych, там если внимательно читать, то есть фраза
0
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
|||||||||||||||||||||
12.10.2012, 04:22 | |||||||||||||||||||||
![]() РешениеДоступ к командам In/Out через драйвер режима ядра команды читающие или пишущие в порт ввода/вывода могут быть расположены в «теле» user-mode приложения, но чтобы они выполнились, необходимо оформить этот фрагмент как процедуру и на исполнение ее запустить из kernel-mode драйвера. При этом в этой процедуре не должны встречаться WinAPI функции, используемые в user-mode, иначе BSOD обеспечен. Адрес процедуры в драйвер можно передать:
Текст драйвера scp01.sys
Первый вариант user-mode приложения, которое запускает драйвер scp01.sys user-mode приложение, которое запускает scp01.sys драйвер, используя API-функции Service Control Manager'a: OpenSCManager, CreateService, StartService, CloseServiceHandle и DeleteService. Этот способ очень прост и хорошо документирован, он подходит для постоянной установки драйверов.
Второй вариант user-mode приложения, которое запускает драйвер scp01.sys Предварительно прописываем драйвер scp01.sys в реестре «вручную» (используем функции RegOpenKey, RegCreateKey, RegSetValue) и загружаем драйвер scp00.sys с помощью функции ZwLoadDriver. В реестре создается минимум необходимых записей, запускаем драйвер, выгружаем драйвер функцией ZwUnloadDriver и удаляем его раздел из реестра (используем функции RegCloseKey, SHDeleteKey). Этот способ позволяет запускать драйвер быстро и незаметно и подходит для маленьких программ не требующих установки, но требующих запуска своего драйвера.
Третий вариант user-mode приложения, которое запускает драйвер scp01.sys Устанавливаем драйвер при помощи функции ZwSetSystemInformation
________________________________________ _________________
© Mikl___ 2011
13
|
58 / 57 / 15
Регистрация: 15.09.2012
Сообщений: 557
|
|
12.10.2012, 22:22 [ТС] | |
Miki / Спасибо за написаную статью, но честно говоря из написаного выше я мало что понял. Естественно что для понимания даного кода нужно немало прочитать. Нада на уровне регистров понимать как работает ОС Windows, например чтоб передать число на какой то порт, сначала записать его в регистр al, и только после этого можна передать его содержимое в порт. Где эту информацию брать, сколько времени на это уйдет - думаю очень много. Хотелось бы примеров "более высокого уровня интеграции".Читал что есть модель драйвера WDM, а сейчас уже и WDF. Например, раньше было очень сложно писать пользовательские Windows приложения. Нада было знать очень много кода, перелопатить API функции. Сейчас ( из того немногого что я знаю) в C# создавать приложения буквально играясь в конструктора в визуальном режиме ( заполняем окно менюшками, кнопками, тексбоксами и определяем для них обработчики). Так у меня вышло написать простейший интернет браузер буквально за 5 минут, приэтом не сильно ламая голову.
Надеюсь что в мире програмирование есть подобная ситуация. Особенно после выхода Visual Studio 2012. Мало информации про WDF/ Надеюсь что это такая же "револючия" (как C#), которая поможет создавать драйвера не вникая (сильно в низкоуровневое програмирование). Лично мне интересно и низкоуровневое програмирование так как щитаю это проффесионализмом, но хотелось бы на пути начального изучения, начать с высокоуровневого програмирование - отдельно понять что как работает, глянуть на драйвер свысока, потом набравсь опыта понять как работает конкретная функция и далее уже разобрав низкоуровневые методы ее реализации научиться писать ассемблерные вставки в код драйвера при необходимости или когда это требуется. Сейчас же хотелось бы (был бы очень рад) увидеть код драйвера WDF. Понять что это за "зверь", понять его структуру. Ожидаю од него что это будет какой то общий шаблон драйвера с возможностью его наполнять как стандартными функциями так и собственными - игра в "конструктор". Хотелось бы чтобы эта тема помогла - многих именно заинтересовать в написании драйверов, показать что это не очень сильно сложно, а при прикладании постепенно усилий можна что-то научиться. При прочтении вашой статьи - как я уже казал я почти ничего не понял - переписываем какието переменные из одного регистра в другой, выполняем функции, все очень для начального уровня сложно. Естественно если человек допустим учиться на прграмиста и постепенно с обяснеиями обучает все на уровне електроники, то может ему такой пример и легок. Мне например более наглядным был пример драйвера (на сайте хабрахабр) который выдает сообщение в режиме ядра (Hell World - при запуске драйвера, и Gydbye - при его завершении. Конешно понимаю что никакой практической пользы от него нету, но все же это просто - можна самому с первого раза попробовать, это увлекательно, вызывает интерес к изучению. Итак заключение моей мысли. Что лично вызвало у меня интерес к написанию драйверов. Не секрет что компютеры проникают у все сферы деятельности. Все больше выпускается так званых умных устройств на микроконтроллерах. Хотелось бы научится ими управлять с помощью ПК. Какую мне бы хотелось увидеть здесь статью. Пример простейшого регулятора напряжения на МК. который бы управлял минидвигателем или освещением. Устройство подключается через любой порт ( что бы пороще было реализовать). У нас есть драйвер и пользовательское приложение. В пользовательском приложении допустим есть кнопки включить , выключить, и регулировка оборотов с помощью ползунка или чего то подобного. Хотелось бы это увидеть на примере драйвера WDF на основе C# ( или что то подобное).
0
|
13.10.2012, 13:22 | |
Не по теме: ASDFD12, отличная у Вас идея. Как и у многих здесь, на форуме. Выпросить всеми правдами и не правдами решение своей задачи. Вообще говоря странно, что любитель писать программы мышкой забрёл в раздел низкоуровневого программирования. Но, надо отдать должное, клянчите Вы виртуозно.
0
|
Почетный модератор
![]() 23246 / 9158 / 1084
Регистрация: 11.04.2010
Сообщений: 11,014
|
|
13.10.2012, 17:08 | |
Оффтоп прекращаем
0
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
|||||||||||||||||
15.10.2012, 12:30 | |||||||||||||||||
литературу в школе учат десять лет, начиная с букваря и простейших сказок, год за годом сложность прочитанного увеличивается и к 10-11 году обучаемый в состоянии разобраться в идеях и творчестве Чехова, Пастернака, Толстова... А здесь ты хочешь после прочтения одной единственной статьи начать писать kernel-mode драйвера? ![]() Добавлено через 5 часов 22 минуты Доступ к командам In/Out через драйвер режима ядра Переделываю драйвер <R>ing-<0> <P>rocedure <C>all & Direct Port I/O (r0pc.sys) by @L.chemist (Andrey A. Meshkov). Драйвер scp02 передает управление на фрагмент кода из scp02-00.exe в котором содержится команда outsb, синхронизация производится через предварительный подсчет тиков. Адрес процедуры передается через WriteFile("\\.\scp02"). Полнофункциональный драйвер. Далее исходный текст драйвера scp02.sys
user-mode приложение, которое запускает scp02.sys драйвер, используя API-функции Service Control Manager'a: OpenSCManager, CreateService, StartService, CloseServiceHandle и DeleteService. Этот способ очень прост и хорошо документирован, он подходит для постоянной установки драйверов.
Предварительно прописываем драйвер scp02.sys в реестре «вручную» (используем функции RegOpenKey, RegCreateKey, RegSetValue) и загружаем драйвер scp02.sys с помощью функции ZwLoadDriver. В реестре создается минимум необходимых записей, запускаем драйвер, выгружаем драйвер функцией ZwUnloadDriver и удаляем его раздел из реестра (используем функции RegCloseKey, SHDeleteKey). Этот способ позволяет запускать драйвер быстро и незаметно и подходит для маленьких программ не требующих установки, но требующих запуска своего драйвера.
________________________________
© Mikl___ 2011
10
|
![]() 4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
||
15.10.2012, 12:40 | ||
0
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
||||||||||||||||||||||||||||||||||||||||||||||
15.10.2012, 13:00 | ||||||||||||||||||||||||||||||||||||||||||||||
Доступ к командам In/Out через изменение карты IOPM Manipulating the IOPM (I/O Permission Bitmap) Changing the IOPM within your Kernel Mode Drivers requires the knowledge of a couple of undocumented calls. These are Ke386IoSetAccessProcess, Ke386SetIoAccessMap and PsLookupProcessByProcessId На написание статьи меня подтолкнуло чтение Криса Касперски «Методы низкоуровневого управления приводами» и упомянутая в этой работе статья Dale Roberts от 01 мая 1996 «Direct Port I/O and Windows NT». Позже в KmdTutor by Four-F я нашел драйвер giveio, который используя функции Ke386SetIoAccessMap, Ke386QueryIoAccessMap и Ke386IoSetAccessProcess предоставлял доступ к портам ввода/вывода user-mode приложениям. Теория Считается, что в Windows NT/2k/XP прямое обращение к портам возможно только на уровне ядра, а приложения вынуждены общаться с портами через высокоуровневый интерфейс, предоставляемый драйвером. На самом деле, выполнять команды IN/OUT можно и на прикладном уровне, правда не без помощи недокументированных возможностей операционной системы и документированных, но малоизвестных особенностей реализации защищенного режима работы в процессорах Intel. В «Instruction Set Reference» приведен псевдокод инструкций IN и OUT:
псевдокод инструкции IN
псевдокод инструкции OUT Обнаружив, что полномочий текущего уровня привилегий недостаточно для выполнения команды IN/OUT, процессор не спешит выбросить исключение general protection fault, а осуществляет дополнительную проверку на предмет состояния карты разрешения ввода/вывода (IOPM ― I/O Permission bitMap) и, если бит памяти, соответствующий данному порту равен нулю, то вывод в порт осуществляется несмотря на запрет со стороны CPL. Таким образом, для взаимодействия с портами с прикладного уровня достаточно скорректировать карту разрешения ввода/вывода, после чего подсистема защиты операционной системы Windows NT перестает мешать, поскольку контроль доступа к портам осуществляется не на программном, а на аппаратном уровне и, если процессор перестанет выбрасывать исключения, операционная система ничего не узнает о происходящем. Из «Architecture Software Developer's Manual Volume 1: Basic Architecture», узнаем, что карта ввода/вывода находится в сегменте состояния задачи (TSS ― Task State Segment), смещение IOPM относительно начала TSS определяется 32-битным полем, расположенном в 66h и 67h байтах сегмента состояния задачи. Нулевой бит карты IOPM отвечает за нулевой порт, первый - за первый, второй - за второй и т.д. вплоть до старшего бита 2000h-байта, отвечающего за 65535 порт. Битовую карту завершает так называемый байт-терминатор, имеющий значение 0FFh. Порты, чьи биты сброшены в нулевое значение, доступны с прикладного уровня без ограничений. Сама карта ввода/вывода доступа лишь драйверам, но не приложениям, поэтому без написания собственного драйвера не обойтись. Однако этот драйвер будет работать только на стадии инициализации, а весь дальнейший ввод/вывод пойдет напрямую, даже если выгрузить драйвер из памяти. В Windows NT смещение карты ввода/вывода по умолчанию находится за пределами сегмента состояния задачи и потому модифицировать карту ввода/вывода не так-то просто. То есть карта ввода/вывода в TSS есть, но она заблокирована системой. Попытка подкорректировать указатель на карту ввода/вывода ни к чему не приводит, поскольку Windows NT хранит копию этого значения в контексте процесса, а потому при переключении контекста указатель на прежнюю карту автоматически восстанавливается. Можно увеличить размер сегмента состояния задачи так, чтобы адрес карты ввода/вывода, прежде указывающий за его конец, теперь приходился на подвластную нам область памяти. Поскольку в хвосте последней страницы, занятой TSS, имеется всего лишь 0F55h байт, максимальный размер карты, которую мы можем создать в этом промежутке, охватывает всего лишь 31392 портов ввода/вывода. Дейлом Робертсом («Direct Port I/O and Windows NT» by Dale Roberts) были обнаружены три недокументированные функции: Ke386SetIoAccessMap, Ke386QueryIoAccessMap и Ke386IoSetAccessProcess, которые обеспечивают управление картой ввода/вывода. Эти функции находятся в NTOSKRNL.EXE и они доступы с уровня драйверов. Функция Ke386SetIoAccessMap принимает два аргумента: dwFlag ― длинное целое, которое нужно установить в 1, чтоб функция работала, и pIopm ― указатель на буфер. Функция копирует переданную карту доступа к портам ввода/вывода длинной 2000h из буфера в TSS по смещению 88h.
Функция Ke386IoSetAccessProcess принимает два аргумента: pProcess ― указатель на структуру процесса, полученный вызовом функции PsGetCurrentProcess и dwFlag ― целое, которое должно быть установлено в 1 чтобы разрешить доступ к портам ввода/вывода, или 0 чтоб запретить его. Когда аргумент dwFlag равен 0, функция запрещает доступ к портам ввода/вывода установкой смещения IOPM переданного процесса за границу сегмента TSS. Когда аргумент dwFlag равен 1, функция разрешает доступ к портам ввода/вывода, устанавливая смещение IOPM переданного процесса на начало IOPM по смещению 88h в TSS.
Практика Драйвер scp04 написан на основе драйвера giveio by Four-F, открывает порты ввода/вывода через изменение карты IOPM и использует функции Ke386SetIoAccessMap, Ke386QueryIoAccessMap, Ke386IoSetAccessProcess. Значение ProcessId драйвер получает через реестр. Использование драйвера scp04 позволяет одновременно использовать команду outsb и WinAPI функции пользовательского режима, например функцию Sleep. scp04 представляет собой неполнофункциональный драйвер, то есть самостоятельно только стартует и открывает порты ввода/вывода после чего возвращает код ошибки и система удаляет его из памяти. Функции Ke386SetIoAccessMap, Ke386QueryIoAccessMap и Ke386IoSetAccessProcess это только «обертки» для функций вызываемых из hal.dll. Правда, как показала проверка, при запуске на Celeron 466 и на двухядерном Pentium 4 функции из hal.dll, заменяющие функции из ntoskernl.exe могут отличаться, я попытался найти компромиссное решение. В результате команды IN и OUT удалось поместить в user-mode приложение, что дает возможность «написания быстрой программы для взаимодействия с устройством, в которой printf()'ы и getchar()'ы чередовались бы с командами ввода/вывода» (Dale Roberts). Далее исходный текст драйвера scp04.sys
user-mode приложение, которое запускает scp04.sys драйвер, используя API-функции Service Control Manager'a: OpenSCManager, CreateService, StartService, CloseServiceHandle и DeleteService. Этот способ очень прост и хорошо документирован, он подходит для постоянной установки драйверов. Перед запуском драйвера, мы создаем в подразделе реестра, соответствующем драйверу, дополнительный параметр ProcessId, и устанавливаем его значение равным идентификатору текущего процесса, то есть процесса программы управления. Если добавление параметра прошло без ошибок, то запускаем драйвер. Получив управление от функции StartService, мы считаем, что драйвер успешно отработал и устанавливаем флаг fOK. Вызов функции RegDeleteValue делать не обязательно. Все равно, весь раздел реестра будет удален последующим вызовом DeleteService. Удаляем драйвер из базы данных SCM и закрываем все открытые описатели.
Предварительно прописываем драйвер scp04.sys в реестре «вручную» (используем функции RegOpenKey, RegCreateKey, RegSetValue) и загружаем драйвер scp04.sys с помощью функции ZwLoadDriver. В реестре создается минимум необходимых записей, запускаем драйвер, выгружаем драйвер функцией ZwUnloadDriver и удаляем его раздел из реестра (используем функции RegCloseKey, SHDeleteKey). Этот способ позволяет запускать драйвер быстро и незаметно и подходит для маленьких программ не требующих установки, но требующих запуска своего драйвера.
_________________
© Mikl___ 2011
8
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
||||||||||||||||
19.10.2012, 04:01 | ||||||||||||||||
Доступ к командам In/Out через изменение карты IOPM Драйвер giveio.sys отработав, возвращает один из кодов ошибки, система удаляет его из памяти, но теперь, любое user-mode приложение имеет доступ к трем портам ввода-вывода до тех пор, пока вы не перезагрузите компьютер. Это дает возможность запускать приложения написанные под DOS или Wind95/98, но всёравно не очень безопасно. Драйвер, написанный по мотивам kernel-mode драйвера PortTalk 2.0 by Craig Peacock, предоставляет доступ к портам 42h, 43h и 61h только тому процессу, который вызывает этот драйвер, а перед выгрузкой из памяти драйвер восстанавливает карту IOPM. Открывает порты IOPM и использует Ke386SetIoAccessMap, Ke386QueryIoAccessMap, Ke386IoSetAccessProcess. ProcessId получает через DeviceIoControl. Сочетание команд outsb и UserMode-WinAPI функции Sleep. Полнофункциональный драйвер. Далее исходный текст драйвера scp05.sys
user-mode приложение, которое запускает scp05.sys драйвер, используя API-функции Service Control Manager'a: OpenSCManager, CreateService, StartService, CloseServiceHandle и DeleteService. Этот способ очень прост и хорошо документирован, он подходит для постоянной установки драйверов.
Предварительно прописываем драйвер scp05.sys в реестре "вручную" (используем функции RegOpenKey, RegCreateKey, RegSetValue) и загружаем драйвер scp05.sys с помощью функции ZwLoadDriver. В реестре создается минимум необходимых записей, запускаем драйвер, выгружаем драйвер функцией ZwUnloadDriver и удаляем его раздел из реестра (используем функции RegCloseKey, SHDeleteKey). Этот способ позволяет запускать драйвер быстро и незаметно и подходит для маленьких программ не требующих установки, но требующих запуска своего драйвера.
________________________________________ ___
© Mikl___ 2011
7
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
||||||||||||||||
19.10.2012, 04:04 | ||||||||||||||||
Доступ к командам In/Out через изменение карты IOPM Драйвер scp06.sys написан на основе драйвера режима ядра UserPort 2.0 by Tomas Franzon changed to PsSetCreateProcessNotifyRoutin method. адресный диапазон расширен до 7A80h для всех процессов и до 0FFFFh для \\.\scp06 процессов. Выполнение Ke386IoSetAccessProcess, сопровождается вызовом функции ZwYieldExecution, которая форсирует процесс переключения. Сочетание команд outsb и user mode WinAPI-функции Sleep. Полнофункциональный драйвер. Далее исходный текст драйвера scp06.sys
Первый вариант user-mode приложения, которое запускает драйвер scp06.sys user-mode приложение, которое запускает scp06.sys драйвер, используя API-функции Service Control Manager'a: OpenSCManager, CreateService, StartService, CloseServiceHandle и DeleteService. Этот способ очень прост и хорошо документирован, он подходит для постоянной установки драйверов.
Второй вариант user-mode приложения, которое запускает драйвер scp06.sys Предварительно прописываем драйвер scp06.sys в реестре "вручную" (используем функции RegOpenKey, RegCreateKey, RegSetValue) и загружаем драйвер scp06.sys с помощью функции ZwLoadDriver. В реестре создается минимум необходимых записей, запускаем драйвер, выгружаем драйвер функцией ZwUnloadDriver и удаляем его раздел из реестра (используем функции RegCloseKey, SHDeleteKey). Этот способ позволяет запускать драйвер быстро и незаметно и подходит для маленьких программ не требующих установки, но требующих запуска своего драйвера.
________________________________________ _________
© Mikl___ 2011
6
|
Модератор
![]() 8962 / 6728 / 921
Регистрация: 14.02.2011
Сообщений: 23,752
|
|||
19.10.2012, 04:42 | |||
Могу порекомендовать книгу
В. П. Солдатов "Программирование драйверов Windows" Москва Издательство БИНОМ 2004 но для её прочтение нужно знать С, основы Windows, шестнадцатеричную арифметику,устройство компьютера т.е не для начинающих(правда не понятно как может начинающий написать драйвер) для написания компилирования и отладки драйверов необходимо скачать Microsoft Windows DDK ( для каждой системы свой) в этом пакете лежат примеры копайся не хочу..... но неплохо-бы знать английский куча информации лежит в MSDN но тут английский обязателен схемотехнику разрабатывать? протокол обмена с компьютером? Добавлено через 2 минуты как его можно использовать? не используется ли он виндой как мультимедийный таймер?
0
|
Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,734
|
||||||||||||||||
19.10.2012, 06:13 | ||||||||||||||||
Доступ к командам In/Out через изменение карты IOPM указатель на карту ввода/вывода, который по умолчанию указывал за границу TSS, и устанавливаем начало IOPM на TSS+0x88. В отличии от UserPort.sys 1.0 драйвер поддерживает Hyper-Threading Technology ("UserPort 1.0 did not run stable on Hyperthreading machined (rebooted without bluescreen).") Драйвер scp07 написан на основе драйвера режима ядра UserPort 1.0 by Tomas Franzon изменение адреса начала IOPM в TSS расширяет размер TSS до 2135h. адресный диапазон расширен до 7A80h для всех процессов и до 0FFFFh для \\.\scp07 процессов. Сочетание команд outsb и WinAPI функции Sleep. Для многопроцессорной или гипертрейдинговой машины может вызвать перезагрузку без BSOD. Полнофункциональный драйвер. Далее исходный текст драйвера scp07.sys
Первый вариант user-mode приложения, которое запускает драйвер scp07.sys user-mode приложение, которое запускает scp07.sys драйвер, используя API-функции Service Control Manager'a: OpenSCManager, CreateService, StartService, CloseServiceHandle и DeleteService. Этот способ очень прост и хорошо документирован, он подходит для постоянной установки драйверов.
Второй вариант user-mode приложения, которое запускает драйвер scp07.sys Предварительно прописываем драйвер scp07.sys в реестре "вручную" (используем функции RegOpenKey, RegCreateKey, RegSetValue) и загружаем драйвер scp07.sys с помощью функции ZwLoadDriver. В реестре создается минимум необходимых записей, запускаем драйвер, выгружаем драйвер функцией ZwUnloadDriver и удаляем его раздел из реестра (используем функции RegCloseKey, SHDeleteKey). Этот способ позволяет запускать драйвер быстро и незаметно и подходит для маленьких программ не требующих установки, но требующих запуска своего драйвера.
________________________________________ ______________
© Mikl___ 2011
7
|
19.10.2012, 06:13 | |
Помогаю со студенческими работами здесь
20
Написать драйвер для мышки Можно ли написать свой драйвер для мышки? Как скорректировать драйвер принтера Как установить свой драйвер? Как работает драйвер swapBuffers Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Опции темы | |
|
Новые блоги и статьи
![]() |
||||
Очередные открытия мега простых чисел, сделанные добровольцами с помощью домашних компьютеров
Programma_Boinc 21.04.2025
Очередные открытия мега простых чисел, сделанные добровольцами с помощью домашних компьютеров.
3 марта 2025 года, в результате обобщенного поиска простых чисел Ферма в PrimeGrid был найден. . .
|
Система статов в Unity
GameUnited 20.04.2025
Статы — фундаментальный элемент игрового дизайна, который определяет характеристики персонажей, предметов и других объектов в игровом мире. Будь то показатель силы в RPG, скорость передвижения в. . .
|
Статические свойства и методы в TypeScript
run.dev 20.04.2025
TypeScript прочно занял своё место в системе современной веб-разработки. Этот строго типизированный язык программирования не просто расширяет возможности JavaScript — он делает разработку более. . .
|
Batch Transform и Batch Gizmo Drawing API в Unity
GameUnited 20.04.2025
В мире разработки игр и приложений на Unity производительность всегда была критическим фактором успеха. Создатели игр постоянно балансируют между визуальной привлекательностью и плавностью работы. . .
|
Звук в Unity: Рандомизация с Audio Random Container
GameUnited 20.04.2025
В современных играх звуковое оформление часто становится элементом, который либо полностью погружает игрока в виртуальный мир, либо разрушает атмосферу за считанные минуты. Представьте: вы исследуете. . .
|
Максимальная производительность C#: Советы, тестирование и заключение
stackOverflow 20.04.2025
Погружение в мир микрооптимизаций C# открывает перед разработчиком целый арсенал мощных техник. Но как определить, где и когда их применять? Ответ начинается с точных измерений и профилирования.
. . .
|
Максимальная производительность C#: Предсказание ветвлений
stackOverflow 20.04.2025
Третий ключевой аспект низкоуровневой оптимизации — предсказание ветвлений. Эта тема менее известна среди разработчиков, но её влияние на производительность может быть колоссальным. Чтобы понять. . .
|
Максимальная производительность C#: Векторизация (SIMD)
stackOverflow 20.04.2025
Помимо работы с кэшем, другим ключевым аспектом низкоуровневой оптимизации является векторизация вычислений. SIMD (Single Instruction, Multiple Data) позволяет обрабатывать несколько элементов данных. . .
|
Максимальная производительность C#: Процессорный кэш
stackOverflow 20.04.2025
Знакомство с внутренним устройством процессорного кэша — ключевой шаг в написании по-настоящему быстрого кода на C#. Этот слой архитектуры компьютера часто ускользает от внимания разработчиков, но. . .
|
Максимальная производительность C#: Введение в микрооптимизации
stackOverflow 20.04.2025
В мире разработки на C# многие привыкли полагаться на . NET Runtime, который "магическим образом" сам оптимизирует код. И часто это работает - современные JIT-компиляторы творят чудеса. Но когда речь. . .
|