源自VC版,一些过滤模拟功能没有弄好,但是不影响在设备管理器中模拟出虚拟键盘,用于单价多用户环境非常方便。
.386
.model flat, stdcall
option casemap:none
include w2k\ntstatus.inc
include w2k\ntddk.inc
include w2k\ntoskrnl.inc
include w2k\ntddkbd.inc
include w2k\hal.inc
includelib d:\masm32\lib\w2k\ntoskrnl.lib
include Strings.mac
includelib hal.lib
IOCTL_TEST equ CTL_CODE(FILE_DEVICE_UNKNOWN, 801h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_SENDKEY equ CTL_CODE(FILE_DEVICE_UNKNOWN, 802h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_INTERNAL_KEYBOARD_CONNECT equ CTL_CODE(FILE_DEVICE_UNKNOWN, 803h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_KEYBOARD_QUERY_ATTRIBUTES equ CTL_CODE(FILE_DEVICE_UNKNOWN, 804h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_KEYBOARD_SET_TYPEMATIC equ CTL_CODE(FILE_DEVICE_UNKNOWN, 805h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_KEYBOARD_SET_INDICATORS equ CTL_CODE(FILE_DEVICE_UNKNOWN, 806h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_KEYBOARD_QUERY_TYPEMATIC equ CTL_CODE(FILE_DEVICE_UNKNOWN, 807h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_KEYBOARD_QUERY_INDICATORS equ CTL_CODE(FILE_DEVICE_UNKNOWN, 808h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION equ CTL_CODE(FILE_DEVICE_UNKNOWN, 809h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_KEYBOARD_INSERT_DATA equ CTL_CODE(FILE_DEVICE_UNKNOWN, 810h, METHOD_BUFFERED, FILE_ANY_ACCESS)
pSeviceCallback typedef proto :PDEVICE_OBJECT,:PKEYBOARD_INPUT_DATA,:PKEYBOARD_INPUT_DATA,:dword
_pSeviceCallback typedef ptr pSeviceCallback
Keys STRUCT
Flags DWORD ?
Press DWORD ?
Code DWORD ?
Keys ENDS
VK_SENDKEY STRUCT
Count DWORD ?
Temp Keys <>
VK_SENDKEY ENDS
PVK_SENDKEY typedef ptr VK_SENDKEY
DEVICE_EXTENSION STRUCT
fdo PDEVICE_OBJECT ?
NextStackDevice PDEVICE_OBJECT ?
DEVICE_EXTENSION ENDS
pDEVICE_EXTENSION typedef ptr DEVICE_EXTENSION
Data STRUCT
Flags DWORD ?
UnitId DWORD ?
MakeCode DWORD ?
Data ENDS
MYKEYBOARD_INPUT_DATA typedef ptr Data
.data
KeyboardClassDO PDEVICE_OBJECT ?
FunctionDevice PDEVICE_OBJECT ?
UnitId dd 0
SeviceCallback _pSeviceCallback ?
.const
CCOUNTED_UNICODE_STRING "
CCOUNTED_UNICODE_STRING "
CCOUNTED_UNICODE_STRING "", TargetDeviceName, 4
.code
.code
SeviceCallback proc DeviceObject:PDEVICE_OBJECT,InputDataStart:PKEYBOARD_INPUT_DATA,InputDataEnd:PKEYBOARD_INPUT_DATA,InputDataConsumed:dword
ret
SeviceCallback endp
DriverEntry proc pDriverObject:PDRIVER_OBJECT,RegistryPath:PUNICODE_STRING
LOCAL deviceNameUnicodeString,deviceLinkUnicodeString:UNICODE_STRING
LOCAL status:NTSTATUS
LOCAL pDeviceObject:PVOID
mov status,STATUS_DEVICE_CONFIGURATION_ERROR
invoke IoCreateDevice, pDriverObject, 0, addr DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, addr pDeviceObject
.if eax == STATUS_SUCCESS
invoke IoCreateSymbolicLink, addr SymbolicLinkName, addr DeviceName
.if eax == STATUS_SUCCESS
mov eax, pDriverObject
assume eax:PTR DRIVER_OBJECT
mov esi,[eax].DriverExtension
assume esi:PTR DRIVER_EXTENSION
;添加设备
mov [esi].AddDevice,offset AddDevice;
;Windows应用程序交互函数
mov [eax].MajorFunction[IRP_MJ_CREATE*(sizeof PVOID)], offset DispatchCreateClose
mov [eax].MajorFunction[IRP_MJ_CLOSE*(sizeof PVOID)], offset DispatchCreateClose
mov [eax].MajorFunction[IRP_MJ_DEVICE_CONTROL*(sizeof PVOID)], offset DispatchControl
mov [eax].MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL*(sizeof PVOID)], offset DispatchInternal
mov [eax].DriverUnload, offset DriverUnload
;即插即用、电源管理、系统控制函数
mov [eax].MajorFunction[IRP_MJ_SYSTEM_CONTROL],offset SystemControl
mov [eax].MajorFunction[IRP_MJ_POWER*(sizeof PVOID)], offset DispatchPower
mov [eax].MajorFunction[IRP_MJ_PNP*(sizeof PVOID)], offset DispatchPnp
assume eax:nothing
assume esi:nothing
mov status, STATUS_SUCCESS
.else
invoke IoDeleteDevice, pDeviceObject
.endif
.endif
mov eax, status
ret
DriverEntry endp
DispatchCreateClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
mov eax, pIrp
assume eax:ptr _IRP
mov [eax].IoStatus.Status, STATUS_SUCCESS
and [eax].IoStatus.Information, 0
assume eax:nothing
fastcall IofCompleteRequest, pIrp, IO_NO_INCREMENT
mov eax, STATUS_SUCCESS
ret
DispatchCreateClose endp
DriverUnload proc pDriverObject:PDRIVER_OBJECT
invoke IoDeleteSymbolicLink, addr SymbolicLinkName
mov eax, pDriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
ret
DriverUnload endp
DispatchPnp proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
LOCAL Status : NTSTATUS
LOCAL MinorFunction:dword
.if FunctionDevice == PDEVICE_OBJECT
mov ecx, pIrp
and (_IRP PTR [ecx]).IoStatus.Information, 0
mov eax, Status
mov (_IRP PTR [ecx]).IoStatus.Status, eax
fastcall IofCompleteRequest, ecx, IO_NO_INCREMENT
mov eax, Status
.endif
mov Status, STATUS_UNSUCCESSFUL
mov esi, pIrp
assume esi:ptr _IRP
mov [esi].IoStatus.Status, STATUS_UNSUCCESSFUL
and [esi].IoStatus.Information, 0
IoGetCurrentIrpStackLocation esi
mov edi, eax
assume edi:ptr IO_STACK_LOCATION
.if [edi].MinorFunction==IRP_MN_REMOVE_DEVICE
.if DEVICE_EXTENSION.NextStackDevice
invoke IoDetachDevice, DEVICE_EXTENSION.NextStackDevice
.endif
mov eax, pDeviceObject
and pDeviceObject, NULL
invoke IoDeleteDevice, pDeviceObject
.endif
mov Status, STATUS_SUCCESS
assume esi:nothing
assume edi:nothing
ret
DispatchPnp endp
DispatchPower proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
invoke PoStartNextPowerIrp, pIrp
IoSkipCurrentIrpStackLocation pIrp
mov eax, pDeviceObject
mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
mov eax, (DEVICE_EXTENSION ptr [eax]).NextStackDevice
invoke PoCallDriver, eax, pIrp
ret
DispatchPower endp
AddDevice proc pDeviceObject:PDEVICE_OBJECT, pDriverObject:PDRIVER_OBJECT
LOCAL Status : NTSTATUS
LOCAL pFilterDeviceObject:PDEVICE_OBJECT
local pTargetDeviceObject:PDEVICE_OBJECT
local pTargetFileObject:PFILE_OBJECT
LOCAL pControlDeviceObject:PDEVICE_OBJECT
local status:NTSTATUS
invoke DbgPrint, $CTA0("KbdSpy: Entering KeyboardAttach\n")
mov status, STATUS_UNSUCCESSFUL
.if ( pFilterDeviceObject != NULL )
mov status, STATUS_SUCCESS
.else
mov eax, pControlDeviceObject
mov ecx, (DEVICE_OBJECT PTR [eax]).DriverObject
invoke IoCreateDevice, ecx, sizeof DEVICE_EXTENSION, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, addr pFilterDeviceObject
.if eax == STATUS_SUCCESS
invoke IoGetDeviceObjectPointer, addr TargetDeviceName, FILE_READ_DATA, addr pTargetFileObject, addr pTargetDeviceObject
.if eax == STATUS_SUCCESS
mov eax, pDriverObject
and (DRIVER_OBJECT PTR [eax]).DriverUnload, NULL
invoke IoAttachDeviceToDeviceStack, pFilterDeviceObject, pTargetDeviceObject
.if eax != NULL
mov edx, eax
mov ecx, pFilterDeviceObject
mov eax, (DEVICE_OBJECT ptr [ecx]).DeviceExtension
assume eax:ptr DEVICE_EXTENSION
mov [eax].NextStackDevice, edx
push pTargetFileObject
pop [eax].NextStackDevice
assume eax:nothing
assume edx:ptr DEVICE_OBJECT
assume ecx:ptr DEVICE_OBJECT
mov eax, [edx].DeviceType
mov [ecx].DeviceType, eax
mov eax, [edx].Flags
and eax, DO_DIRECT_IO + DO_BUFFERED_IO + DO_POWER_PAGABLE
or [ecx].Flags, eax
and [ecx].Flags, not DO_DEVICE_INITIALIZING
assume edx:nothing
assume ecx:nothing
mov status, STATUS_SUCCESS
.else
invoke ObDereferenceObject, pTargetFileObject
invoke IoDeleteDevice, pFilterDeviceObject
and pFilterDeviceObject, NULL
mov eax, pDriverObject
mov (DRIVER_OBJECT PTR [eax]).DriverUnload, offset DriverUnload
invoke DbgPrint, $CTA0("KbdSpy: Couldn't attach to target device\n")
mov status, STATUS_NO_SUCH_DEVICE
.endif
.else
invoke IoDeleteDevice, pFilterDeviceObject
and pFilterDeviceObject, NULL
invoke DbgPrint, $CTA0("KbdSpy: Couldn't get target device object pointer\n")
.endif
.else
invoke DbgPrint, $CTA0("KbdSpy: Couldn't create filter device\n")
.endif
.endif
mov eax, status
ret
AddDevice endp
SystemControl proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
LOCAL Status : NTSTATUS
.if FunctionDevice == DEVICE_EXTENSION.fdo
fastcall IofCompleteRequest, ecx, IO_NO_INCREMENT
.endif
mov eax, Status
ret
SystemControl endp
DispatchInternal proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
LOCAL Status : NTSTATUS
local pEventObject:PKEVENT
local ioControlCode:dword
mov Status,STATUS_SUCCESS
mov esi, pIrp
assume esi : ptr _IRP
IoGetCurrentIrpStackLocation esi
mov edi, eax
assume edi : ptr IO_STACK_LOCATION
mov eax, [edi].Parameters.DeviceIoControl.IoControlCode
mov ioControlCode,eax
.if eax==IOCTL_INTERNAL_KEYBOARD_CONNECT
.elseif eax==IOCTL_KEYBOARD_QUERY_ATTRIBUTES
.elseif eax==IOCTL_KEYBOARD_SET_TYPEMATIC
.elseif eax==IOCTL_KEYBOARD_SET_INDICATORS
.elseif eax==IOCTL_KEYBOARD_QUERY_TYPEMATIC
.elseif eax==IOCTL_KEYBOARD_QUERY_INDICATORS
.elseif eax==IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
.elseif eax==IOCTL_KEYBOARD_INSERT_DATA
.endif
IoSkipCurrentIrpStackLocation pIrp
mov eax, pDeviceObject
mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
mov eax, (DEVICE_EXTENSION ptr [eax]).NextStackDevice
invoke IoCallDriver, eax, pIrp
assume edi:nothing
assume esi:nothing
ret
DispatchInternal endp
DispatchControl proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
local inputBuffer:PVOID
local inputBufferLength:dword
local outputBuffer:PVOID
local outputBufferLength:dword
local ioControlCode:dword
local workItem:dword ;WORK_QUEUE_ITEM
LOCAL Status : NTSTATUS
LOCAL dwBytesReturned
LOCAL IoStatus:dword
LOCAL IoBuffer:dword
LOCAL NumSend:dword
mov Status,STATUS_SUCCESS
mov esi, pIrp
assume esi : ptr _IRP
IoGetCurrentIrpStackLocation esi
mov edi, eax
assume edi : ptr IO_STACK_LOCATION
mov eax,[esi].IoStatus.Status
mov IoStatus,eax
mov eax,[esi].AssociatedIrp.SystemBuffer
mov IoBuffer,eax
mov eax, [edi].Parameters.DeviceIoControl.IoControlCode
mov ioControlCode,eax
mov eax, [esi].AssociatedIrp.SystemBuffer
mov inputBuffer,eax
mov outputBuffer,eax
mov eax,[edi].Parameters.DeviceIoControl.InputBufferLength
mov inputBufferLength,eax
mov eax,[edi].Parameters.DeviceIoControl.OutputBufferLength
mov outputBufferLength,eax
mov Status, STATUS_UNSUCCESSFUL
mov esi, pIrp
assume esi:ptr _IRP
mov [esi].IoStatus.Status, STATUS_UNSUCCESSFUL
and [esi].IoStatus.Information, 0
IoGetCurrentIrpStackLocation esi
mov edi, eax
assume edi:ptr IO_STACK_LOCATION
mov Status, STATUS_INVALID_DEVICE_REQUEST
mov NumSend,0
@loop:
mov esi,VK_SENDKEY.Count
.if ioControlCode == IOCTL_SENDKEY
.if IoBuffer==0 || inputBufferLength < sizeof VK_SENDKEY || esi > 5
mov Status, STATUS_INVALID_PARAMETER
jmp @exit
.endif
xor ecx,ecx
@@:
inc ecx
.if ecx> esi
jmp @f
.endif
mov eax,VK_SENDKEY.Temp.Press
.if eax==0
mov eax,KEYBOARD_INPUT_DATA
mov Data[ecx],eax
.endif
invoke SeviceCallback,KeyboardClassDO,Data, Data[ecx],addr NumSend
mov Status,STATUS_SUCCESS
@@:
.else
mov Status, STATUS_INVALID_DEVICE_REQUEST
.endif
@exit:
mov ecx, pIrp
and (_IRP PTR [ecx]).IoStatus.Information, 0
mov eax, Status
mov (_IRP PTR [ecx]).IoStatus.Status, eax
fastcall IofCompleteRequest, ecx, IO_NO_INCREMENT
mov eax, Status
assume edi:nothing
assume esi:nothing
ret
DispatchControl endp
end DriverEntry