<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=399618&amp;view=findpost&amp;p=3574993</guid>
        <pubDate>Wed, 18 Feb 2015 18:08:15 +0000</pubDate>
        <title>Драйвер на VB6.</title>
        <link>https://forum.sources.ru/index.php?showtopic=399618&amp;view=findpost&amp;p=3574993</link>
        <description><![CDATA[TheTrik: Всем привет. Появилось время и решил написать что-то необычное на VB6, а именно попытаться написать драйвер. Сразу скажу до этого я никогда не писал драйвера и не имею никакого опыта программирования в режиме ядра. Драйвер, по моим задумкам, должен будет читать память недоступную в пользовательском режиме, а именно в диапазоне <em class='tag-i'>0x80000000 - 0xffffffff</em> (в режиме по-умолчанию, без <strong class='tag-b'>IMAGE_FILE_LARGE_ADDRESS_AWARE</strong>). Сразу приведу исходный код драйвера который получился (<a class='tag-url' href='http://www.youtube.com/v/XizH8FODgRY' target='_blank'>видео</a>):<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&#39; modTrickMemReader.bas &nbsp;- модуль драйвера</div><div class="code_line">&#39; © Кривоус Анатолий Анатольевич (The trick), 2014</div><div class="code_line">&nbsp;</div><div class="code_line">Option Explicit</div><div class="code_line">&nbsp;</div><div class="code_line">Public Enum NT_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;STATUS_SUCCESS = 0</div><div class="code_line">&nbsp;&nbsp; &nbsp;STATUS_INVALID_PARAMETER = &amp;HC000000D</div><div class="code_line">End Enum</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type UNICODE_STRING</div><div class="code_line">&nbsp;&nbsp; &nbsp;Length &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;MaximumLength &nbsp; &nbsp; &nbsp; As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpBuffer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type LIST_ENTRY</div><div class="code_line">&nbsp;&nbsp; &nbsp;Flink &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Blink &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type KDEVICE_QUEUE</div><div class="code_line">&nbsp;&nbsp; &nbsp;Type &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;Size &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeviceListHead &nbsp; &nbsp; &nbsp;As LIST_ENTRY</div><div class="code_line">&nbsp;&nbsp; &nbsp;Lock &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Busy &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type KDPC</div><div class="code_line">&nbsp;&nbsp; &nbsp;Type &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;Importance &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;Number &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;DpcListEntry &nbsp; &nbsp; &nbsp; &nbsp;As LIST_ENTRY</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeferredRoutine &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeferredContext &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;SystemArgument1 &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;SystemArgument2 &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DpcData &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type DISPATCHER_HEADER</div><div class="code_line">&nbsp;&nbsp; &nbsp;Lock &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;SignalState &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;WaitListHead &nbsp; &nbsp; &nbsp; &nbsp;As LIST_ENTRY</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type KEVENT</div><div class="code_line">&nbsp;&nbsp; &nbsp;Header &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As DISPATCHER_HEADER</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type IO_STATUS_BLOCK</div><div class="code_line">&nbsp;&nbsp; &nbsp;StatusPointer &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Information &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type Tail</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverContext(3) &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Thread &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;AuxiliaryBuffer &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;ListEntry &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As LIST_ENTRY</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpCurStackLocation &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;OriginalFileObject &nbsp;As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type IRP</div><div class="code_line">&nbsp;&nbsp; &nbsp;Type &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;Size &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;MdlAddress &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Flags &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;AssociatedIrp &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;ThreadListEntry &nbsp; &nbsp; As LIST_ENTRY</div><div class="code_line">&nbsp;&nbsp; &nbsp;IoStatus &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As IO_STATUS_BLOCK</div><div class="code_line">&nbsp;&nbsp; &nbsp;RequestorMode &nbsp; &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;PendingReturned &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;StackCount &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;CurrentLocation &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;Cancel &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;CancelIrql &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;ApcEnvironment &nbsp; &nbsp; &nbsp;As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;AllocationFlags &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;UserIosb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;UserEvent &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Overlay &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Currency</div><div class="code_line">&nbsp;&nbsp; &nbsp;CancelRoutine &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;UserBuffer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Tail &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Tail</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type DEVICEIOCTL</div><div class="code_line">&nbsp;&nbsp; &nbsp;OutputBufferLength &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;InputBufferLength &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;IoControlCode &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Type3InputBuffer &nbsp; &nbsp;As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type IO_STACK_LOCATION</div><div class="code_line">&nbsp;&nbsp; &nbsp;MajorFunction &nbsp; &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;MinorFunction &nbsp; &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;Flags &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;Control &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Поле DeviceIoControl из объединения</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeviceIoControl &nbsp; &nbsp; As DEVICEIOCTL</div><div class="code_line">&nbsp;&nbsp; &nbsp;pDeviceObject &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;pFileObject &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;pCompletionRoutine &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;pContext &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type DRIVER_OBJECT</div><div class="code_line">&nbsp;&nbsp; &nbsp;Type &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;Size &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;pDeviceObject &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Flags &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverStart &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverSize &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverSection &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverExtension &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverName &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As UNICODE_STRING</div><div class="code_line">&nbsp;&nbsp; &nbsp;HardwareDatabase &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;FastIoDispatch &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverInit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverStartIo &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverUnload &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;MajorFunction(27) &nbsp; As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Type DEVICE_OBJECT</div><div class="code_line">&nbsp;&nbsp; &nbsp;Type &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;Size &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;ReferenceCount &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverObject &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;NextDevice &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;AttachedDevice &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;CurrentIrp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Timer &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Flags &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Characteristics &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Vpb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeviceExtension &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeviceType &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;StackSize &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;Queue(39) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Byte</div><div class="code_line">&nbsp;&nbsp; &nbsp;AlignRequirement &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeviceQueue &nbsp; &nbsp; &nbsp; &nbsp; As KDEVICE_QUEUE</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dpc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As KDPC</div><div class="code_line">&nbsp;&nbsp; &nbsp;ActiveThreadCount &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;SecurityDescriptor &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeviceLock &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As KEVENT</div><div class="code_line">&nbsp;&nbsp; &nbsp;SectorSize &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;Spare1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeviceObjExtension &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Reserved &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">End Type</div><div class="code_line">Private Type BinaryString</div><div class="code_line">&nbsp;&nbsp; &nbsp;D(255) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Integer</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Public Const FILE_DEVICE_UNKNOWN &nbsp; &nbsp;As Long = &amp;H22</div><div class="code_line">Public Const IO_NO_INCREMENT &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;H0</div><div class="code_line">Public Const IRP_MJ_CREATE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;H0</div><div class="code_line">Public Const IRP_MJ_CLOSE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long = &amp;H2</div><div class="code_line">Public Const IRP_MJ_DEVICE_CONTROL &nbsp;As Long = &amp;HE</div><div class="code_line">Public Const FILE_DEVICE_MEMREADER &nbsp;As Long = &amp;H8000&amp;</div><div class="code_line">Public Const IOCTL_READ_MEMORY &nbsp; &nbsp; &nbsp;As Long = &amp;H80002000</div><div class="code_line">&nbsp;</div><div class="code_line">Public DeviceName &nbsp; &nbsp; &nbsp; As UNICODE_STRING &nbsp; &#39; Строка с именем устройства</div><div class="code_line">Public DeviceLink &nbsp; &nbsp; &nbsp; As UNICODE_STRING &nbsp; &#39; Строка с именем ссылки</div><div class="code_line">Public Device &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As DEVICE_OBJECT &nbsp; &nbsp;&#39; Объект устройства</div><div class="code_line">&nbsp;</div><div class="code_line">Dim strName As BinaryString &nbsp; &nbsp; &#39; Строка с именем устройства</div><div class="code_line">Dim strLink As BinaryString &nbsp; &nbsp; &#39; Строка с именем ссылки</div><div class="code_line">&nbsp;</div><div class="code_line">Public Sub Main()</div><div class="code_line">End Sub</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Если ошибка - False</div><div class="code_line">Public Function NT_SUCCESS(ByVal Status As NT_STATUS) As Boolean</div><div class="code_line">&nbsp;&nbsp; &nbsp;NT_SUCCESS = Status &#62;= STATUS_SUCCESS</div><div class="code_line">End Function</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Получить указатель на стек пакета</div><div class="code_line">Public Function IoGetCurrentIrpStackLocation(pIrp As IRP) As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;IoGetCurrentIrpStackLocation = pIrp.Tail.lpCurStackLocation</div><div class="code_line">End Function</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Точка входа в драйвер</div><div class="code_line">Public Function DriverEntry(DriverObject As DRIVER_OBJECT, RegistryPath As UNICODE_STRING) As NT_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim Status As NT_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Инициализация имен</div><div class="code_line">&nbsp;&nbsp; &nbsp;Status = Init()</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Здесь не обязательна проверка, но я поставил, т.к. возможно усовершенствование функции Init</div><div class="code_line">&nbsp;&nbsp; &nbsp;If Not NT_SUCCESS(Status) Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;DriverEntry = Status</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Exit Function</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Создаем устройство</div><div class="code_line">&nbsp;&nbsp; &nbsp;Status = IoCreateDevice(DriverObject, 0, DeviceName, FILE_DEVICE_MEMREADER, 0, False, Device)</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Проверяем создалось ли устройство</div><div class="code_line">&nbsp;&nbsp; &nbsp;If Not NT_SUCCESS(Status) Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;DriverEntry = Status</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Exit Function</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Создаем связь для доступа по имени из пользовательского режима</div><div class="code_line">&nbsp;&nbsp; &nbsp;Status = IoCreateSymbolicLink(DeviceLink, DeviceName)</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Проверяем корректность</div><div class="code_line">&nbsp;&nbsp; &nbsp;If Not NT_SUCCESS(Status) Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&#39; При неудаче удаляем устройство</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;IoDeleteDevice Device</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;DriverEntry = Status</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Exit Function</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Определяем функции</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverObject.DriverUnload = GetAddr(AddressOf DriverUnload) &#39; Выгрузка драйвера</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverObject.MajorFunction(IRP_MJ_CREATE) = GetAddr(AddressOf DriverCreateClose) &nbsp; &nbsp;&#39; При вызове CreateFile</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverObject.MajorFunction(IRP_MJ_CLOSE) = GetAddr(AddressOf DriverCreateClose) &nbsp; &nbsp; &#39; При вызове CloseHandle</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverObject.MajorFunction(IRP_MJ_DEVICE_CONTROL) = GetAddr(AddressOf DriverDeviceControl) &nbsp;&#39; При вызове DeviceIoControl</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Успех</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverEntry = STATUS_SUCCESS</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">End Function</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Процедура выгрузки драйвера</div><div class="code_line">Public Sub DriverUnload(DriverObject As DRIVER_OBJECT)</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Удаляем связь</div><div class="code_line">&nbsp;&nbsp; &nbsp;IoDeleteSymbolicLink DeviceLink</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Удаляем устройство</div><div class="code_line">&nbsp;&nbsp; &nbsp;IoDeleteDevice ByVal DriverObject.pDeviceObject</div><div class="code_line">End Sub</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Функция вызывается при открытии/закрытии драйвера</div><div class="code_line">Public Function DriverCreateClose(DeviceObject As DEVICE_OBJECT, pIrp As IRP) As NT_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;pIrp.IoStatus.Information = 0</div><div class="code_line">&nbsp;&nbsp; &nbsp;pIrp.IoStatus.StatusPointer = STATUS_SUCCESS</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Возвращаем IRP пакет менеджеру ввода/вывода</div><div class="code_line">&nbsp;&nbsp; &nbsp;IoCompleteRequest pIrp, IO_NO_INCREMENT</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Успех</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverCreateClose = STATUS_SUCCESS</div><div class="code_line">End Function</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Функция обработки IOCTL запросов</div><div class="code_line">Public Function DriverDeviceControl(DeviceObject As DEVICE_OBJECT, pIrp As IRP) As NT_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim lpStack As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim ioStack As IO_STACK_LOCATION</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Получаем указатель на стек пакета</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpStack = IoGetCurrentIrpStackLocation(pIrp)</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Проверяем указатель на валидность</div><div class="code_line">&nbsp;&nbsp; &nbsp;If lpStack Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&#39; Копируем в локальную переменную</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;memcpy ioStack, ByVal lpStack, Len(ioStack)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&#39; Проверяем IOCTL и объединение AssociatedIrp в котором содержится SystemBuffer</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&#39; В SystemBuffer содержится буфер, переданный нами в DeviceIoControl</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;If ioStack.DeviceIoControl.IoControlCode = IOCTL_READ_MEMORY And _</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pIrp.AssociatedIrp &#60;&#62; 0 Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Dim lpPointer &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Dim DataSize &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Копируем параметы из SystemBuffer</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memcpy lpPointer, ByVal pIrp.AssociatedIrp, 4</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memcpy DataSize, ByVal pIrp.AssociatedIrp + 4, 4</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Проверяем размер буфера</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;If DataSize &#60;= ioStack.DeviceIoControl.OutputBufferLength Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Проверяем количество страниц, которые мы можем прочитать</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Dim lpStart As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Dim pgCount As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Dim pgSize &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Dim pgOfst &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Определяем адрес начала страницы</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lpStart = lpPointer And &amp;HFFFFF000</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Определяем смещение от начала страницы</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pgOfst = lpPointer And &amp;HFFF&amp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Проход по станицам и проверка на PageFault</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Do While MmIsAddressValid(ByVal lpStart) And (pgSize - pgOfst &#60; DataSize)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lpStart = lpStart + &amp;H1000</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pgCount = pgCount + 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pgSize = pgSize + &amp;H1000</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Loop</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Если хоть одна страница доступна</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;If pgCount Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Получаем реальный размер в байтах</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pgSize = pgCount * &amp;H1000 - pgOfst</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Корректируем резмер</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;If DataSize &#62; pgSize Then DataSize = pgSize</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Возвращаем реальный размер прочитанных данных</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pIrp.IoStatus.Information = DataSize</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Успех</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pIrp.IoStatus.StatusPointer = STATUS_SUCCESS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Копируем данные в SystemBuffer</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memcpy ByVal pIrp.AssociatedIrp, ByVal lpPointer, DataSize</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Возвращаем IRP пакет менеджеру ввода/вывода</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IoCompleteRequest pIrp, IO_NO_INCREMENT</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Упех</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DriverDeviceControl = STATUS_SUCCESS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#39; Выход</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Exit Function</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Возвращаем реальный размер прочитанных данных</div><div class="code_line">&nbsp;&nbsp; &nbsp;pIrp.IoStatus.Information = 0</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Ошибка DeviceIoControl</div><div class="code_line">&nbsp;&nbsp; &nbsp;pIrp.IoStatus.StatusPointer = STATUS_INVALID_PARAMETER</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Возвращаем IRP пакет менеджеру ввода/вывода</div><div class="code_line">&nbsp;&nbsp; &nbsp;IoCompleteRequest pIrp, IO_NO_INCREMENT</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Ошибка</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverDeviceControl = STATUS_INVALID_PARAMETER</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">End Function</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Функция инициализации</div><div class="code_line">Private Function Init() As NT_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Инициализируем имя устройства</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39;\Device\TrickMemReader</div><div class="code_line">&nbsp;&nbsp; &nbsp;strName.D(0) = &amp;H5C: &nbsp; &nbsp;strName.D(1) = &amp;H44: &nbsp; &nbsp;strName.D(2) = &amp;H65: &nbsp; &nbsp;strName.D(3) = &amp;H76: &nbsp; &nbsp;strName.D(4) = &amp;H69:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strName.D(5) = &amp;H63: &nbsp; &nbsp;strName.D(6) = &amp;H65: &nbsp; &nbsp;strName.D(7) = &amp;H5C: &nbsp; &nbsp;strName.D(8) = &amp;H54: &nbsp; &nbsp;strName.D(9) = &amp;H72:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strName.D(10) = &amp;H69: &nbsp; strName.D(11) = &amp;H63: &nbsp; strName.D(12) = &amp;H6B: &nbsp; strName.D(13) = &amp;H4D: &nbsp; strName.D(14) = &amp;H65:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strName.D(15) = &amp;H6D: &nbsp; strName.D(16) = &amp;H52: &nbsp; strName.D(17) = &amp;H65: &nbsp; strName.D(18) = &amp;H61: &nbsp; strName.D(19) = &amp;H64:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strName.D(20) = &amp;H65: &nbsp; strName.D(21) = &amp;H72:</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Создаем UNICODE_STRING</div><div class="code_line">&nbsp;&nbsp; &nbsp;RtlInitUnicodeString DeviceName, strName</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Инициализация ссылки на имя устройства из user-mode</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39;\DosDevices\TrickMemReader</div><div class="code_line">&nbsp;&nbsp; &nbsp;strLink.D(0) = &amp;H5C: &nbsp; &nbsp;strLink.D(1) = &amp;H44: &nbsp; &nbsp;strLink.D(2) = &amp;H6F: &nbsp; &nbsp;strLink.D(3) = &amp;H73: &nbsp; &nbsp;strLink.D(4) = &amp;H44:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strLink.D(5) = &amp;H65: &nbsp; &nbsp;strLink.D(6) = &amp;H76: &nbsp; &nbsp;strLink.D(7) = &amp;H69: &nbsp; &nbsp;strLink.D(8) = &amp;H63: &nbsp; &nbsp;strLink.D(9) = &amp;H65:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strLink.D(10) = &amp;H73: &nbsp; strLink.D(11) = &amp;H5C: &nbsp; strLink.D(12) = &amp;H54: &nbsp; strLink.D(13) = &amp;H72: &nbsp; strLink.D(14) = &amp;H69:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strLink.D(15) = &amp;H63: &nbsp; strLink.D(16) = &amp;H6B: &nbsp; strLink.D(17) = &amp;H4D: &nbsp; strLink.D(18) = &amp;H65: &nbsp; strLink.D(19) = &amp;H6D:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strLink.D(20) = &amp;H52: &nbsp; strLink.D(21) = &amp;H65: &nbsp; strLink.D(22) = &amp;H61: &nbsp; strLink.D(23) = &amp;H64: &nbsp; strLink.D(24) = &amp;H65:</div><div class="code_line">&nbsp;&nbsp; &nbsp;strLink.D(25) = &amp;H72:</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Создаем UNICODE_STRING</div><div class="code_line">&nbsp;&nbsp; &nbsp;RtlInitUnicodeString DeviceLink, strLink</div><div class="code_line">&#39;</div><div class="code_line">End Function</div><div class="code_line">&nbsp;</div><div class="code_line">Private Function GetAddr(ByVal Value As Long) As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;GetAddr = Value</div><div class="code_line">End Function</div><div class="code_line">&nbsp;</div><div class="code_line">&#39;</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
Итак, драйвер должен иметь точку входа <strong class='tag-b'>DriverEntry</strong>, которую вызывает диспетчер ввода/вывода при загрузке драйвера. В параметрах передается указатель на объект-драйвер и указатель на строку с именем ключа реестра, соответствующего загружаемому драйверу. В процедуре <strong class='tag-b'>Init</strong> мы создаем 2 строки, одна с названием устройства, другая с названием ссылки на устройство. Т.к. мы не можем использовать рантайм в режиме ядра, то приходится создавать строку в виде статического массива, обернутого в пользовательский тип, тем самым VB6 выделяет память под этот массив в стеке. Если использовать строку, то неизбежно будет вызвана одна из функций рантайма для копирования и присваивания строки, а этого мы допустить не можем. Далее мы вызываем <strong class='tag-b'>IoCreateDevice</strong>, которая создает объект-устройство. Объект-устройство является получателем запросов ввода/вывода и к нему мы будем получать доступ при вызове функции <strong class='tag-b'>CreateFile</strong> из пользовательского режима. В качестве первого параметра передается указатель на объект-драйвера; вторым параметром передаем 0, т.к. у нас нет структуры расширения устройства и нам не нужно выделять память; третьим параметром мы передаем имя устройства, оно нам понадобится для реализации доступа к устройству; четвертым параметром передается тип устройства (см. ниже); в пятом мы передаем 0, т.к. у нас &quot;нестандартное устройство&quot;; в шестом передаем <strong class='tag-b'>False</strong>, т.к. нам не нужен монопольный режим; последний параметр - выходной. В качестве имени устройства мы должны использовать строку вида <em class='tag-i'>&#092;Device&#092;DeviceName</em> (где DeviceName - TrickMemReader), это имя нам понадобится для того, чтобы мы могли создать ссылку на него, которая в свою очередь нужна для доступа к устройству из пользовательского режима. Тип устройства у нас - <strong class='tag-b'>FILE_DEVICE_MEMREADER</strong>. Все нестандартные устройства должны иметь тип либо <strong class='tag-b'>FILE_DEVICE_UNKNOWN</strong>, либо число от 0x8000 - 0xffff. Я создал константу <strong class='tag-b'>FILE_DEVICE_MEMREADER</strong> со значением 0x8000, что соответствует первому свободному номеру. При успехе, создается устройство и заполняется структура <strong class='tag-b'>DEVICE_OBJECT</strong>. После нужно создать связь по имени между устройством из режима ядра и пользовательским режимом. В качестве имени мы используем <em class='tag-i'>&#092;DosDevices&#092;TrickMemReader</em>, из пользовательского режима мы будем обращаться к нему через ссылку &#39;&#092;&#092;.&#092;TrickMemReader&quot;. Ссылка создается через <strong class='tag-b'>IoCreateSymbolicLink</strong>. Далее мы определяем callback-процедуры, которые будут вызываться при определенных событиях:<ol class="tag-list" type="1"><li><strong class='tag-b'>DriverUnload</strong> - при деинициализации драйвера;</li><li><strong class='tag-b'>DriverCreateClose</strong> - при открытии и закрытии устройства;</li><li><strong class='tag-b'>DriverDeviceControl</strong> - при вызове <strong class='tag-b'>DeviceIoControl</strong>.</li></ol>Все. Теперь мы возвращаем <strong class='tag-b'>STATUS_SUCCESS </strong>, что соответствует успешному выполнению.<br>
Теперь рассмотрим процедуру <strong class='tag-b'>DriverUnload</strong>. Здесь все просто - мы удаляем связь и созданное устройство. В функции обработки открытия и закрытия устройства <strong class='tag-b'>DriverCreateClose</strong>, в статусе запроса мы возвращаем успех, и возвращаем <strong class='tag-b'>IRP</strong> пакет менеджеру ввода/вывода. Обмен данными между приложением и устройством осуществляется через IRP-пакеты. IRP-пакет состоит из 2-х частей: заголовок и стек переменной длины. Часть структуры представлена типом IRP. Итак, теперь мы добавляем функциональность нашему драйверу в функции <strong class='tag-b'>DriverDeviceControl</strong>. В эту функцию диспетчер ввода/вывода будет передавать IRP-пакет с данными переданными из клиентского приложения, которые мы будем формировать вызовом функции <strong class='tag-b'>DeviceIoControl</strong>. В качестве параметров мы будем передавать 2 <strong class='tag-b'>Long</strong> числа: 1-е адрес, откуда производить чтение, 2-е количество байт для чтения. Также одним из передаваемых параметров в IRP-пакете, при вызове <strong class='tag-b'>DeviceIoControl</strong>, является управляющий код ввода/вывода (<strong class='tag-b'>IOCTL</strong>), который представляет собой структуру из типа устройства, номера функции, типа передачи данных и тип доступа. Можно определить несколько таких кодов для разных операций и использовать их. Я определил код так <strong class='tag-b'>IOCTL_READ_MEMORY = 0x80002000</strong>, 8000 - соответствует типу нешего девайса <strong class='tag-b'>(FILE_DEVICE_MEMREADER</strong>); номер функции = 0x800, значения ниже зарезервированы, для пользовательских функций разрешены значения 0x800 - 0xFFF; тип передачи данных - 0x0 (<strong class='tag-b'>METHOD_BUFFERED</strong>), это значит что мы будем принимать/передавать данные через буфер, определяемый параметром <strong class='tag-b'>SystemBuffer</strong> IRP-пакета); тип доступа - <strong class='tag-b'>FILE_ANY_ACCESS</strong>. Наглядно:<br>
<img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/fc70de7abb8edfdc5da0cec1a06a4c3e.png' alt='user posted image'><br>
Итак, в функции <strong class='tag-b'>DriverDeviceControl</strong> мы получаем указатель на стек ввода/вывода IRP-запроса с помощью функции <strong class='tag-b'>IoGetCurrentIrpStackLocation</strong>, которая возвращает его из параметра <strong class='tag-b'>lpCurStackLocation</strong>. При упехе (если указатель ненулевой) копируем в локальную структуру <strong class='tag-b'>IO_STACK_LOCATION</strong> параметры на которые указывает этот указатель. Теперь мы проверяем IOCTL-код и поле <strong class='tag-b'>AssociatedIrp</strong>, которое представляет собой объединение (в VB6 нет объединений) в котором хранится указатель на <strong class='tag-b'>SystemBuffer</strong>. Т.к. у нас тип передачи данных соответствует <strong class='tag-b'>METHOD_BUFFERED</strong>, то в параметре <strong class='tag-b'>SystemBuffer</strong> содержится указатель на буфер с параметрами (адрес и размер) <strong class='tag-b'>DeviceIoControl</strong>, в этом буфере мы также можем возвратить данные которые записываются в выходной буфер <strong class='tag-b'>DeviceIoControl</strong>. Теперь если у нас данные содержат корректные значения (<strong class='tag-b'>IOCTL</strong> и <strong class='tag-b'>SystemBuffer</strong>), то мы копируем в локальные переменные параметры (<strong class='tag-b'>lpPointer</strong>, <strong class='tag-b'>DataSize</strong>). Далее проверяем размер буфера. Размер системного буфера ввода/вывода содержится в параметре <strong class='tag-b'>DeviceIoControl.OutputBufferLength</strong>. Если запрошенное количество байт не больше чем размер системного буфера, то все отлично. Теперь мы должны вычислить количество страниц памяти занимаемой данными которые мы хотим скопировать. Для этого мы определяем виртуальный адрес начала страницы соответствующей переданному указателю, и т.к. размер страниц кратен 4 кБ (0x1000) мы просто зануляем 12 бит указателя. Далее мы проверяем в цикле не будет ли вызвано исключение Page fault с помощью функции <strong class='tag-b'>MmIsAddressValid</strong>. Если страница отсутствует в ОЗУ, то функция возвратит <strong class='tag-b'>False</strong>. Таким образом мы проверяем количество страниц которые занимает нужный нам участок памяти и количество страниц которые мы сможем прочитать. Далее мы вычисляем реальный размер данных, которые мы сможем прочесть и при необходимости корректируем размер. Далее в заголовок <strong class='tag-b'>IRP</strong>-пакета мы копируем размер данных, который мы можем прочесть и успешный статус. Поле <strong class='tag-b'>IoStatus.Information</strong> пакета соответствует значению которое возвращает <strong class='tag-b'>DeviceIoControl</strong> в параметре <strong class='tag-b'>lpBytesReturned</strong>. Далее копируем в <strong class='tag-b'>SystemBuffer</strong> нужное количество байт с помощью <strong class='tag-b'>RtlMoveMemory</strong> и возвращаем <strong class='tag-b'>IRP</strong>-пакет менеджеру ввода/вывода. Возвращаем статус успешной операции. Во всех остальных случаях возвращаем ошибку <strong class='tag-b'>STATUS_INVALID_PARAMETER</strong> и нулевой размер данных. Все, код драйвера готов.<br>
Приступим к компиляции. Т.к. мы не можем использовать рантайм, все <strong class='tag-b'>API</strong>-функции мы объявляем в <strong class='tag-b'>TLB</strong>, для того чтобы они попали в импорт:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">[uuid(0000001F-0000-0000-0000-000000000AAB)]</div><div class="code_line">library ImportFunctionsForTrickMemReaderDriver</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp; &nbsp;[dllname(&quot;Ntoskrnl.exe&quot;)] </div><div class="code_line">&nbsp;&nbsp; &nbsp;module Ntoskrnl</div><div class="code_line">&nbsp;&nbsp; &nbsp;{ </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;IoCreateDevice&quot;)]int IoCreateDevice</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *DriverObject, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int &nbsp; &nbsp; DeviceExtensionSize,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;void &nbsp; &nbsp;*DeviceName,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int &nbsp; &nbsp; DeviceType,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int &nbsp; &nbsp; DeviceCharacteristics,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int &nbsp; &nbsp; Exclusive,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;void &nbsp; &nbsp;*DeviceObject);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;IoCreateSymbolicLink&quot;)]int IoCreateSymbolicLink</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *SymbolicLinkName, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;void &nbsp; &nbsp;*DeviceName);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;IoDeleteDevice&quot;)]void IoDeleteDevice</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *DeviceObject);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;IoDeleteSymbolicLink&quot;)]int IoDeleteSymbolicLink</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *SymbolicLinkName);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;IoCompleteRequest&quot;)]void IoCompleteRequest</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *pIrp, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unsigned char &nbsp; PriorityBoost);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;RtlInitUnicodeString&quot;)]int RtlInitUnicodeString</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *UnicodeString, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;void &nbsp; &nbsp;*StringPtr);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;RtlMoveMemory&quot;)]void memcpy</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *Destination, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;void &nbsp; &nbsp;*Source,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int &nbsp; &nbsp; Length);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;MmIsAddressValid&quot;)]int MmIsAddressValid</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *VirtualAddress);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[entry(&quot;InterlockedExchange&quot;)]int InterlockedExchange</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(void &nbsp; *Target, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;void &nbsp; &nbsp;*Value);</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">}</div></ol></div></div></div></div><br>
<em class='tag-i'>PS. InterlockedExchange - я оставил, т.к. вначале драйвер имел немного другую структуру, в последствии оставил объявление в TLB. В драйвере она не попадет в импорт.</em><br>
Для того чтобы драйвер работал нужно сделать три вещи:<ol class="tag-list" type="1"><li>В поле <strong class='tag-b'>Subsystem</strong> структуры <strong class='tag-b'>IMAGE_OPTIONAL_HEADER</strong> PE-файла драйвера должно быть значение <strong class='tag-b'>IMAGE_SUBSYSTEM_NATIVE</strong> что соответствует драйверу режима ядра.</li><li>Указать в качестве точки входа нашу процедуру <strong class='tag-b'>DriverEntry</strong></li><li>Добавить секцию релокации, для того чтобы драйвер мог загружаться по любому адресу.</li><li>Исключить <strong class='tag-b'>MSVBVM60</strong> из иморта.</li></ol>Для первых 3-х пунктов добавляем ключи компиляции в <strong class='tag-b'>vbp</strong>-файл, со следующим содержимым:<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">[VBCompiler]</div><div class="code_line">LinkSwitches= /ENTRY:DriverEntry /SUBSYSTEM:NATIVE /FIXED:NO</div></ol></div></div></div></div><br>
Компилируем проект со всеми опциями оптимизации. Для исключения рантайма из импорта, я использую свою утилиту <strong class='tag-b'>Patch</strong>, которую я использовал <a class='tag-url' href='http://bbs.vbstreets.ru/viewtopic.php?f=15&t=45597' target='_blank'>тут</a>. Я немного доработал ее, т.к. изначально не мог запустить драйвер и долго ломал голову из-за чего это происходит, а причина была в контрольной сумме. После исключения из импорта библиотеки контрольная сумма поменялась, а я не обновлял ее. В <strong class='tag-b'>EXE</strong> файлах, <strong class='tag-b'>DLL</strong> и т.д. это поле не проверяется, а в драйверах проверяется. Для проверки смотрим импорт в любой программе для просмотра PE:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/605bbe6bf6b59452a6cd6d672ff966ad.png' alt='user posted image'></div><br>
Как видим рантайма нет. Что нам и требовалось.<br>
Для тестирования драйвера я написал простую программку, которая загружает драйвер и работает с ним.<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&#39; frmTestTrickVBDriver.frm &nbsp;- форма для тестирования драйвера</div><div class="code_line">&#39; © Кривоус Анатолий Анатольевич (The trick), 2014</div><div class="code_line">&nbsp;</div><div class="code_line">Option Explicit</div><div class="code_line">&nbsp;</div><div class="code_line">Private Type SERVICE_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwServiceType &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwCurrentState &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwControlsAccepted &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwWin32ExitCode &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwServiceSpecificExitCode &nbsp; As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwCheckPoint &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwWaitHint &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">End Type</div><div class="code_line">&nbsp;</div><div class="code_line">Private Declare Function ControlService Lib &quot;advapi32.dll&quot; (ByVal hService As Long, ByVal dwControl As Long, lpServiceStatus As SERVICE_STATUS) As Long</div><div class="code_line">Private Declare Function OpenSCManager Lib &quot;advapi32.dll&quot; Alias &quot;OpenSCManagerW&quot; (ByVal lpMachineName As Long, ByVal lpDatabaseName As Long, ByVal dwDesiredAccess As Long) As Long</div><div class="code_line">Private Declare Function CloseServiceHandle Lib &quot;advapi32.dll&quot; (ByVal hSCObject As Long) As Long</div><div class="code_line">Private Declare Function OpenService Lib &quot;advapi32.dll&quot; Alias &quot;OpenServiceW&quot; (ByVal hSCManager As Long, ByVal lpServiceName As Long, ByVal dwDesiredAccess As Long) As Long</div><div class="code_line">Private Declare Function CreateService Lib &quot;advapi32.dll&quot; Alias &quot;CreateServiceW&quot; (ByVal hSCManager As Long, ByVal lpServiceName As Long, ByVal lpDisplayName As Long, ByVal dwDesiredAccess As Long, ByVal dwServiceType As Long, ByVal dwStartType As Long, ByVal dwErrorControl As Long, ByVal lpBinaryPathName As Long, ByVal lpLoadOrderGroup As String, lpdwTagId As Long, ByVal lpDependencies As Long, ByVal lp As Long, ByVal lpPassword As Long) As Long</div><div class="code_line">Private Declare Function StartService Lib &quot;advapi32.dll&quot; Alias &quot;StartServiceW&quot; (ByVal hService As Long, ByVal dwNumServiceArgs As Long, ByVal lpServiceArgVectors As Long) As Long</div><div class="code_line">Private Declare Function DeleteService Lib &quot;advapi32.dll&quot; (ByVal hService As Long) As Long</div><div class="code_line">Private Declare Function CreateFile Lib &quot;kernel32&quot; Alias &quot;CreateFileW&quot; (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long</div><div class="code_line">Private Declare Function CloseHandle Lib &quot;kernel32&quot; (ByVal hObject As Long) As Long</div><div class="code_line">Private Declare Function DeviceIoControl Lib &quot;kernel32&quot; (ByVal hDevice As Long, ByVal dwIoControlCode As Long, lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, ByVal nOutBufferSize As Long, lpBytesReturned As Long, lpOverlapped As Any) As Long</div><div class="code_line">&nbsp;</div><div class="code_line">Private Const ERROR_SERVICE_ALREADY_RUNNING As Long = 1056&amp;</div><div class="code_line">Private Const ERROR_SERVICE_EXISTS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = 1073&amp;</div><div class="code_line">Private Const SERVICE_CONTROL_STOP &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;H1</div><div class="code_line">Private Const SC_MANAGER_ALL_ACCESS &nbsp; &nbsp; &nbsp; &nbsp; As Long = &amp;HF003F</div><div class="code_line">Private Const SERVICE_ALL_ACCESS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;HF01FF</div><div class="code_line">Private Const SERVICE_KERNEL_DRIVER &nbsp; &nbsp; &nbsp; &nbsp; As Long = &amp;H1</div><div class="code_line">Private Const SERVICE_DEMAND_START &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;H3</div><div class="code_line">Private Const SERVICE_ERROR_NORMAL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;H1</div><div class="code_line">Private Const GENERIC_READ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;H80000000</div><div class="code_line">Private Const GENERIC_WRITE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long = &amp;H40000000</div><div class="code_line">Private Const FILE_SHARE_READ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long = &amp;H1</div><div class="code_line">Private Const FILE_SHARE_WRITE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = &amp;H2</div><div class="code_line">Private Const OPEN_EXISTING &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long = 3</div><div class="code_line">Private Const FILE_ATTRIBUTE_NORMAL &nbsp; &nbsp; &nbsp; &nbsp; As Long = &amp;H80</div><div class="code_line">Private Const INVALID_HANDLE_VALUE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;As Long = -1</div><div class="code_line">Private Const IOCTL_READ_MEMORY &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; As Long = &amp;H80002000</div><div class="code_line">&nbsp;</div><div class="code_line">Private Const DriverName &nbsp; &nbsp;As String = &quot;TrickMemReader&quot;</div><div class="code_line">Private Const NumOfRows &nbsp; &nbsp; As Long = 32</div><div class="code_line">&nbsp;</div><div class="code_line">Private DriverFile &nbsp;As String</div><div class="code_line">Private hMgr &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">Private hSrv &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">Private hDev &nbsp; &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">Private buffer() &nbsp; &nbsp;As Byte</div><div class="code_line">Private bufLen &nbsp; &nbsp; &nbsp;As Long</div><div class="code_line">Private Address &nbsp; &nbsp; As Long</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Нажатие на кнопку чтения памяти по адресу</div><div class="code_line">Private Sub cmdRead_Click()</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim param(1) &nbsp; &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;On Error GoTo Cancel</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Address = CLng(&quot;&amp;H&quot; &amp; Trim(txtAddress.Text))</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Формируем параметры</div><div class="code_line">&nbsp;&nbsp; &nbsp;param(0) = Address</div><div class="code_line">&nbsp;&nbsp; &nbsp;param(1) = 16 * NumOfRows</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Делаем запрос драйверу</div><div class="code_line">&nbsp;&nbsp; &nbsp;If DeviceIoControl(hDev, IOCTL_READ_MEMORY, param(0), 8, buffer(0), UBound(buffer) + 1, bufLen, ByVal 0&amp;) = 0 Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;bufLen = 0</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Update</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">Cancel:</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">End Sub</div><div class="code_line">&nbsp;</div><div class="code_line">Private Sub Form_Load()</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim sw &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim sh &nbsp;As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Выделяем буфер</div><div class="code_line">&nbsp;&nbsp; &nbsp;ReDim buffer(16 * NumOfRows - 1)</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Получаем имя файла драйвера</div><div class="code_line">&nbsp;&nbsp; &nbsp;DriverFile = App.Path &amp; &quot;\&quot; &amp; DriverName &amp; &quot;.sys&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Открываем БД диспетчера управления службами</div><div class="code_line">&nbsp;&nbsp; &nbsp;hMgr = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS)</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;If hMgr = 0 Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;MsgBox &quot;Не удалось установить связь с диспетчером управления службами&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;End</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Создаем службу</div><div class="code_line">&nbsp;&nbsp; &nbsp;hSrv = CreateService(hMgr, StrPtr(DriverName), StrPtr(DriverName), SERVICE_ALL_ACCESS, _</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, StrPtr(DriverFile), _</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0, 0, 0, 0, 0)</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Если служба уже запущена</div><div class="code_line">&nbsp;&nbsp; &nbsp;If hSrv = 0 And Err.LastDllError = ERROR_SERVICE_EXISTS Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&#39; Открываем службу</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;hSrv = OpenService(hMgr, StrPtr(DriverName), SERVICE_ALL_ACCESS)</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;If hSrv = 0 Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;MsgBox &quot;Не удалось создать службу&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Unload Me</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;End</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Запускаем драйвер</div><div class="code_line">&nbsp;&nbsp; &nbsp;If StartService(hSrv, 0, 0) = 0 Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;If Err.LastDllError &#60;&#62; ERROR_SERVICE_ALREADY_RUNNING Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox &quot;Не удалось запустить службу&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Unload Me</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;End</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Подключаемся к драйверу</div><div class="code_line">&nbsp;&nbsp; &nbsp;hDev = CreateFile(StrPtr(&quot;\.\&quot; &amp; DriverName), GENERIC_READ Or FILE_SHARE_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&amp;, _</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;If hDev = INVALID_HANDLE_VALUE Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;MsgBox &quot;Не возможно подключится к драйверу&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Unload Me</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;End</div><div class="code_line">&nbsp;&nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Определяем положение и размер контролов и формы</div><div class="code_line">&nbsp;&nbsp; &nbsp;sw = picDump.TextWidth(&quot;_&quot;)</div><div class="code_line">&nbsp;&nbsp; &nbsp;sh = picDump.TextHeight(&quot;_&quot;)</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;picDump.Move 5, 5, (sw * 77) + (picDump.Width - picDump.ScaleWidth), (sh * NumOfRows) + (picDump.Height - picDump.ScaleHeight)</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;lblAddress.Top = picDump.Top + picDump.Height + 5</div><div class="code_line">&nbsp;&nbsp; &nbsp;txtAddress.Top = lblAddress.Top</div><div class="code_line">&nbsp;&nbsp; &nbsp;cmdRead.Top = txtAddress.Top</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Me.Width = (picDump.Width + 10 - Me.ScaleWidth) * Screen.TwipsPerPixelX + Me.Width</div><div class="code_line">&nbsp;&nbsp; &nbsp;Me.Height = (txtAddress.Top + 5 + txtAddress.Height - Me.ScaleHeight) * Screen.TwipsPerPixelY + Me.Height</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Update</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">End Sub</div><div class="code_line">&nbsp;</div><div class="code_line">&#39; // Обновить данные в окне</div><div class="code_line">Private Sub Update()</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim col As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim row As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim ptr As Long</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim hxd As String</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim asi As String</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim adr As String</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim out As String</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;For row = 0 To NumOfRows - 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adr = Hex(Address + row * 16)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adr = String(8 - Len(adr), &quot;0&quot;) &amp; adr</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;asi = &quot;&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;hxd = &quot;&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;For col = 0 To 15</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;If ptr &#60; bufLen Then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;hxd = hxd &amp; &quot; &quot; &amp; IIf(buffer(ptr) &#60; &amp;H10, &quot;0&quot; &amp; Hex(buffer(ptr)), Hex(buffer(ptr)))</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;asi = asi &amp; IIf(buffer(ptr) &#62;= 32, Chr$(buffer(ptr)), &quot;?&quot;)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Else</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;hxd = hxd &amp; &quot; ??&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;asi = asi &amp; &quot;?&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;End If</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ptr = ptr + 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Next</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;If row Then out = out &amp; vbNewLine</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;out = out &amp; adr &amp; &quot;:&quot; &amp; hxd &amp; &quot; | &quot; &amp; asi</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Next</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;picDump.Cls</div><div class="code_line">&nbsp;&nbsp; &nbsp;picDump.Print out</div><div class="code_line">&nbsp;&nbsp; &nbsp;</div><div class="code_line">End Sub</div><div class="code_line">&nbsp;</div><div class="code_line">Private Sub Form_Unload(Cancel As Integer)</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dim Status As SERVICE_STATUS</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Отключаемся от драйвера</div><div class="code_line">&nbsp;&nbsp; &nbsp;CloseHandle hDev</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Останавливаем драйвер</div><div class="code_line">&nbsp;&nbsp; &nbsp;ControlService hSrv, SERVICE_CONTROL_STOP, Status</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Удаляем службу</div><div class="code_line">&nbsp;&nbsp; &nbsp;DeleteService hSrv</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39; Закрываем описатели</div><div class="code_line">&nbsp;&nbsp; &nbsp;CloseServiceHandle hSrv</div><div class="code_line">&nbsp;&nbsp; &nbsp;CloseServiceHandle hMgr</div><div class="code_line">End Sub</div></ol></div></div></div></div><br>
Драйвер должен лежать в той же папке что и программа. Код прокомментирован, так что я не буду описывать его работу.<br>
Для отладки драйвера нужно использовать ядерный отладчик. Отлаживать будем на виртуальной системе (<strong class='tag-b'>VMware</strong>) - <strong class='tag-b'>Windows XP</strong>. В качестве отладчика возьмем <strong class='tag-b'>Syser</strong>, выберем наш драйвер и нажмем <strong class='tag-b'>Load</strong>. Система остановится, и мы перейдем в окно отладчика:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/f4d3f233210f47b8d07a367a0a451265.png' alt='user posted image'></div><br>
Мы находимся в начале функции <strong class='tag-b'>DriverEntry</strong>. Первый <strong class='tag-b'>CALL</strong> соответствует вызову функции <strong class='tag-b'>Init</strong>. Если мы проследим пошагово  (F8) что там внутри, то увидим как заполняется структура и вызывается <strong class='tag-b'>RtlInitUnicodeString</strong> для имени устройства и символической связи. Второй <strong class='tag-b'>CALL</strong> соответствует функции <strong class='tag-b'>NT_SUCCESS</strong>, смотрим что она возвращает <strong class='tag-b'>TRUE</strong> (в регистре <strong class='tag-b'>EAX</strong>) и код прыгает после проверки (<strong class='tag-b'>TEST EAX, EAX</strong>) на ноль (<strong class='tag-b'>False</strong>) дальше:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/81170c613555c3dbee384ba89c3b2a84.png' alt='user posted image'></div><br>
Как видно код заталкивает в стек параметры для функции <strong class='tag-b'>IoCreateDevice</strong> от последнего к первому с помощью <strong class='tag-b'>PUSH</strong>&#39;ей. Начнем проверку параметров. Проверим имя устройства (3-й параметр - <strong class='tag-b'>PUSH 0f8a2c010</strong>), для этого введем команду <strong class='tag-b'>d 0f8a2c010</strong> (что значит просмотреть дамп памяти по адресу <strong class='tag-b'>f8a2c010</strong> и смотрим содержимое:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/5f2aeb510dfa35905ab0782e86fd18c1.png' alt='user posted image'></div><br>
первые 8 байт - это наша переменная <strong class='tag-b'>DeviceName</strong>. Первые два слова - соответственно длина строки и максимальная длина строки в байтах. Следующее двойное слово - указатель на строку, смотрим (<strong class='tag-b'>d f8a2c0d8</strong> учитываем порядок байтов little-endian):<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/cc7245045783d6d5e932858ed4abc175.png' alt='user posted image'></div><br>
, то что нужно там <strong class='tag-b'>Unicode</strong> строка с именем устройства. Если посмотреть на параметр <strong class='tag-b'>Device</strong> (последний выходной параметр - <strong class='tag-b'>PUSH 0f8a2c020</strong>), то можно увидеть что он отличается от имени на 0x10 байт. Теперь посмотрим  на декларации переменных, переменная <strong class='tag-b'>Device</strong> задекларирована после <strong class='tag-b'>DeviceName</strong> и <strong class='tag-b'>DeviceLink</strong>, общей длиной 8 + 8 = 0x10 байт. Т.е. порядок расположения переменных в памяти соответствует порядку объявления в коде. Проверяем первый неконстантный параметр <strong class='tag-b'>ESI</strong>, в самом начале в него копируется значение по адресу <strong class='tag-b'>ESP+0xC</strong>. Регистр <strong class='tag-b'>ESP</strong> - указывает на вершину стека. Если пройти в начало функции <strong class='tag-b'>DriverEntry</strong>, то можно увидеть сохранение в стеке двух регистров <strong class='tag-b'>ESI</strong> и <strong class='tag-b'>EDI</strong> (по соглашению <strong class='tag-b'>StdCall</strong> эти регистры находятся в списке сохраняемых, т.е. процедура не должна изменять их после вызова). <strong class='tag-b'>DriverObject</strong> передается в первой паременной, т.е. ближе всех к вершине стека, также после всех параметров сохраняется адрес возврата - т.е. параметр <strong class='tag-b'>DriverObject</strong> до выполнения первой инструкции в функции <strong class='tag-b'>DriverEntry</strong> находится по адресу <strong class='tag-b'>ESP+4</strong> (стек растет в сторону уменьшения адресов), после двух <strong class='tag-b'>PUSH</strong>&#39;ей он соответственно смещается еще на 8 байт, в итоге <strong class='tag-b'>DriverObject</strong> находится по адресу <strong class='tag-b'>ESP+0С</strong>, все правильно. Параметры корректные, можно вызывать функцию. Жмем <strong class='tag-b'>F10</strong> чтобы не заходить внутрь <strong class='tag-b'>IoCreateDevice</strong> и смотрим значение регистра <strong class='tag-b'>EAX</strong> после вызова, там должно быть неотрицательное число, что сигнализирует что функция отработала без ошибок. У меня она возвратила 0 (<strong class='tag-b'>STATUS_SUCCESS</strong>), все отлично. Дальше идет уже знакомая процедура по адресу <strong class='tag-b'>0xF8A2B750</strong> - <strong class='tag-b'>NT_SUCCESS</strong>:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/ca0e7726a42a199e3bf2870002b5cd9b.png' alt='user posted image'></div><br>
При успехе идет прыжок на <strong class='tag-b'>0xf8a2b7bf</strong>, где идет заталкивание в стек параметров для функции <strong class='tag-b'>IoCreateSymbolicLink</strong>. Параметр <strong class='tag-b'>DeviceName</strong> мы уже проверяли, проверяем <strong class='tag-b'>DeviceLink</strong>:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/bdf845edfcc2e98d2caf532df58dc0aa.png' alt='user posted image'></div><br>
То что нужно. Жмем <strong class='tag-b'>F10</strong>, тестируем <strong class='tag-b'>EAX</strong>, при успехе идем дальше при неудаче, удаляем девайс и выходим с ошибкой. Процедура по адресу <strong class='tag-b'>0xf8a2bbb0</strong> - это <strong class='tag-b'>GetAddr</strong>, которая просто возвращает переданное ей значение:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/54b06d98f4c5bde00dc3fc289fe49468.png' alt='user posted image'></div><br>
Дальше идет копирование адресов по смещениям <strong class='tag-b'>DriverObject</strong>, если посмотреть деларации то можно увидеть что по смещению 0x34 записывается адрес <strong class='tag-b'>DriverUnload</strong>, по смещению 0x38 - <strong class='tag-b'>MajorFunction(0)</strong> и т.д. Записываемые значения соответствуют адресам функций в нашем драйвере. Дальше происходит обнуление <strong class='tag-b'>EAX</strong> (возвращаемой значение) и выход из процедуры <strong class='tag-b'>DriverEntry</strong>. Все работает без ошибок, идем дальше. Итак, чтобы отследить работу драйвера мы поставим точку останова на функцию <strong class='tag-b'>DriverDeviceControl</strong>. Адрес ее можно взять по только что записанным смещениям в структуре <strong class='tag-b'>DRIVER_OBJECT</strong> либо найти простым просмотром и анализированием кода. В моем тесте адрес равен <strong class='tag-b'>0xf8a2b870</strong>, переходим на него (<strong class='tag-b'>. 0xf8a2b870</strong>) и нажимаем <strong class='tag-b'>F9</strong>, ставя точку останова. Напротив инструкции установится маркер:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/ac11fb67583c7797325f052173421e37.png' alt='user posted image'></div><br>
Теперь при вызове этой функции отладчик остановит выполнение кода и даст нам возможность пошагово выполнить код. Функции <strong class='tag-b'>DriverCreateClose</strong> и <strong class='tag-b'>DriverUnload</strong> я не буду описывать, т.к. там все просто. Жмем <strong class='tag-b'>F5</strong>, тем самым продолжая выполнение в обычном режиме. Нас тут же переносит обратно в <strong class='tag-b'>Windows</strong>. Теперь мы запускаем наше тестовое приложение, вводим какой-нибудь адрес (например 81234567) и жмем на кнопку <strong class='tag-b'>Read</strong>. Наш вызов перехватывает отладчик и мы можем продолжить тестировать код функции <strong class='tag-b'>DriverDeviceControl</strong>.<br>
Подробно внутри я не буду описывать код, остановлюсь на самом копировании:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/4dd0571fa270db28d43853409272bceb.png' alt='user posted image'></div><br>
Сразу смотрим на стек (регистр <strong class='tag-b'>ESP</strong>), видим что передаются правильные параметры. На всякий случай делаем дамп, потом сравним:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/76934867bde157ce6121458cfaf17dcd.png' alt='user posted image'></div><br>
Нажимаем <strong class='tag-b'>F5</strong> - и возвращаемся в <strong class='tag-b'>Windows</strong>. Смотрим на дамп уже в нашей программе:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/aec0f649b934c2944aa6244f01457be2.png' alt='user posted image'></div><br>
Как видим все отлично скопировалось. Попробуем скопировать данные на границе страниц, так чтобы одна страница отсутствовала. Экспериментальным  методом была найдена такая страница вот что получаем:<br>
<div class='tag-align-center'><img class='tag-img' src='http://s7.hostingkartinok.com/uploads/images/2014/11/6510dab845e276b929c25f95c2bfe984.png' alt='user posted image'></div><br>
Как видим, что данные скопировались корректно, где не получилось там у нас отображаются вопросительные знаки. В выходном параметре <strong class='tag-b'>DeviceIoControl</strong> у нас возвращается количество реально прочитанных байт, его мы и используем для отображения вопросительных знаков. <br>
<hr><br>
Как видим на <strong class='tag-b'>VB6</strong> можно написать простой драйвер, а если использовать ассемблерные вставки можно и посерьезнее что-нибудь написать. Всем спасибо за внимание. Удачи&#33;<br>
<span class="b-attach" data-size="40497" data-hits="240" data-attach-id="43650" data-attach-post-id="3574993">
			<span class="b-attach__title"></span><a class='b-attach-link' href='https://forum.sources.ru/index.php?act=Attach&amp;type=post&amp;id=3574993&amp;attach_id=43650' title='Скачать файл' target='_blank'>TrickVB6Driver.rar</a> (, : 240)
		</span>]]></description>
        <author>TheTrik</author>
        <category>Visual Basic: Общие вопросы</category>
      </item>
	
      </channel>
      </rss>
	