forked from microsoft/Windows-driver-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
elamsample.c
473 lines (361 loc) · 12 KB
/
elamsample.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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//
// Module Name:
//
// elamsample.c
//
// Abstract:
//
// This driver demonstrates how to use the Boot Driver Callback APIs
// IoRegisterBootDriverCallback and IoUnRegisterBootDriverCallback and
// the callback type PBOOT_DRIVER_CALLBACK_FUNCTION.
//
// Environment:
//
// Kernel mode only.
//
#include <elamsample.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#endif // ALLOC_PRAGMA
//
// Trace level to use for kernel debugger DbgPrintEx output.
//
#define ELAMSAMPLE_TRACE_LEVEL DPFLTR_TRACE_LEVEL
//
// Callback handle returned by IoRegisterBootDriverCallback.
//
static PVOID g_IoRegisterBootDriverCallbackHandle = NULL;
//
// Current status update type from the callback.
//
static BDCB_STATUS_UPDATE_TYPE g_CurrentBcdCallbackContextType =
BdCbStatusPrepareForDependencyLoad;
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine is called by the Operating System to initialize the driver.
It creates the device object, fills in the dispatch entry points and
completes the initialization.
Arguments:
DriverObject - Supplies a pointer to the object that represents this device
driver.
RegistryPath - Supplies a pointer to the Services key in the registry.
Return Value:
STATUS_SUCCESS if initialized successfully.
Error status if the driver could not be initialized.
--*/
{
WDF_OBJECT_ATTRIBUTES Attributes;
WDF_DRIVER_CONFIG Config;
WDFDRIVER Driver;
NTSTATUS Status;
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample is being initialized.\r\n");
//
// Initialize a non-PnP driver with the framework.
//
WDF_DRIVER_CONFIG_INIT(&Config, WDF_NO_EVENT_CALLBACK);
Config.DriverInitFlags |= WdfDriverInitNonPnpDriver;
//
// Non-PnP drivers must register an unload routine.
//
Config.EvtDriverUnload = ElamSampleEvtDriverUnload;
//
// Create a framework driver object.
//
WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
Status = WdfDriverCreate(DriverObject,
RegistryPath,
&Attributes,
&Config,
&Driver);
if (!NT_SUCCESS(Status))
{
return Status;
}
//
// Register for the boot driver callback.
//
g_IoRegisterBootDriverCallbackHandle = IoRegisterBootDriverCallback(
ElamSampleBootDriverCallback,
NULL);
if (g_IoRegisterBootDriverCallbackHandle == NULL)
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
VOID
ElamSampleEvtDriverUnload(
_In_ WDFDRIVER Driver
)
/*++
Routine Description:
This routine is called by the I/O subsystem before unloading the driver.
It creates the device object, fills in the dispatch entry points and
completes the initialization.
Arguments:
Driver - Supplies a handle to a framework driver object.
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER(Driver);
if (g_IoRegisterBootDriverCallbackHandle != NULL)
{
IoUnregisterBootDriverCallback(g_IoRegisterBootDriverCallbackHandle);
g_IoRegisterBootDriverCallbackHandle = NULL;
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample is being unloaded.\r\n");
}
VOID
ElamSampleBootDriverCallback(
_In_opt_ PVOID CallbackContext,
_In_ BDCB_CALLBACK_TYPE Classification,
_Inout_ PBDCB_IMAGE_INFORMATION ImageInformation
)
/*++
Routine Description:
This routine is called by the Operating System when boot start drivers are
being initialized.
Arguments:
CallbackContext - Supplies the opaque context specified during callback
registration.
Classification - Supplies the type of the callback, including status update
or image initialized.
ImageInformation - Supplies a pointer to information about the next boot
driver that is about to be initialized.
Return Value:
None.
--*/
{
PBDCB_STATUS_UPDATE_CONTEXT StatusUpdate;
//
// IoRegisterBootDriverCallback was called with a null context. Ensure that
// is passed here.
//
if (CallbackContext != NULL)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample has been passed an unexpected callback context.\r\n");
}
switch (Classification)
{
case BdCbStatusUpdate:
StatusUpdate = (PBDCB_STATUS_UPDATE_CONTEXT)ImageInformation;
ElamSampleProcessStatusUpdate(StatusUpdate->StatusType);
break;
case BdCbInitializeImage:
ElamSampleProcessInitializeImage(ImageInformation);
break;
default:
//
// Do nothing. If new classifications are supported we should just
// ignore them.
//
break;
}
}
VOID
ElamSampleProcessStatusUpdate(
_In_ BDCB_STATUS_UPDATE_TYPE StatusType
)
/*++
Routine Description:
This routine processes the BdCbStatusUpdate callback type.
Arguments:
StatusType - Supplies the type of status that is being reported.
Return Value:
None.
--*/
{
switch (StatusType)
{
case BdCbStatusPrepareForDependencyLoad:
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample reports that Boot Start driver dependencies are being initialized.\r\n\r\n");
break;
case BdCbStatusPrepareForDriverLoad:
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample reports that Boot Start drivers are about to be initialized.\r\n\r\n");
break;
case BdCbStatusPrepareForUnload:
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample reports that all Boot Start drivers have been initialized "
"and that ElamSample is about to be unloaded\r\n\r\n");
break;
default:
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample reports an unknown status type.\r\n\r\n");
break;
}
g_CurrentBcdCallbackContextType = StatusType;
}
VOID
ElamSampleProcessInitializeImage(
_Inout_ PBDCB_IMAGE_INFORMATION ImageInformation
)
/*++
Routine Description:
This routine processes the BdCbInitializeImage callback type.
Arguments:
ImageInformation - Supplies a pointer to information about the next boot
driver that is about to be initialized.
Return Value:
None.
--*/
{
//
// Is this a dependency or a boot start driver?
//
if (g_CurrentBcdCallbackContextType == BdCbStatusPrepareForDependencyLoad)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample reports the following dependency is about to be initialized:\r\n");
}
else if (g_CurrentBcdCallbackContextType == BdCbStatusPrepareForDriverLoad)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample reports the following Boot Start driver is about to be initialized:\r\n");
}
else
{
NT_ASSERT(g_CurrentBcdCallbackContextType == BdCbStatusPrepareForDependencyLoad ||
g_CurrentBcdCallbackContextType == BdCbStatusPrepareForDriverLoad);
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample reports an invalid status type for image initialization:\r\n");
}
//
// Display the image name and any associated registry path.
//
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Image name \"%wZ\"\r\n",
&ImageInformation->ImageName);
if (ImageInformation->RegistryPath.Buffer != NULL)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Registry path \"%wZ\"\r\n",
&ImageInformation->RegistryPath);
}
//
// Did this image fail Code Integrity checks?
//
if ((ImageInformation->ImageFlags & BDCB_IMAGEFLAGS_FAILED_CODE_INTEGRITY) != 0)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: FAILED Code Integrity checks but boot policy allowed it to be loaded.\r\n");
}
//
// Display the image's hash.
//
if (ImageInformation->ImageHash != NULL &&
ImageInformation->ImageHashLength != 0)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Image hash algorithm = 0x%08x.\r\n",
ImageInformation->ImageHashAlgorithm);
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Image hash:");
ElamSamplePrintHex(ImageInformation->ImageHash,
ImageInformation->ImageHashLength);
}
//
// Display who signed the image (if at all).
//
if (ImageInformation->CertificatePublisher.Buffer != NULL)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Image is signed by \"%wZ\".\r\n",
&ImageInformation->CertificatePublisher);
if (ImageInformation->CertificateIssuer.Buffer != NULL)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Certificate issued by \"%wZ\".\r\n",
&ImageInformation->CertificateIssuer);
}
if (ImageInformation->CertificateThumbprint != NULL &&
ImageInformation->CertificateThumbprintLength != 0)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Certificate thumb print algorithm = 0x%08x.\r\n",
ImageInformation->ThumbprintHashAlgorithm);
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Certificate thumb print:");
ElamSamplePrintHex(ImageInformation->CertificateThumbprint,
ImageInformation->CertificateThumbprintLength);
}
}
else
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"ElamSample: Not signed.\r\n");
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, ELAMSAMPLE_TRACE_LEVEL, "\r\n");
//
// Report that we don't know the authenticity of this image.
//
ImageInformation->Classification = BdCbClassificationUnknownImage;
}
VOID
ElamSamplePrintHex(
_In_reads_bytes_(DataSize) PVOID Data,
_In_ ULONG DataSize
)
/*++
Routine Description:
This routine prints out the supplied data in hexadecimal form.
Arguments:
Data - Supplies a pointer to the data to be printed.
DataSize - Supplies the length in bytes of the data to be printed.
Return Value:
None.
--*/
{
PCUCHAR Bytes;
ULONG Index;
for (Bytes = (PCUCHAR)Data, Index = 0; Index < DataSize; Index++)
{
if ((Index & 15) == 0)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"\r\nElamSample: ");
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
ELAMSAMPLE_TRACE_LEVEL,
"%02x ",
Bytes[Index]);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, ELAMSAMPLE_TRACE_LEVEL, "\r\n");
}