?? mouspy.bat
字號:
.elseif [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_INVERT_MOVEMENT
.if [edi].Parameters.DeviceIoControl.InputBufferLength == sizeof BOOL
mov eax, [esi].AssociatedIrp.SystemBuffer
mov eax, [eax]
mov g_fInvertMovement, eax
and [esi].IoStatus.Information, 0
mov [esi].IoStatus.Status, STATUS_SUCCESS
.else
mov [esi].IoStatus.Status, STATUS_INFO_LENGTH_MISMATCH
.endif
.else
mov [esi].IoStatus.Status, STATUS_INVALID_DEVICE_REQUEST
.endif
mov eax, [esi].IoStatus.Status
mov status, eax
assume esi:nothing
assume edi:nothing
fastcall IofCompleteRequest, esi, IO_NO_INCREMENT
mov eax, status
ret
CDO_DispatchDeviceControl endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; DriverUnload
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
DriverUnload proc pDriverObject:PDRIVER_OBJECT
local MouseData:MOUSE_DATA
invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName
; Empty and destroy list
.while TRUE
invoke RemoveEntry, addr MouseData
.break .if eax == 0
.endw
invoke ExDeleteNPagedLookasideList, g_pMouseDataLookaside
invoke ExFreePool, g_pMouseDataLookaside
mov eax, pDriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
ret
DriverUnload endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; ReadComplete
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ReadComplete proc uses esi edi ebx pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP, pContext:PVOID
local MouseData:MOUSE_DATA
local cEntriesLogged:DWORD
; This routine is to be called when the IRP is completed.
; It is running at IRQL <= DISPATCH_LEVEL and in an arbitrary thread context.
mov esi, pIrp
assume esi:ptr _IRP
; Probably better to use NT_SUCCESS-like behaviour, but it works anyway
.if [esi].IoStatus.Status == STATUS_SUCCESS
; At least one MOUSE_INPUT_DATA structure was transferred.
; The AssociatedIrp.SystemBuffer member points to the output buffer
; that is allocated by the Win32 subsystem to output the requested
; number of MOUSE_INPUT_DATA structures.
mov edi, [esi].AssociatedIrp.SystemBuffer
assume edi:ptr MOUSE_INPUT_DATA
; The Information member specifies the number of bytes
; that are transferred to the Win32 subsystem output buffer.
mov ebx, [esi].IoStatus.Information
and cEntriesLogged, 0
.while sdword ptr ebx >= sizeof MOUSE_INPUT_DATA
mov eax, [edi].LastX
mov MouseData.LastX, eax
mov eax, [edi].LastY
mov MouseData.LastY, eax
mov eax, [edi].Buttons
mov MouseData.Buttons, eax
invoke AddEntry, addr MouseData
inc cEntriesLogged
; Now lets have fun
.if g_fInvertButtons
.if [edi].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN
and [edi].ButtonFlags, not MOUSE_LEFT_BUTTON_DOWN
or [edi].ButtonFlags, MOUSE_RIGHT_BUTTON_DOWN
.elseif [edi].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN
and [edi].ButtonFlags, not MOUSE_RIGHT_BUTTON_DOWN
or [edi].ButtonFlags, MOUSE_LEFT_BUTTON_DOWN
.endif
.if [edi].ButtonFlags & MOUSE_LEFT_BUTTON_UP
and [edi].ButtonFlags, not MOUSE_LEFT_BUTTON_UP
or [edi].ButtonFlags, MOUSE_RIGHT_BUTTON_UP
.elseif [edi].ButtonFlags & MOUSE_RIGHT_BUTTON_UP
and [edi].ButtonFlags, not MOUSE_RIGHT_BUTTON_UP
or [edi].ButtonFlags, MOUSE_LEFT_BUTTON_UP
.endif
.endif
.if g_fInvertMovement
movzx eax, [edi].Flags
and eax, MOUSE_MOVE_RELATIVE
.if eax == MOUSE_MOVE_RELATIVE
; Only for relative movement
.if [edi].LastX != 0
xor eax, eax
sub eax, [edi].LastX
mov [edi].LastX, eax
.endif
.if [edi].LastY != 0
xor eax, eax
sub eax, [edi].LastY
mov [edi].LastY, eax
.endif
.endif
.endif
add edi, sizeof MOUSE_INPUT_DATA
sub ebx, sizeof MOUSE_INPUT_DATA
.endw
assume edi:nothing
; Notify user-mode client.
.if ( cEntriesLogged != 0 )
LOCK_ACQUIRE g_EventSpinLock
mov bl, al ; old IRQL
.if ( g_pEventObject != NULL ) ; EventObject may go away
invoke KeSetEvent, g_pEventObject, 0, FALSE
.endif
LOCK_RELEASE g_EventSpinLock, bl
.endif
.endif
; Any driver that returns STATUS_SUCCESS from IoCompletion routine should check the
; IRP->PendingReturned flag in the IoCompletion routine. If the flag is set,
; the IoCompletion routine must call IoMarkIrpPending with the IRP.
.if [esi].PendingReturned
IoMarkIrpPending esi
.endif
assume esi:nothing
lock dec g_dwPendingRequests
mov eax, STATUS_SUCCESS
ret
ReadComplete endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; FiDO_DispatchRead
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
FiDO_DispatchRead proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
; The IRP_MJ_READ request transfers zero or more MOUSE_INPUT_DATA structures
; from Mouclass's internal data queue to the Win32 subsystem buffer.
.if g_fSpy
lock inc g_dwPendingRequests
; We pass the same parameters to lower driver copying our stack location to the next-lower one.
IoCopyCurrentIrpStackLocationToNext pIrp
; To find out how the IRP will be completed we install completion routine.
; It will be called when the next-lower-level driver has completed IRP.
IoSetCompletionRoutine pIrp, ReadComplete, NULL, TRUE, TRUE, TRUE
.else
; No need to know what will happen with IRP. So just pass it down and forget.
; Bacause we do not need to set completion routine use IoSkipCurrentIrpStackLocation
; instead of IoCopyCurrentIrpStackLocationToNext. It's faster.
IoSkipCurrentIrpStackLocation pIrp
.endif
; It's time to send an IRP to next-lower-level driver.
mov eax, pDeviceObject
mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
mov eax, (FiDO_DEVICE_EXTENSION ptr [eax]).pNextLowerDeviceObject
invoke IoCallDriver, eax, pIrp
; We must return exactly the same value IoCallDriver has returned.
ret
FiDO_DispatchRead endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; FiDO_DispatchPower
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
FiDO_DispatchPower proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
invoke PoStartNextPowerIrp, pIrp
IoSkipCurrentIrpStackLocation pIrp
mov eax, pDeviceObject
mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
mov eax, (FiDO_DEVICE_EXTENSION ptr [eax]).pNextLowerDeviceObject
invoke PoCallDriver, eax, pIrp
; We must return exactly the same value PoCallDriver has returned.
ret
FiDO_DispatchPower endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; DriverDispatch
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
DriverDispatch proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
local status:NTSTATUS
local dwMajorFunction:DWORD
IoGetCurrentIrpStackLocation pIrp
movzx eax, (IO_STACK_LOCATION PTR [eax]).MajorFunction
mov dwMajorFunction, eax
mov eax, pDeviceObject
.if eax == g_pFilterDeviceObject
mov eax, dwMajorFunction
.if eax == IRP_MJ_READ
invoke FiDO_DispatchRead, pDeviceObject, pIrp
mov status, eax
.elseif eax == IRP_MJ_POWER
invoke FiDO_DispatchPower, pDeviceObject, pIrp
mov status, eax
.else
invoke FiDO_DispatchPassThrough, pDeviceObject, pIrp
mov status, eax
.endif
.elseif eax == g_pControlDeviceObject
; Request is to our CDO. Let' see what our client want us do
mov eax, dwMajorFunction
.if eax == IRP_MJ_CREATE
invoke CDO_DispatchCreate, pDeviceObject, pIrp
mov status, eax
.elseif eax == IRP_MJ_CLOSE
invoke CDO_DispatchClose, pDeviceObject, pIrp
mov status, eax
.elseif eax == IRP_MJ_DEVICE_CONTROL
invoke CDO_DispatchDeviceControl, pDeviceObject, pIrp
mov status, eax
.else
mov ecx, pIrp
mov (_IRP PTR [ecx]).IoStatus.Status, STATUS_INVALID_DEVICE_REQUEST
and (_IRP PTR [ecx]).IoStatus.Information, 0
fastcall IofCompleteRequest, ecx, IO_NO_INCREMENT
mov status, STATUS_INVALID_DEVICE_REQUEST
.endif
.else
; Strange, we have recieved IRP for the device we do not know about.
; This should never happen. Just complete IRP as invalid.
mov ecx, pIrp
mov (_IRP PTR [ecx]).IoStatus.Status, STATUS_INVALID_DEVICE_REQUEST
and (_IRP PTR [ecx]).IoStatus.Information, 0
fastcall IofCompleteRequest, ecx, IO_NO_INCREMENT
mov status, STATUS_INVALID_DEVICE_REQUEST
.endif
mov eax, status
ret
DriverDispatch endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; D I S C A R D A B L E C O D E
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.code INIT
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; DriverEntry
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
local status:NTSTATUS
mov status, STATUS_DEVICE_CONFIGURATION_ERROR
; Create a Control Device Object (CDO). The purpose of the CDO is to allow
; our user-mode client to communicate with us, even before the filter is attached
; to its target
;
; We store the CDO pointer into g_pControlDeviceObject, a globally defined variable.
; This way we can identify the control device object in dispatch routines by comparing
; the passed in device pointer against our CDO pointer
;
; CDO is exclusive one. It ensures that only one process opens the device at a time.
; DDK stands it is reserved for system use and drivers set this parameter to FALSE.
; Anyway we set it to TRUE and to force single-client logic mantain global variable
; g_fCDOOpened which we will set/reset in CDO_DispatchCreate/CDO_DispatchClose
invoke IoCreateDevice, pDriverObject, 0, addr g_usControlDeviceName, \
FILE_DEVICE_UNKNOWN, 0, TRUE, addr g_pControlDeviceObject
.if eax == STATUS_SUCCESS
;mov eax, g_pControlDeviceObject
;mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
;and (CDO_DEVICE_EXTENSION ptr [eax]).fOpened, 0
invoke IoCreateSymbolicLink, addr g_usSymbolicLinkName, addr g_usControlDeviceName
.if eax == STATUS_SUCCESS
; Allocate memory for lookaside list
invoke ExAllocatePool, NonPagedPool, sizeof NPAGED_LOOKASIDE_LIST
.if eax != NULL
mov g_pMouseDataLookaside, eax
invoke ExInitializeNPagedLookasideList, g_pMouseDataLookaside, \
NULL, NULL, 0, sizeof MOUSE_DATA_ENTRY, 'ypSM', 0
; Use doubly linked list to track memory blocks
; we will allocate/free from/to lookaside list
InitializeListHead addr g_MouseDataListHead
and g_cMouseDataEntries, 0
; Init spin lock guarding common driver routines
invoke KeInitializeSpinLock, addr g_MouseDataSpinLock
; Init spin lock guarding event pointer
invoke KeInitializeSpinLock, addr g_EventSpinLock
; Init CDO state mutex
MUTEX_INIT g_mtxCDO_State
; I know they all are zero by default, but...
and g_fCDO_Opened, FALSE
and g_fFiDO_Attached, FALSE
and g_pFilterDeviceObject, NULL
and g_fSpy, FALSE
and g_dwPendingRequests, 0
and g_fInvertButtons, FALSE
and g_fInvertMovement, FALSE
mov eax, pDriverObject
assume eax:ptr DRIVER_OBJECT
mov ecx, IRP_MJ_MAXIMUM_FUNCTION + 1
.while ecx
dec ecx
mov [eax].MajorFunction[ecx*(sizeof PVOID)], offset DriverDispatch
.endw
mov [eax].DriverUnload, offset DriverUnload
assume eax:nothing
mov eax, pDriverObject
mov g_pDriverObject, eax
mov status, STATUS_SUCCESS
.else ; ExAllocatePool failed
invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName
invoke IoDeleteDevice, g_pControlDeviceObject
.endif
.else ; IoCreateSymbolicLink failed
invoke IoDeleteDevice, g_pControlDeviceObject
.endif
.endif
mov eax, status
ret
DriverEntry endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
end DriverEntry
:make
set drv=MouSpy
if exist ..\%drv%.sys del ..\%drv%.sys
\masm32\bin\ml /nologo /c /coff %drv%.bat
\masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native /ignore:4078 %drv%.obj
del %drv%.obj
move %drv%.sys ..
echo.
pause
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -