?? mouspy.bat
字號:
;@echo off
;goto make
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
; MouSpy - This is an example of a simple legacy mouse filter driver
;
; WARNING: You will fail to attach to USB-mouse stack
;
; We create two device objects. The first one is a control device. It provides
; the interface to our user-mode client. The second device is a filter device.
; It intercepts mouse data being passed from the mouse class driver.
; So, it is an upper filter. The intercepted data is collected in the list.
; Upon timer triggering we signal shared event object to notify our user-mode
; client about there is something interesting for it. The user-mode client
; issues control request and we copy all info into the buffer.
;
; Written by Four-F (four-f@mail.ru)
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.486
.model flat, stdcall
option casemap:none
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; I N C L U D E F I L E S
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
include \masm32\include\w2k\ntstatus.inc
include \masm32\include\w2k\ntddk.inc
include \masm32\include\w2k\ntoskrnl.inc
include \masm32\include\w2k\ntddmou.inc
include \masm32\include\w2k\hal.inc
includelib \masm32\lib\w2k\ntoskrnl.lib
includelib \masm32\lib\w2k\hal.lib
include \masm32\Macros\Strings.mac
include ..\common.inc
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; M A C R O S
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; spin lock macros
LOCK_ACQUIRE MACRO lck:REQ
; Returns old IRQL in al
IF (OPATTR (lck)) AND 00010000y
;; Is a register value
IFDIFI <lck>, <ecx> ;; don't move ecx onto itself
mov ecx, lck
ENDIF
ELSEIF (OPATTR (lck)) AND 01000000y
;; relative to SS
lea ecx, lck
ELSE
mov ecx, offset lck
ENDIF
fastcall KfAcquireSpinLock, ecx
ENDM
LOCK_RELEASE MACRO lck:REQ, NewIrql:REQ
IF (OPATTR (lck)) AND 00010000y
;; Is a register value
IFDIFI <lck>, <ecx> ;; don't move ecx onto itself
mov ecx, lck
ENDIF
ELSEIF (OPATTR (lck)) AND 01000000y
;; relative to SS
lea ecx, lck
ELSE
mov ecx, offset lck
ENDIF
IFDIFI <NewIrql>, <dl> ;; don't move dl onto itself
mov dl, NewIrql
ENDIF
.if dl == DISPATCH_LEVEL
fastcall KefReleaseSpinLockFromDpcLevel, ecx
.else
and edx, 0FFh ;; for shure (KIRQL is BYTE)
fastcall KfReleaseSpinLock, ecx, edx
.endif
ENDM
; mutex macros
MUTEX_INIT MACRO mtx:REQ
IF (OPATTR (mtx)) AND 00010000y
;; Is a register value
invoke KeInitializeMutex, mtx, 0
ELSEIF (OPATTR (mtx)) AND 01000000y
;; relative to SS
invoke KeInitializeMutex, addr mtx, 0
ELSE
invoke KeInitializeMutex, offset mtx, 0
ENDIF
ENDM
MUTEX_ACQUIRE MACRO mtx:REQ
IF (OPATTR (mtx)) AND 00010000y
;; Is a register value
invoke KeWaitForMutexObject, mtx, Executive, KernelMode, FALSE, NULL
ELSEIF (OPATTR (mtx)) AND 01000000y
;; relative to SS
invoke KeWaitForMutexObject, addr mtx, Executive, KernelMode, FALSE, NULL
ELSE
invoke KeWaitForMutexObject, offset mtx, Executive, KernelMode, FALSE, NULL
ENDIF
ENDM
MUTEX_RELEASE MACRO mtx:REQ
IF (OPATTR (mtx)) AND 00010000y
;; Is a register value
invoke KeReleaseMutex, mtx, FALSE
ELSEIF (OPATTR (mtx)) AND 01000000y
;; relative to SS
invoke KeReleaseMutex, addr mtx, FALSE
ELSE
invoke KeReleaseMutex, offset mtx, FALSE
ENDIF
ENDM
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; S T R U C T U R E S
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
MOUSE_DATA_ENTRY STRUCT
ListEntry LIST_ENTRY <> ; For memory blocks tracking.
MouseData MOUSE_DATA <>
MOUSE_DATA_ENTRY ENDS
FiDO_DEVICE_EXTENSION STRUCT
; The top of the stack before this filter was added
pNextLowerDeviceObject PDEVICE_OBJECT ?
; The referenced pointer to file object that represents
; the corresponding device object. This pointer we get
; from IoGetDeviceObjectPointer and must dereference
; while detaching.
pTargetFileObject PFILE_OBJECT ?
FiDO_DEVICE_EXTENSION ENDS
PFiDO_DEVICE_EXTENSION typedef ptr FiDO_DEVICE_EXTENSION
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; R E A D O N L Y D A T A
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.const
CCOUNTED_UNICODE_STRING "\\Device\\MouSpy", g_usControlDeviceName, 4
CCOUNTED_UNICODE_STRING "\\DosDevices\\MouSpy", g_usSymbolicLinkName, 4
CCOUNTED_UNICODE_STRING "\\Device\\PointerClass0", g_usTargetDeviceName, 4
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; U N I N I T I A L I Z E D D A T A
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.data?
g_pDriverObject PDRIVER_OBJECT ?
g_pControlDeviceObject PDEVICE_OBJECT ? ; Control Device Object pointer
g_pFilterDeviceObject PDEVICE_OBJECT ? ; Filter Device Object pointer
g_pEventObject PKEVENT ?
; This spin-lock let us be sure that no one will dereference event object pointer
; while we compare it agaist NULL and then call KeSetEvent in our completion routine
g_EventSpinLock KSPIN_LOCK ? ; locks mouse data list
g_fCDO_Opened BOOL ?
g_fFiDO_Attached BOOL ?
g_fSpy BOOL ?
g_dwPendingRequests DWORD ?
align 4
g_pMouseDataLookaside PNPAGED_LOOKASIDE_LIST ?
align 4
g_MouseDataListHead LIST_ENTRY <> ; accessed under lock
; Holds number of MOUSE_DATA_ENTRYs in list. Should not exceed MAX_MOUSE_DATA_ENTRIES.
g_cMouseDataEntries SDWORD ? ; accessed under lock
; This spin-lock let us be sure that only one thread is working with mouse data at a time
g_MouseDataSpinLock KSPIN_LOCK ?
; This mutex let us be sure no one will try to do some unpredictable things.
; For example: no one can try to attach while we in the middle of the detaching.
align 4
g_mtxCDO_State KMUTEX <>
g_fInvertButtons BOOL ?
g_fInvertMovement BOOL ?
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; C O D E
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.code
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; _ExAllocateFromNPagedLookasideList
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
_ExAllocateFromNPagedLookasideList proc uses esi Lookaside:PNPAGED_LOOKASIDE_LIST
;; Function Description:
;; This function removes (pops) the first entry from the specified
;; nonpaged lookaside list.
;;
;; Arguments:
;; Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
;;
;; Return Value:
;; If an entry is removed from the specified lookaside list, then the
;; address of the entry is returned as the function value. Otherwise,
;; NULL is returned.
mov esi, Lookaside
assume esi:ptr NPAGED_LOOKASIDE_LIST
mov ecx, esi
inc [esi].L.TotalAllocates
lea edx, [esi]._Lock
fastcall ExInterlockedPopEntrySList, ecx, edx
.if eax == NULL
push [esi].L.Tag
inc [esi].L.AllocateMisses
push [esi].L._Size
push [esi].L._Type
call [esi].L.Allocate
.endif
assume esi:nothing
ret
_ExAllocateFromNPagedLookasideList endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; _ExFreeToNPagedLookasideList
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
_ExFreeToNPagedLookasideList proc Lookaside:PNPAGED_LOOKASIDE_LIST, Entry:PVOID
;; Function Description:
;; This function inserts (pushes) the specified entry into the specified
;; nonpaged lookaside list.
;;
;; Arguments:
;; Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
;; Entry - Supples a pointer to the entry that is inserted in the lookaside list.
;;
;; Return Value:
;; None.
mov ecx, Lookaside
assume ecx:ptr NPAGED_LOOKASIDE_LIST
inc [ecx].L.TotalFrees
mov ax, [ecx].L.ListHead.Depth
.if ax >= [ecx].L.Depth
push Entry
inc [ecx].L.FreeMisses
call [ecx].L.Free
.else
mov edx, Entry
lea eax, [ecx]._Lock
fastcall ExInterlockedPushEntrySList, ecx, edx, eax
.endif
assume ecx:nothing
ret
_ExFreeToNPagedLookasideList endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; AddEntry
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
AddEntry proc uses ebx pMouseData:PMOUSE_DATA
; We have to access g_cMouseDataEntries and g_MouseDataListHead
; under lock protection. Since mouse movement occur relatively rare
; we simply protect whole code. So, this proc may be optimized a little.
LOCK_ACQUIRE g_MouseDataSpinLock
mov bl, al ; old IRQL
.if g_cMouseDataEntries < MAX_MOUSE_DATA_ENTRIES
; Allocate new entry from lookaside list
invoke _ExAllocateFromNPagedLookasideList, g_pMouseDataLookaside
.if eax != NULL
mov edx, eax
assume edx:ptr MOUSE_DATA_ENTRY
mov ecx, pMouseData
assume ecx:ptr MOUSE_DATA
mov eax, [ecx].LastX
mov [edx].MouseData.LastX, eax
mov eax, [ecx].LastY
mov [edx].MouseData.LastY, eax
mov eax, [ecx].Buttons
mov [edx].MouseData.Buttons, eax
assume ecx:nothing
; Add to head
lea ecx, [edx].ListEntry
InsertHeadList addr g_MouseDataListHead, ecx
assume edx:nothing
inc g_cMouseDataEntries
.endif
.endif
LOCK_RELEASE g_MouseDataSpinLock, bl
ret
AddEntry endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; RemoveEntry
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
RemoveEntry proc uses ebx pBuffer:PVOID
local cbCopied:DWORD
and cbCopied, 0
; We have to access g_cMouseDataEntries and g_MouseDataListHead
; under lock protection. Since mouse movements occur relatively rare
; we simply protect whole code. So, this proc may be optimized a little.
LOCK_ACQUIRE g_MouseDataSpinLock
mov bl, al ; old IRQL
IsListEmpty addr g_MouseDataListHead
.if eax != TRUE ; Is there something to remove?
; Remove from tail
RemoveTailList addr g_MouseDataListHead
mov edx, eax ; edx -> MOUSE_DATA_ENTRY.ListEntry
sub edx, MOUSE_DATA_ENTRY.ListEntry ; edx -> MOUSE_DATA_ENTRY
assume edx:ptr MOUSE_DATA_ENTRY
mov ecx, pBuffer
assume ecx:ptr MOUSE_DATA
mov eax, [edx].MouseData.LastX
mov [ecx].LastX, eax
mov eax, [edx].MouseData.LastY
mov [ecx].LastY, eax
mov eax, [edx].MouseData.Buttons
mov [ecx].Buttons, eax
mov cbCopied, sizeof MOUSE_DATA
assume ecx:nothing
assume edx:nothing
; Put a block back onto lookaside list
invoke _ExFreeToNPagedLookasideList, g_pMouseDataLookaside, edx
dec g_cMouseDataEntries
.endif
LOCK_RELEASE g_MouseDataSpinLock, bl
mov eax, cbCopied
ret
RemoveEntry endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; MouseAttach
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
MouseAttach proc
local status:NTSTATUS
local pTargetDeviceObject:PDEVICE_OBJECT
local pTargetFileObject:PFILE_OBJECT
invoke DbgPrint, $CTA0("MouSpy: Entering MouseAttach\n")
mov status, STATUS_UNSUCCESSFUL
.if ( g_pFilterDeviceObject != NULL )
; Filter device object exist and should be attached
mov status, STATUS_SUCCESS
.else
; Let's attach to mouse device stack
;
; Create unnamed device because filter device objects should never be named.
; We are going to attach it to existing mouse device stack. So no one may
; directly open filter device by name.
mov eax, g_pControlDeviceObject
mov ecx, (DEVICE_OBJECT PTR [eax]).DriverObject
invoke IoCreateDevice, ecx, sizeof FiDO_DEVICE_EXTENSION, NULL, \
FILE_DEVICE_UNKNOWN, 0, FALSE, addr g_pFilterDeviceObject
.if eax == STATUS_SUCCESS
; Supply a name for any device object in the stack we are about to attach to.
; IoGetDeviceObjectPointer returns the pointer to upper most device object in the stack.
invoke IoGetDeviceObjectPointer, addr g_usTargetDeviceName, FILE_READ_DATA, \
addr pTargetFileObject, addr pTargetDeviceObject
.if eax == STATUS_SUCCESS
; Here we have two pointers: pointer to the topmost device in the mouse stack
; and pointer to the corresponding file object. IoGetDeviceObjectPointer
; references file object but not the device object.
;
; We are just one line from attaching to our target. We must prevent
; our driver from unloading while it intercepts mouse IRPs.
; We could use RemoveLock, but the easiest solution is to remove pointer
; 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -