Hello everyone (sorry my English). There was a time, and decided to write something unusual on VB6, namely to try to write a driver. I must say before that I never wrote a driver and have no programming experience in kernel mode. The driver, according to my idea, will have to read the memory is not available in user mode, namely in the range 0x80000000 - 0xffffffff (in default mode, without IMAGE_FILE_LARGE_ADDRESS_AWARE). Immediately give the driver source code which is obtained:
Code:
' modTrickMemReader.bas - модуль драйвера
' © Кривоус Анатолий Анатольевич (The trick), 2014
Option Explicit
Public Enum NT_STATUS
STATUS_SUCCESS = 0
STATUS_INVALID_PARAMETER = &HC000000D
End Enum
Public Type UNICODE_STRING
Length As Integer
MaximumLength As Integer
lpBuffer As Long
End Type
Public Type LIST_ENTRY
Flink As Long
Blink As Long
End Type
Public Type KDEVICE_QUEUE
Type As Integer
Size As Integer
DeviceListHead As LIST_ENTRY
Lock As Long
Busy As Long
End Type
Public Type KDPC
Type As Byte
Importance As Byte
Number As Integer
DpcListEntry As LIST_ENTRY
DeferredRoutine As Long
DeferredContext As Long
SystemArgument1 As Long
SystemArgument2 As Long
DpcData As Long
End Type
Public Type DISPATCHER_HEADER
Lock As Long
SignalState As Long
WaitListHead As LIST_ENTRY
End Type
Public Type KEVENT
Header As DISPATCHER_HEADER
End Type
Public Type IO_STATUS_BLOCK
StatusPointer As Long
Information As Long
End Type
Public Type Tail
DriverContext(3) As Long
Thread As Long
AuxiliaryBuffer As Long
ListEntry As LIST_ENTRY
lpCurStackLocation As Long
OriginalFileObject As Long
End Type
Public Type IRP
Type As Integer
Size As Integer
MdlAddress As Long
Flags As Long
AssociatedIrp As Long
ThreadListEntry As LIST_ENTRY
IoStatus As IO_STATUS_BLOCK
RequestorMode As Byte
PendingReturned As Byte
StackCount As Byte
CurrentLocation As Byte
Cancel As Byte
CancelIrql As Byte
ApcEnvironment As Byte
AllocationFlags As Byte
UserIosb As Long
UserEvent As Long
Overlay As Currency
CancelRoutine As Long
UserBuffer As Long
Tail As Tail
End Type
Public Type DEVICEIOCTL
OutputBufferLength As Long
InputBufferLength As Long
IoControlCode As Long
Type3InputBuffer As Long
End Type
Public Type IO_STACK_LOCATION
MajorFunction As Byte
MinorFunction As Byte
Flags As Byte
Control As Byte
' Поле DeviceIoControl из объединения
DeviceIoControl As DEVICEIOCTL
pDeviceObject As Long
pFileObject As Long
pCompletionRoutine As Long
pContext As Long
End Type
Public Type DRIVER_OBJECT
Type As Integer
Size As Integer
pDeviceObject As Long
Flags As Long
DriverStart As Long
DriverSize As Long
DriverSection As Long
DriverExtension As Long
DriverName As UNICODE_STRING
HardwareDatabase As Long
FastIoDispatch As Long
DriverInit As Long
DriverStartIo As Long
DriverUnload As Long
MajorFunction(27) As Long
End Type
Public Type DEVICE_OBJECT
Type As Integer
Size As Integer
ReferenceCount As Long
DriverObject As Long
NextDevice As Long
AttachedDevice As Long
CurrentIrp As Long
Timer As Long
Flags As Long
Characteristics As Long
Vpb As Long
DeviceExtension As Long
DeviceType As Long
StackSize As Byte
Queue(39) As Byte
AlignRequirement As Long
DeviceQueue As KDEVICE_QUEUE
Dpc As KDPC
ActiveThreadCount As Long
SecurityDescriptor As Long
DeviceLock As KEVENT
SectorSize As Integer
Spare1 As Integer
DeviceObjExtension As Long
Reserved As Long
End Type
Private Type BinaryString
D(255) As Integer
End Type
Public Const FILE_DEVICE_UNKNOWN As Long = &H22
Public Const IO_NO_INCREMENT As Long = &H0
Public Const IRP_MJ_CREATE As Long = &H0
Public Const IRP_MJ_CLOSE As Long = &H2
Public Const IRP_MJ_DEVICE_CONTROL As Long = &HE
Public Const FILE_DEVICE_MEMREADER As Long = &H8000&
Public Const IOCTL_READ_MEMORY As Long = &H80002000
Public DeviceName As UNICODE_STRING ' Строка с именем устройства
Public DeviceLink As UNICODE_STRING ' Строка с именем ссылки
Public Device As DEVICE_OBJECT ' Объект устройства
Dim strName As BinaryString ' Строка с именем устройства
Dim strLink As BinaryString ' Строка с именем ссылки
Public Sub Main()
End Sub
' // Если ошибка - False
Public Function NT_SUCCESS(ByVal Status As NT_STATUS) As Boolean
NT_SUCCESS = Status >= STATUS_SUCCESS
End Function
' // Получить указатель на стек пакета
Public Function IoGetCurrentIrpStackLocation(pIrp As IRP) As Long
IoGetCurrentIrpStackLocation = pIrp.Tail.lpCurStackLocation
End Function
' // Точка входа в драйвер
Public Function DriverEntry(DriverObject As DRIVER_OBJECT, RegistryPath As UNICODE_STRING) As NT_STATUS
Dim Status As NT_STATUS
' Инициализация имен
Status = Init()
' Здесь не обязательна проверка, но я поставил, т.к. возможно усовершенствование функции Init
If Not NT_SUCCESS(Status) Then
DriverEntry = Status
Exit Function
End If
' Создаем устройство
Status = IoCreateDevice(DriverObject, 0, DeviceName, FILE_DEVICE_MEMREADER, 0, False, Device)
' Проверяем создалось ли устройство
If Not NT_SUCCESS(Status) Then
DriverEntry = Status
Exit Function
End If
' Создаем связь для доступа по имени из пользовательского режима
Status = IoCreateSymbolicLink(DeviceLink, DeviceName)
' Проверяем корректность
If Not NT_SUCCESS(Status) Then
' При неудаче удаляем устройство
IoDeleteDevice Device
DriverEntry = Status
Exit Function
End If
' Определяем функции
DriverObject.DriverUnload = GetAddr(AddressOf DriverUnload) ' Выгрузка драйвера
DriverObject.MajorFunction(IRP_MJ_CREATE) = GetAddr(AddressOf DriverCreateClose) ' При вызове CreateFile
DriverObject.MajorFunction(IRP_MJ_CLOSE) = GetAddr(AddressOf DriverCreateClose) ' При вызове CloseHandle
DriverObject.MajorFunction(IRP_MJ_DEVICE_CONTROL) = GetAddr(AddressOf DriverDeviceControl) ' При вызове DeviceIoControl
' Успех
DriverEntry = STATUS_SUCCESS
End Function
' // Процедура выгрузки драйвера
Public Sub DriverUnload(DriverObject As DRIVER_OBJECT)
' Удаляем связь
IoDeleteSymbolicLink DeviceLink
' Удаляем устройство
IoDeleteDevice ByVal DriverObject.pDeviceObject
End Sub
' // Функция вызывается при открытии/закрытии драйвера
Public Function DriverCreateClose(DeviceObject As DEVICE_OBJECT, pIrp As IRP) As NT_STATUS
pIrp.IoStatus.Information = 0
pIrp.IoStatus.StatusPointer = STATUS_SUCCESS
' Возвращаем IRP пакет менеджеру ввода/вывода
IoCompleteRequest pIrp, IO_NO_INCREMENT
' Успех
DriverCreateClose = STATUS_SUCCESS
End Function
' // Функция обработки IOCTL запросов
Public Function DriverDeviceControl(DeviceObject As DEVICE_OBJECT, pIrp As IRP) As NT_STATUS
Dim lpStack As Long
Dim ioStack As IO_STACK_LOCATION
' Получаем указатель на стек пакета
lpStack = IoGetCurrentIrpStackLocation(pIrp)
' Проверяем указатель на валидность
If lpStack Then
' Копируем в локальную переменную
memcpy ioStack, ByVal lpStack, Len(ioStack)
' Проверяем IOCTL и объединение AssociatedIrp в котором содержится SystemBuffer
' В SystemBuffer содержится буфер, переданный нами в DeviceIoControl
If ioStack.DeviceIoControl.IoControlCode = IOCTL_READ_MEMORY And _
pIrp.AssociatedIrp <> 0 Then
Dim lpPointer As Long
Dim DataSize As Long
' Копируем параметы из SystemBuffer
memcpy lpPointer, ByVal pIrp.AssociatedIrp, 4
memcpy DataSize, ByVal pIrp.AssociatedIrp + 4, 4
' Проверяем размер буфера
If DataSize <= ioStack.DeviceIoControl.OutputBufferLength Then
' Проверяем количество страниц, которые мы можем прочитать
Dim lpStart As Long
Dim pgCount As Long
Dim pgSize As Long
Dim pgOfst As Long
' Определяем адрес начала страницы
lpStart = lpPointer And &HFFFFF000
' Определяем смещение от начала страницы
pgOfst = lpPointer And &HFFF&
' Проход по станицам и проверка на PageFault
Do While MmIsAddressValid(ByVal lpStart) And (pgSize - pgOfst < DataSize)
lpStart = lpStart + &H1000
pgCount = pgCount + 1
pgSize = pgSize + &H1000
Loop
' Если хоть одна страница доступна
If pgCount Then
' Получаем реальный размер в байтах
pgSize = pgCount * &H1000 - pgOfst
' Корректируем резмер
If DataSize > pgSize Then DataSize = pgSize
' Возвращаем реальный размер прочитанных данных
pIrp.IoStatus.Information = DataSize
' Успех
pIrp.IoStatus.StatusPointer = STATUS_SUCCESS
' Копируем данные в SystemBuffer
memcpy ByVal pIrp.AssociatedIrp, ByVal lpPointer, DataSize
' Возвращаем IRP пакет менеджеру ввода/вывода
IoCompleteRequest pIrp, IO_NO_INCREMENT
' Упех
DriverDeviceControl = STATUS_SUCCESS
' Выход
Exit Function
End If
End If
End If
End If
' Возвращаем реальный размер прочитанных данных
pIrp.IoStatus.Information = 0
' Ошибка DeviceIoControl
pIrp.IoStatus.StatusPointer = STATUS_INVALID_PARAMETER
' Возвращаем IRP пакет менеджеру ввода/вывода
IoCompleteRequest pIrp, IO_NO_INCREMENT
' Ошибка
DriverDeviceControl = STATUS_INVALID_PARAMETER
End Function
' // Функция инициализации
Private Function Init() As NT_STATUS
' Инициализируем имя устройства
'\Device\TrickMemReader
strName.D(0) = &H5C: strName.D(1) = &H44: strName.D(2) = &H65: strName.D(3) = &H76: strName.D(4) = &H69:
strName.D(5) = &H63: strName.D(6) = &H65: strName.D(7) = &H5C: strName.D(8) = &H54: strName.D(9) = &H72:
strName.D(10) = &H69: strName.D(11) = &H63: strName.D(12) = &H6B: strName.D(13) = &H4D: strName.D(14) = &H65:
strName.D(15) = &H6D: strName.D(16) = &H52: strName.D(17) = &H65: strName.D(18) = &H61: strName.D(19) = &H64:
strName.D(20) = &H65: strName.D(21) = &H72:
' Создаем UNICODE_STRING
RtlInitUnicodeString DeviceName, strName
' Инициализация ссылки на имя устройства из user-mode
'\DosDevices\TrickMemReader
strLink.D(0) = &H5C: strLink.D(1) = &H44: strLink.D(2) = &H6F: strLink.D(3) = &H73: strLink.D(4) = &H44:
strLink.D(5) = &H65: strLink.D(6) = &H76: strLink.D(7) = &H69: strLink.D(8) = &H63: strLink.D(9) = &H65:
strLink.D(10) = &H73: strLink.D(11) = &H5C: strLink.D(12) = &H54: strLink.D(13) = &H72: strLink.D(14) = &H69:
strLink.D(15) = &H63: strLink.D(16) = &H6B: strLink.D(17) = &H4D: strLink.D(18) = &H65: strLink.D(19) = &H6D:
strLink.D(20) = &H52: strLink.D(21) = &H65: strLink.D(22) = &H61: strLink.D(23) = &H64: strLink.D(24) = &H65:
strLink.D(25) = &H72:
' Создаем UNICODE_STRING
RtlInitUnicodeString DeviceLink, strLink
'
End Function
Private Function GetAddr(ByVal Value As Long) As Long
GetAddr = Value
End Function