드라이버 .c 파일 코드
더보기
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
#include "Source.h"
VOID DriverUnload(
_In_ PDRIVER_OBJECT driverObject
)
{
UNREFERENCED_PARAMETER(driverObject);
UNICODE_STRING SymbolicLinkName;
// 심볼릭링크 삭제
RtlInitUnicodeString(&SymbolicLinkName, SYMBOLIC_NAME_STRING);
IoDeleteSymbolicLink(&SymbolicLinkName);
// DeviceObject 삭제 Delete the user-mode symbolic link and deviceobjct.
IoDeleteDevice(driverObject->DeviceObject);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[DriverUnload()]\n");
}
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT driverObject,
IN PUNICODE_STRING registryPath
)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "\n\n DriverEntry!!\n");
driverObject->DriverUnload = DriverUnload;
//사용하지 않는 파라미터는 에러처리
UNREFERENCED_PARAMETER(registryPath); // registryPath = registryPath 이렇게 해도 됨.
UNREFERENCED_PARAMETER(driverObject);
NTSTATUS status = STATUS_SUCCESS;
//DbgBreakPoint();
PDEVICE_OBJECT DeviceObject = NULL;
UNICODE_STRING ntDeviceName;
UNICODE_STRING SymbolicLinkName;
GF__DEVICE_EXTENSION *pDE = NULL;
// Opt-in to using non-executable pool memory on Windows 8 and later.
// https://msdn.microsoft.com/en-us/library/windows/hardware/hh920402(v=vs.85).aspx
/*ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[20221026] ==>ExInitializeDriverRuntime\n");*/
// Set up dispatch entry points for the driver.
driverObject->MajorFunction[IRP_MJ_CREATE] = MyCreateDispatch;
driverObject->MajorFunction[IRP_MJ_CLOSE] = MyCloseDispatch;
driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDeviceIoControlDispatch; // IOCTL 명령어를 받을 수 있도록 합니다
// DeviceObject 생성
RtlInitUnicodeString(&ntDeviceName, NTDEVICE_NAME_STRING);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[20221026] ==>CreateDeviceObject [%ls]\n", ntDeviceName.Buffer);
status = IoCreateDevice(
driverObject, // DriverObject
sizeof(GF__DEVICE_EXTENSION), // DeviceExtensionSize
&ntDeviceName, // DeviceName
FILE_DEVICE_UNKNOWN, // DeviceType
FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
FALSE, // Not Exclusive
&DeviceObject // DeviceObject
);
if (!NT_SUCCESS(status)) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "\tIoCreateDevice returned 0x%x\n", status);
return(status);
}
pDE = (GF__DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
KeInitializeSpinLock(&pDE->SpinLock);
// 심볼릭생성 Create a symbolic link for userapp to interact with the driver.
RtlInitUnicodeString(&SymbolicLinkName, SYMBOLIC_NAME_STRING); // L"\\DosDevices\\MYSAMPLE"
status = IoCreateSymbolicLink(&SymbolicLinkName, &ntDeviceName);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[20221026] ==>Create a symbolic link [%ls]\n", SymbolicLinkName.Buffer);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(DeviceObject);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "\tIoCreateSymbolicLink returned 0x%x\n", status);
return(status);
}
if (!NT_SUCCESS(status)) {
DriverUnload(driverObject);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[DriverUnload] DriverUnload - 5 (%d)\n", status);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[DriverUnload] DriverUnload - 6 (%d)\n", status);
return status;
}
NTSTATUS MyCreateDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
pDevObj = pDevObj;
pIrp = pIrp;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, 0); // 0 -> IO_NO_INCREMENT
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[20221026] MyCreateDispatch!!\n");
return STATUS_SUCCESS;
}
NTSTATUS MyCloseDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
GF__DEVICE_EXTENSION *pDE = NULL;
KIRQL OldIrql;
pDE = (GF__DEVICE_EXTENSION *)pDevObj->DeviceExtension;
KeAcquireSpinLock(&pDE->SpinLock, &OldIrql);
// 타이머가 구동중이라면 타이머를 취소합니다
if (pDE->bIsTimerOn == TRUE)
{
KeCancelTimer(&pDE->Timer);
pDE->bIsTimerOn = FALSE;
}
// 사용중이던 공유이벤트가 있다면 반납합니다
if (pDE->pSharedEventObject)
{
ObDereferenceObject(pDE->pSharedEventObject); // 참조수를 감소합니다
pDE->pSharedEventObject = NULL;
}
KeReleaseSpinLock(&pDE->SpinLock, OldIrql);
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, 0); // 0 -> IO_NO_INCREMENT
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[20221026] MyCloseDispatch!!\n");
return STATUS_SUCCESS;
}
VOID MyTimerDpcRoutine(
struct _KDPC *Dpc,
PVOID DeferredContext, // DEVICE_EXTENSION 주소가 전달됩니다
PVOID SystemArgument1,
PVOID SystemArgument2
)
{
GF__DEVICE_EXTENSION *pDE = DeferredContext;
KIRQL OldIrql;
KEVENT *pkEvent = NULL;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2); // 사용하지 않는 파라미터에 대한 컴파일오류방지
KeAcquireSpinLock(&pDE->SpinLock, &OldIrql); // 동기화문제방지를 위해 스핀락을 획득합니다
pkEvent = pDE->pSharedEventObject;
pDE->pSharedEventObject = NULL;
KeReleaseSpinLock(&pDE->SpinLock, OldIrql); // 스핀락은 가능하면 빨리 반납합니다
if (pkEvent)
{ // 공유이벤트가 준비되어 있는지 확인합니다
KeSetEvent(pkEvent, 0, FALSE); // 이벤트를 시그널합니다
ObDereferenceObject(pkEvent); // 커널오브젝트의 참조수를 감소합니다
}
}
// Win32 API DeviceIoControl()함수와 연결됩니다
NTSTATUS MyDeviceIoControlDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "\n[20221026][%s]\n", "MyDeviceIoControlDispatch()");
PIO_STACK_LOCATION pStack = NULL;
GF__DEVICE_EXTENSION *pDE = NULL;
KIRQL OldIrql;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
pDE = (GF__DEVICE_EXTENSION *)pDevObj->DeviceExtension;
pStack = IoGetCurrentIrpStackLocation(pIrp); // IRP의 파라미터중에 현재 드라이버를 위한 영역을 찾습니다
switch (pStack->Parameters.DeviceIoControl.IoControlCode) // IOCTL 명령어를 확인합니다
{
case IOCTL_SAMPLE_SHARE_EVENT:
{
HANDLE *pUserEventHandle = NULL;
LARGE_INTEGER Time;
pUserEventHandle = (HANDLE *)pIrp->AssociatedIrp.SystemBuffer;
// 응용프로그램이 전달한 이벤트핸들값이 담긴 시스템버퍼를 접근합니다
KeAcquireSpinLock(&pDE->SpinLock, &OldIrql);
// 타이머가 구동중이라면 타이머를 취소합니다
if (pDE->bIsTimerOn == TRUE)
{
KeCancelTimer(&pDE->Timer);
pDE->bIsTimerOn = FALSE;
}
// 사용중이던 공유이벤트가 있다면 반납합니다
if (pDE->pSharedEventObject)
{
ObDereferenceObject(pDE->pSharedEventObject); // 참조수를 감소합니다
pDE->pSharedEventObject = NULL;
}
KeReleaseSpinLock(&pDE->SpinLock, OldIrql); // 가능하면 스핀락은 빨리 풀어줍니다
// 사용자가 전달한 이벤트핸들에 대응되는 커널오브젝트를 참조합니다
Status = ObReferenceObjectByHandle(
*pUserEventHandle, // 이벤트핸들
0,
NULL,
KernelMode,
&pDE->pSharedEventObject, // 참조되는 커널오브젝트가 담길 주소
NULL
);
if (!NT_SUCCESS(Status)) // 커널오브젝트가 참조되지 않으면..
break;
// 타이머와 DPC를 준비합니다
KeInitializeTimer(&pDE->Timer);
KeInitializeDpc(&pDE->Dpc, MyTimerDpcRoutine, pDE);
Time.QuadPart = -1 * 10 * 3000000; // 3초를 설정합니다
KeSetTimer(&pDE->Timer, Time, &pDE->Dpc); // 3초후에 이벤트를 시그널합니다
pDE->bIsTimerOn = TRUE;
Status = STATUS_SUCCESS;
break;
}
}
pIrp->IoStatus.Status = Status;
IoCompleteRequest(pIrp, 0); // 0 -> IO_NO_INCREMENT
return Status;
}
|
cs |
드라이버 .h 파일 코드
더보기
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
|
#pragma once
#include <ntifs.h>
#include <ntddk.h>
#include <wdm.h>
#define NTDEVICE_NAME_STRING L"\\Device\\GF_sys_driver"
#define SYMBOLIC_NAME_STRING L"\\DosDevices\\MY_GF_sys_driver"
// 새로운 IOCTL 명령어를 정의합니다
#define IOCTL_SAMPLE_SHARE_EVENT CTL_CODE( FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS )
// -----
// 0x800 부터 0xFFF 까지 정의가능합니다
typedef struct
{
KSPIN_LOCK SpinLock;
BOOLEAN bIsTimerOn;
KTIMER Timer;
KDPC Dpc;
KEVENT *pSharedEventObject;
}GF__DEVICE_EXTENSION;
NTSTATUS MyCreateDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS MyCloseDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS MyDeviceIoControlDispatch(PDEVICE_OBJECT pDevObj, PIRP pIrp);
|
cs |
드라이버와 통신하기 위한 실행파일
더보기
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
|
#include <iostream>
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
// 타이머 버전!!!!!
//
// 새로운 IOCTL 명령어를 정의합니다
#define IOCTL_GF_SHARE_EVENT CTL_CODE( FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS )
// -----
// 0x800 부터 0xFFF 까지 정의가능합니다
int main()
{
printf("START!!\n");
HANDLE handle = (HANDLE)-1;
BOOL bRet = FALSE;
DWORD dwRet = 0;
HANDLE hEvent;
handle = CreateFile(L"\\\\.\\MY_GF_sys_driver",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (handle == (HANDLE)INVALID_HANDLE_VALUE)
return 1;
// 이벤트핸들을 생성합니다
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// 이벤트핸들값을 드라이버에게 전달하기 위해서 핸들을 담은 버퍼의 주소를 InputBuffer로 사용.
if (hEvent)
{
bRet = DeviceIoControl(
handle,
IOCTL_GF_SHARE_EVENT,
&hEvent,
sizeof(HANDLE),
NULL,
0,
&dwRet,
NULL
);
if (!bRet)
printf("DeviceIOControl Fail!! (0x%x)\n", GetLastError());
__int64 start_tick, end_tick; // 시간 체크를 위한 변수
start_tick = GetTickCount64();
// 드라이버측에서 해당하는 이벤트를 시그널하는것을 기다립니다
dwRet = WaitForSingleObject(hEvent, INFINITE);
if (dwRet == WAIT_OBJECT_0)
printf("Event Signalled!!!\n");
end_tick = GetTickCount64();
printf("경과시간: %lld \n", end_tick - start_tick);
// 아무키나 받을 때 까지 대기.
_getch();
// 사용이 끝난 이벤트핸들을 반납합니다
CloseHandle(hEvent);
}
CloseHandle(handle);
return 0;
}
|
cs |
결과 화면
'Windows Driver > Kernel & Driver 개발' 카테고리의 다른 글
7. 드라이버와 App간 통신 (문자열 주고 받기_코드) (0) | 2022.11.23 |
---|---|
7. 드라이버와 App간 통신 (문자열 주고 받기_이론) (0) | 2022.11.04 |
5. 특정 프로그램 실행 제어 (0) | 2022.10.03 |
4. 프로세스 강제 종료 막기 (1) | 2022.09.30 |
3. windbg를 이용한 드라이버 디버깅 (0) | 2022.09.21 |