驅動程式 - Windows Driver Model (WDM) - 使用範例 - Assembly (MASM32) - Use Thread



參考資訊:
https://wasm.in/
http://four-f.narod.ru/
https://github.com/steward-fu/ddk
https://www.tutorialspoint.com/user-level-threads-and-kernel-level-threads
https://mropengate.blogspot.com/2015/01/operating-system-ch4-multithread.html

main.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
.386p
.model flat, stdcall
option casemap:none
     
include c:\masm32\include\w2k\ntstatus.inc
include c:\masm32\include\w2k\ntddk.inc
include c:\masm32\include\w2k\ntoskrnl.inc
include c:\masm32\include\w2k\ntddkbd.inc
include c:\masm32\Macros\Strings.mac
 
includelib c:\masm32\lib\wxp\i386\ntoskrnl.lib
  
public DriverEntry
  
MyDeviceExtension struct
    bExit DWORD ?
    pThread PVOID ?
    pNextDev PDEVICE_OBJECT ?
MyDeviceExtension ends
  
IOCTL_START equ CTL_CODE(FILE_DEVICE_UNKNOWN, 800h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_STOP  equ CTL_CODE(FILE_DEVICE_UNKNOWN, 801h, METHOD_BUFFERED, FILE_ANY_ACCESS)
  
.const
MSG_START   byte "IOCTL_START",0
MSG_STOP    byte "IOCTL_STOP",0
  
.code
MyThread proc pParam : DWORD
    local pStr : DWORD
    local pDevExt : DWORD
    local stTime : LARGE_INTEGER
      
    or stTime.HighPart, -1
    mov stTime.LowPart, -10000000
  
    invoke IoGetCurrentProcess
    add eax, 174h
    mov pStr, eax
    invoke DbgPrint, $CTA0("Current process: %s"), pStr
  
    mov eax, pParam
    mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
    push eax
    pop pDevExt
    mov eax, (MyDeviceExtension ptr [eax]).bExit
    .while(eax != TRUE)
        invoke KeDelayExecutionThread, KernelMode, FALSE, addr stTime
        invoke DbgPrint, $CTA0("Sleep 1s")
        mov eax, pDevExt
        mov eax, (MyDeviceExtension ptr [eax]).bExit
    .endw
    invoke DbgPrint, $CTA0("Exit MyThread")
    invoke PsTerminateSystemThread, STATUS_SUCCESS
    ret
MyThread endp
  
IrpOpenClose proc pMyDevice : PDEVICE_OBJECT, pIrp : PIRP
    IoGetCurrentIrpStackLocation pIrp
    movzx eax, (IO_STACK_LOCATION ptr [eax]).MajorFunction
 
    .if eax == IRP_MJ_CREATE
        invoke DbgPrint, $CTA0("IRP_MJ_CREATE")
    .elseif eax == IRP_MJ_CLOSE
        invoke DbgPrint, $CTA0("IRP_MJ_CLOSE")
    .endif
  
    mov eax, pIrp
    and (_IRP ptr [eax]).IoStatus.Information, 0
    mov (_IRP ptr [eax]).IoStatus.Status, STATUS_SUCCESS
    fastcall IofCompleteRequest, pIrp, IO_NO_INCREMENT
    mov eax, STATUS_SUCCESS
    ret
IrpOpenClose endp
  
IrpIOCTL proc uses ebx pMyDevice : PDEVICE_OBJECT, pIrp : PIRP
    local pBuf : DWORD
    local dwLen : DWORD
    local pDevExt : ptr
    local hThread : DWORD
    local pThread : PVOID
  
    and dwLen, 0
    mov eax, pMyDevice
    push (DEVICE_OBJECT ptr [eax]).DeviceExtension
    pop pDevExt
  
    IoGetCurrentIrpStackLocation pIrp
    mov eax, (IO_STACK_LOCATION ptr [eax]).Parameters.DeviceIoControl.IoControlCode
    .if eax == IOCTL_START
        invoke DbgPrint, offset MSG_START
  
        mov ebx, pDevExt
        and (MyDeviceExtension ptr [ebx]).bExit, 0
  
        ; User Thread
        invoke PsCreateSystemThread, addr hThread, THREAD_ALL_ACCESS, NULL, -1, NULL, offset MyThread, pMyDevice
          
        ; System Thread
        ;invoke PsCreateSystemThread, addr hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, offset MyThread, pMyDevice
          
        .if eax == STATUS_SUCCESS
            mov ebx, pDevExt
            invoke ObReferenceObjectByHandle, hThread, THREAD_ALL_ACCESS, NULL, KernelMode, addr (MyDeviceExtension ptr [ebx]).pThread, NULL
            invoke ZwClose, hThread
        .endif
  
    .elseif eax == IOCTL_STOP
        invoke DbgPrint, offset MSG_STOP
        mov ebx, pDevExt
        mov (MyDeviceExtension ptr [ebx]).bExit, TRUE
        push (MyDeviceExtension ptr [ebx]).pThread
        pop pThread
        mov eax, pThread
        .if eax != NULL
            invoke KeWaitForSingleObject, pThread, Executive, KernelMode, FALSE, NULL
            invoke ObDereferenceObject, pThread
        .endif
    .endif
  
    mov eax, pIrp
    mov (_IRP ptr [eax]).IoStatus.Status, STATUS_SUCCESS
    push dwLen
    pop (_IRP ptr [eax]).IoStatus.Information
    fastcall IofCompleteRequest, pIrp, IO_NO_INCREMENT
    mov eax, STATUS_SUCCESS
    ret
IrpIOCTL endp
  
IrpPnp proc pMyDevice : PDEVICE_OBJECT, pIrp : PIRP
    local pDevExt : ptr
    local szSymName : UNICODE_STRING
  
    mov eax, pMyDevice
    push (DEVICE_OBJECT ptr [eax]).DeviceExtension
    pop pDevExt
         
    IoGetCurrentIrpStackLocation pIrp
    movzx eax, (IO_STACK_LOCATION ptr [eax]).MinorFunction
    .if eax == IRP_MN_START_DEVICE
        mov eax, pIrp
        mov (_IRP ptr [eax]).IoStatus.Status, STATUS_SUCCESS
    .elseif eax == IRP_MN_REMOVE_DEVICE
        invoke RtlInitUnicodeString, addr szSymName, $CTW0("\\DosDevices\\MyDriver")
        invoke IoDeleteSymbolicLink, addr szSymName        
        mov eax, pIrp
        mov (_IRP ptr [eax]).IoStatus.Status, STATUS_SUCCESS
  
        mov eax, pDevExt
        invoke IoDetachDevice, (MyDeviceExtension ptr [eax]).pNextDev
        invoke IoDeleteDevice, pMyDevice
        fastcall IofCompleteRequest, pIrp, IO_NO_INCREMENT
        ret
    .endif
    IoSkipCurrentIrpStackLocation pIrp
  
    mov eax, pDevExt
    invoke IoCallDriver, (MyDeviceExtension ptr [eax]).pNextDev, pIrp
    ret
IrpPnp endp
  
AddDevice proc pMyDriver : PDRIVER_OBJECT, pPhyDevice : PDEVICE_OBJECT
    local pMyDevice : PDEVICE_OBJECT
    local szDevName : UNICODE_STRING
    local szSymName : UNICODE_STRING
  
    invoke RtlInitUnicodeString, addr szDevName, $CTW0("\\Device\\MyDriver")
    invoke RtlInitUnicodeString, addr szSymName, $CTW0("\\DosDevices\\MyDriver")
    invoke IoCreateDevice, pMyDriver, sizeof MyDeviceExtension, addr szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, addr pMyDevice
    .if eax == STATUS_SUCCESS
        invoke IoAttachDeviceToDeviceStack, pMyDevice, pPhyDevice
        .if eax != NULL
            push eax
            mov eax, pMyDevice
            mov eax, (DEVICE_OBJECT ptr [eax]).DeviceExtension
            pop (MyDeviceExtension ptr [eax]).pNextDev
  
            mov eax, pMyDevice
            or (DEVICE_OBJECT ptr [eax]).Flags, DO_BUFFERED_IO
            and (DEVICE_OBJECT ptr [eax]).Flags, not DO_DEVICE_INITIALIZING
            invoke IoCreateSymbolicLink, addr szSymName, addr szDevName
        .endif
    .endif
    ret
AddDevice endp
  
Unload proc pMyDriver : PDRIVER_OBJECT
    ret
Unload endp
  
DriverEntry proc pMyDriver : PDRIVER_OBJECT, pMyRegistry : PUNICODE_STRING
    mov eax, pMyDriver
    mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_PNP            * (sizeof PVOID)], offset IrpPnp
    mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_CREATE         * (sizeof PVOID)], offset IrpOpenClose
    mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_CLOSE          * (sizeof PVOID)], offset IrpOpenClose
    mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_DEVICE_CONTROL * (sizeof PVOID)], offset IrpIOCTL
    mov (DRIVER_OBJECT ptr [eax]).DriverUnload, offset Unload
    mov eax, (DRIVER_OBJECT ptr [eax]).DriverExtension
    mov (DRIVER_EXTENSION ptr [eax]).AddDevice, AddDevice
    mov eax, STATUS_SUCCESS
    ret
DriverEntry endp
end

app.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.386p
.model flat, stdcall
option casemap:none
     
include c:\masm32\include\windows.inc
include c:\masm32\include\masm32.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\msvcrt.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\w2k\ntddkbd.inc
include c:\masm32\Macros\Strings.mac
      
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\masm32.lib
includelib c:\masm32\lib\msvcrt.lib
includelib c:\masm32\lib\kernel32.lib
     
IOCTL_START equ CTL_CODE(FILE_DEVICE_UNKNOWN, 800h, METHOD_BUFFERED, FILE_ANY_ACCESS)
IOCTL_STOP  equ CTL_CODE(FILE_DEVICE_UNKNOWN, 801h, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
.data?
hFile dd ?
dwRet dd ?
     
.code
start:
    invoke CreateFile, $CTA0("\\\\.\\MyDriver"), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
    mov hFile, eax
    invoke DeviceIoControl, hFile, IOCTL_START, NULL, 0, NULL, 0, offset dwRet, NULL
    invoke Sleep, 3000
    invoke DeviceIoControl, hFile, IOCTL_STOP, NULL, 0, NULL, 0, offset dwRet, NULL
    invoke CloseHandle, hFile
    invoke ExitProcess, 0
  
end start
end

完成