⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbdspy.bat

📁 这是asm驱动的开发包
💻 BAT
📖 第 1 页 / 共 3 页
字号:
				; to DriverUnload routine from driver object. OK, let's do it.

				mov eax, g_pDriverObject
				and (DRIVER_OBJECT PTR [eax]).DriverUnload, NULL
			
				; Now our driver is not unloadable

				invoke IoAttachDeviceToDeviceStack, g_pFilterDeviceObject, pTargetDeviceObject
				.if eax != NULL

					mov edx, eax

					; Fill filter device object extension

					mov ecx, g_pFilterDeviceObject
					mov eax, (DEVICE_OBJECT ptr [ecx]).DeviceExtension
					assume eax:ptr FiDO_DEVICE_EXTENSION
					mov [eax].pNextLowerDeviceObject, edx
					push pTargetFileObject
					pop [eax].pTargetFileObject
					assume eax:nothing

					; We need to copy DeviceType and Characteristics from the target device object
					; underneath us to our filter device object.  We also need to copy DO_DIRECT_IO,
					; DO_BUFFERED_IO, and DO_POWER_PAGABLE flags.  This guarantees that the filter
					; device object looks the same as the target device object.

					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

					; IoCreateDevice sets the DO_DEVICE_INITIALIZING flag in the device object.
					; While this flag is set, the I/O Manager will refuse to attach other device
					; objects to us or to open a handle to our device.  So we have to clear
					; this flag because now we are ready to filter.
					;
					; Note: It is not necessary to clear the DO_DEVICE_INITIALIZING flag on device
					; objects that are created in DriverEntry, because this is done automatically
					; by the I/O Manager.

					and [ecx].Flags, not DO_DEVICE_INITIALIZING

					assume edx:nothing
					assume ecx:nothing

					mov status, STATUS_SUCCESS

				.else		; IoAttachDeviceToDeviceStack failed

					; We have failed to attach

					invoke ObDereferenceObject, pTargetFileObject
				
					invoke IoDeleteDevice, g_pFilterDeviceObject
					and g_pFilterDeviceObject, NULL

					; Let the driver to be unloaded
		
					mov eax, g_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		; IoGetDeviceObjectPointer failed

				invoke IoDeleteDevice, g_pFilterDeviceObject
				and g_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

KeyboardAttach endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                      KeyboardDetach                                               
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

KeyboardDetach proc

local status:NTSTATUS
local pTopmostDeviceObject:PDEVICE_OBJECT

	invoke DbgPrint, $CTA0("KbdSpy: Entering KeyboardDetach\n")		

	mov status, STATUS_UNSUCCESSFUL

	.if g_pFilterDeviceObject != NULL

		; Lets see if there is someone above us.
		; Temporary set the DO_DEVICE_INITIALIZING flag in filter device object.
		; So no one can attach while we check the stack.

		mov eax, g_pFilterDeviceObject
		or (DEVICE_OBJECT ptr [eax]).Flags, DO_DEVICE_INITIALIZING

		invoke IoGetAttachedDeviceReference, g_pFilterDeviceObject
		mov pTopmostDeviceObject, eax

		.if eax != g_pFilterDeviceObject

			; Someone sits on the top of us. Do nothing except restoring
			; Flags field in the filter device object

			mov eax, g_pFilterDeviceObject
			and (DEVICE_OBJECT ptr [eax]).Flags, not DO_DEVICE_INITIALIZING
						
			invoke DbgPrint, $CTA0("KbdSpy: Couldn't detach. Someone sits over\n")
			invoke DbgPrint, $CTA0("KbdSpy: Filter device is still attached\n")

		.else			

			mov eax, g_pFilterDeviceObject
			mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
			mov ecx, (FiDO_DEVICE_EXTENSION ptr [eax]).pTargetFileObject

			fastcall ObfDereferenceObject, ecx

			mov eax, g_pFilterDeviceObject
			mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
			mov eax, (FiDO_DEVICE_EXTENSION ptr [eax]).pNextLowerDeviceObject

			invoke IoDetachDevice, eax
			
			mov status, STATUS_SUCCESS

			invoke DbgPrint, $CTA0("KbdSpy: Filter device detached\n")

			; Destroy filter device.

			mov eax, g_pFilterDeviceObject
			and g_pFilterDeviceObject, NULL
			invoke IoDeleteDevice, eax

			; Our driver is still not unloadable because we might have outstanding IRPs

		.endif

		; Dereference the device object pointer returned by IoGetAttachedDeviceReference

		invoke ObDereferenceObject, pTopmostDeviceObject

	.endif

	mov eax, status
	ret

KeyboardDetach endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                  FiDO_DispatchPassThrough                                         
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

FiDO_DispatchPassThrough proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

; The default dispatch routine. Our driver should send down all IRPs it deal not with

   	IoSkipCurrentIrpStackLocation pIrp

	mov eax, pDeviceObject
	mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
	mov eax, (FiDO_DEVICE_EXTENSION ptr [eax]).pNextLowerDeviceObject

	invoke IoCallDriver, eax, pIrp
	ret

FiDO_DispatchPassThrough endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                    CDO_DispatchCreate                                             
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

CDO_DispatchCreate proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

