|
-
Feb 11th, 2015, 07:28 AM
#1
[VB6] - Kernel mode driver.
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 - driver module
' // © Krivous Anatoly Anatolevich (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 ' // Device name unicode string
Public DeviceLink As UNICODE_STRING ' // Device link unicode string
Public Device As DEVICE_OBJECT ' // Device object
Dim strName As BinaryString ' // Device name string
Dim strLink As BinaryString ' // Device link string
Public Sub Main()
End Sub
' // If error - false
Public Function NT_SUCCESS( _
ByVal Status As NT_STATUS) As Boolean
NT_SUCCESS = Status >= STATUS_SUCCESS
End Function
' // Get pointer to IRP stack
Public Function IoGetCurrentIrpStackLocation( _
ByRef pIrp As IRP) As Long
IoGetCurrentIrpStackLocation = pIrp.Tail.lpCurStackLocation
End Function
' // Entry point of driver
Public Function DriverEntry( _
ByRef DriverObject As DRIVER_OBJECT, _
ByRef RegistryPath As UNICODE_STRING) As NT_STATUS
Dim Status As NT_STATUS
' // Strings initialization
Status = Init()
' // This checking is not required but i left it because you can improve Init function
If Not NT_SUCCESS(Status) Then
DriverEntry = Status
Exit Function
End If
' // Create new device
Status = IoCreateDevice(DriverObject, 0, DeviceName, FILE_DEVICE_MEMREADER, 0, False, Device)
' // Check if device has been created
If Not NT_SUCCESS(Status) Then
DriverEntry = Status
Exit Function
End If
' // Create link, in order to access to object from user mode
Status = IoCreateSymbolicLink(DeviceLink, DeviceName)
' // Check if link has been created
If Not NT_SUCCESS(Status) Then
' // If is not created then delete device
IoDeleteDevice Device
DriverEntry = Status
Exit Function
End If
' // Set callback functions
DriverObject.DriverUnload = GetAddr(AddressOf DriverUnload) ' // Driver unloading
DriverObject.MajorFunction(IRP_MJ_CREATE) = GetAddr(AddressOf DriverCreateClose) ' // When CreateFile is being called
DriverObject.MajorFunction(IRP_MJ_CLOSE) = GetAddr(AddressOf DriverCreateClose) ' // When CloseHandle is being called
DriverObject.MajorFunction(IRP_MJ_DEVICE_CONTROL) = GetAddr(AddressOf DriverDeviceControl) ' // When DeviceIoControl is being called
' // Everything fine
DriverEntry = STATUS_SUCCESS
End Function
' // Unloading driver procedure
Public Sub DriverUnload( _
ByRef DriverObject As DRIVER_OBJECT)
' // Delete link
IoDeleteSymbolicLink DeviceLink
' // Delete device
IoDeleteDevice ByVal DriverObject.pDeviceObject
End Sub
' // This function is being called during opening/closing driver
Public Function DriverCreateClose( _
ByRef DeviceObject As DEVICE_OBJECT, _
ByRef pIrp As IRP) As NT_STATUS
pIrp.IoStatus.Information = 0
pIrp.IoStatus.StatusPointer = STATUS_SUCCESS
' // Return IRP packet to IO manager
IoCompleteRequest pIrp, IO_NO_INCREMENT
' // Success
DriverCreateClose = STATUS_SUCCESS
End Function
' // IOCTL processing procedure
Public Function DriverDeviceControl( _
ByRef DeviceObject As DEVICE_OBJECT, _
ByRef pIrp As IRP) As NT_STATUS
Dim lpStack As Long
Dim ioStack As IO_STACK_LOCATION
' // Get pointer to IRP stack
lpStack = IoGetCurrentIrpStackLocation(pIrp)
' // If valid pointer
If lpStack Then
' // Copy to local variable
memcpy ioStack, ByVal lpStack, Len(ioStack)
' // Check IOCTL and AssociatedIrp union that contains SystemBuffer
' // SystemBuffer contains the buffer passed from DeviceIoControl
If ioStack.DeviceIoControl.IoControlCode = IOCTL_READ_MEMORY And _
pIrp.AssociatedIrp <> 0 Then
Dim lpPointer As Long
Dim DataSize As Long
' // Copy parameters from SystemBuffer
memcpy lpPointer, ByVal pIrp.AssociatedIrp, 4
memcpy DataSize, ByVal pIrp.AssociatedIrp + 4, 4
' П// Check buffer size
If DataSize <= ioStack.DeviceIoControl.OutputBufferLength Then
' // Get the number of allowed pages
Dim lpStart As Long
Dim pgCount As Long
Dim pgSize As Long
Dim pgOfst As Long
' // Get first address of page
lpStart = lpPointer And &HFFFFF000
' // Get offset at beginning of page
pgOfst = lpPointer And &HFFF&
' // Go thru pages and check PageFault error
Do While MmIsAddressValid(ByVal lpStart) And (pgSize - pgOfst < DataSize)
lpStart = lpStart + &H1000
pgCount = pgCount + 1
pgSize = pgSize + &H1000
Loop
' // If there are allowed pages
If pgCount Then
' // Get size in bytes
pgSize = pgCount * &H1000 - pgOfst
' // Fix size
If DataSize > pgSize Then DataSize = pgSize
' // Return total read bytes
pIrp.IoStatus.Information = DataSize
' // Success to DeviceIoControl
pIrp.IoStatus.StatusPointer = STATUS_SUCCESS
' Copy data to system buffer
memcpy ByVal pIrp.AssociatedIrp, ByVal lpPointer, DataSize
' // Return IRP packet to IO manager
IoCompleteRequest pIrp, IO_NO_INCREMENT
' // Success
DriverDeviceControl = STATUS_SUCCESS
' // Exit
Exit Function
End If
End If
End If
End If
' // Return real size of read bytes
pIrp.IoStatus.Information = 0
' // Error to DeviceIoControl
pIrp.IoStatus.StatusPointer = STATUS_INVALID_PARAMETER
' // Return IRP packet to IO manager
IoCompleteRequest pIrp, IO_NO_INCREMENT
' // Error
DriverDeviceControl = STATUS_INVALID_PARAMETER
End Function
' // Initialize all strings
Private Function Init() As NT_STATUS
' // Initialize device name "\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
' // Fill UNICODE_STRING structure
RtlInitUnicodeString DeviceName, strName
' // Initialize device link for 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
' // Fill UNICODE_STRING structure
RtlInitUnicodeString DeviceLink, strLink
End Function
' // Return passed value
Private Function GetAddr( _
ByVal Value As Long) As Long
GetAddr = Value
End Function
So, the driver must have an entry point DriverEntry, which causes the controller I/O driver is loaded. In the parameters of a pointer to an object-driver and a pointer to a string containing the name of the registry key corresponding to the loadable driver. In the Init procedure, we create two lines, one with the name of the device, the other with reference to the device name. Because we can not use the runtime kernel mode, it is necessary to create a string in the form of a static array, wrapped in a user-defined type, thereby VB6 allocates memory for the array on the stack. If you use a string that will inevitably be caused by one of the functions for runtime and copy assignment line, and we can not allow that. Then we can call IoCreateDevice, which creates a device object. Device object is the recipient of I/O requests and to him we will access when calling CreateFile function from user mode.
Last edited by The trick; Jul 30th, 2016 at 08:13 AM.
Reason: New version/translation to English
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|