local status:NTSTATUS
local KeyData:KEY_DATA

	invoke DbgPrint, $CTA0("KbdSpy: Entering CDO_DispatchCreate\n")

	; Drain g_KeyDataListHead.  If someone have ran KbdSpy previously
	; but have failed to unload the driver because of not pressing
	; a key as recommended, we have at least one pending IRP.  When
	; someone press a kay this pending IRP is completed and our
	; completion routine will add one entry into g_KeyDataListHead.
	; So if it's not a first time we are being created we may have
	; some entr(ies)y in g_KeyDataListHead from previous sessions.
	; So lets throw them away.

	.while TRUE

		invoke RemoveEntry, addr KeyData
		.break .if eax == 0

	.endw

	MUTEX_ACQUIRE g_mtxCDO_State

	.if g_fCDO_Opened

		; Only one client at a time is allowed

		mov status, STATUS_DEVICE_BUSY

	.else

		; No one else may open control device
	
		mov g_fCDO_Opened, TRUE
		
		mov status, STATUS_SUCCESS

	.endif

	MUTEX_RELEASE g_mtxCDO_State

	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
	ret

CDO_DispatchCreate endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                    CDO_DispatchClose                                              
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

CDO_DispatchClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

	invoke DbgPrint, $CTA0("KbdSpy: Entering CDO_DispatchClose\n")

	; Do not set completion routine any more
	
	and g_fSpy, FALSE

	MUTEX_ACQUIRE g_mtxCDO_State
				
	.if ( g_pFilterDeviceObject == NULL )

		.if g_dwPendingRequests == 0

			; If we have datached from the keyboard stack, and there is
			; no outstanding IRPs it's safe to unload.

			mov eax, g_pDriverObject
			mov (DRIVER_OBJECT PTR [eax]).DriverUnload, offset DriverUnload

		.endif

	.endif

	; Someone else may open control device

	and g_fCDO_Opened, FALSE	

	MUTEX_RELEASE g_mtxCDO_State

	mov eax, STATUS_SUCCESS
		
	mov ecx, pIrp
	and (_IRP PTR [ecx]).IoStatus.Information, 0
	mov (_IRP PTR [ecx]).IoStatus.Status, eax

	push eax

	fastcall IofCompleteRequest, ecx, IO_NO_INCREMENT

	pop eax
	ret

CDO_DispatchClose endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                      FillKeyData                                                  
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

FillKeyData proc uses edi ebx pBuffer:PVOID, cbBuffer:DWORD

local KeyData:KEY_DATA
local cbReturned:DWORD

	and cbReturned, 0

	; Lets see how many KEY_DATAs will fit into passed in buffer

	mov eax, cbBuffer
	mov ecx, sizeof KEY_DATA
	xor edx, edx
	div ecx
	mov ebx, eax

	mov edi, pBuffer

	.while ebx

		invoke RemoveEntry, edi
		
		.break .if eax == 0

		add cbReturned,  eax

		dec ebx
		add edi, sizeof KEY_DATA

	.endw

	mov eax, cbReturned
	ret

FillKeyData endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                CDO_DispatchDeviceControl                                          
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

CDO_DispatchDeviceControl proc uses esi edi ebx pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

local status:NTSTATUS
local pEventObject:PKEVENT
local liDelayTime:LARGE_INTEGER
local KeyData:KEY_DATA

	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].Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_ATTACH
		.if [edi].Parameters.DeviceIoControl.InputBufferLength == sizeof HANDLE

			MUTEX_ACQUIRE g_mtxCDO_State

			; The user-mode client wants us attach to the keyboard device stack

			mov edx, [esi].AssociatedIrp.SystemBuffer
			mov edx, [edx]			; event handle from user-mode

			mov ecx, ExEventObjectType
			mov ecx, [ecx]
			mov ecx, [ecx]			; PTR OBJECT_TYPE
	
			invoke ObReferenceObjectByHandle, edx, EVENT_MODIFY_STATE, ecx, \
										UserMode, addr pEventObject, NULL
			.if eax == STATUS_SUCCESS

				; If passed event handle is valid, attach to keyboard
					
				.if !g_fFiDO_Attached

					invoke KeyboardAttach
					mov [esi].IoStatus.Status, eax

					.if eax == STATUS_SUCCESS

						mov eax, pEventObject
						mov g_pEventObject, eax			; No need to lock

						mov g_fFiDO_Attached, TRUE
						mov g_fSpy, TRUE				; Set completion routine.
		
					.else
						; Failed to attach
						invoke ObDereferenceObject, pEventObject
					.endif

				.else
					; We was attached

					LOCK_ACQUIRE g_EventSpinLock
					mov bl, al			; old IRQL

					mov eax, g_pEventObject
					.if eax != NULL
						and g_pEventObject, NULL
						invoke ObDereferenceObject, eax
					.endif

					mov eax, pEventObject
					mov g_pEventObject, eax
					
					LOCK_RELEASE g_EventSpinLock, bl

					mov g_fSpy, TRUE				; Set completion routine.
		
					mov [esi].IoStatus.Status, STATUS_SUCCESS
				.endif

			.else
				mov [esi].IoStatus.Status, STATUS_INVALID_PARAMETER
			.endif

			MUTEX_RELEASE g_mtxCDO_State
	
		.else
			mov [esi].IoStatus.Status, STATUS_INFO_LENGTH_MISMATCH
		.endif

	.elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_DETACH

		MUTEX_ACQUIRE g_mtxCDO_State
	
		; The user-mode client wants us to detach from the keyboard device stack

		.if g_fFiDO_Attached

			; Do not set completion routine any more no matter will we detach or not
	
			and g_fSpy, FALSE
	
			invoke KeyboardDetach
			mov [esi].IoStatus.Status, eax

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -