1
+ #include " IOCTLCommunication.h"
2
+
3
+ /* *
4
+ Default constructor.
5
+ */
6
+ IOCTLCommunication::IOCTLCommunication (
7
+ VOID
8
+ )
9
+ {
10
+
11
+ }
12
+
13
+ /* *
14
+ Disconnect from the driver.
15
+ */
16
+ IOCTLCommunication::~IOCTLCommunication (
17
+ VOID
18
+ )
19
+ {
20
+ CloseHandle (this ->device );
21
+ }
22
+
23
+ /* *
24
+ Establish communication with the driver.
25
+ @return Whether or not we successfully connected to the driver.
26
+ */
27
+ BOOLEAN
28
+ IOCTLCommunication::ConnectDevice (
29
+ VOID
30
+ )
31
+ {
32
+ this ->device = CreateFile (GLOBAL_NAME, GENERIC_READ | GENERIC_WRITE, 0 , NULL , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
33
+ if (this ->device == INVALID_HANDLE_VALUE)
34
+ {
35
+ printf (" IOCTLCommunication!IOCTLCommunication: Failed to connect to driver device with error %i.\n " , GetLastError ());
36
+ return FALSE ;
37
+ }
38
+
39
+ printf (" IOCTLCommunication!IOCTLCommunication: Established communication with driver.\n " );
40
+ return TRUE ;
41
+ }
42
+
43
+ /* *
44
+ Small wrapper around the DeviceIoControl call to the driver.
45
+ @param IOCTLCode - The IOCTL code to pass to the driver.
46
+ @param Input - The input buffer.
47
+ @param InputLength - Size of the input buffer.
48
+ @param Output - The output buffer.
49
+ @param OutputLength - Size of the output buffer.
50
+ @return Whether or not the call succeeded.
51
+ */
52
+ BOOLEAN
53
+ IOCTLCommunication::GenericQueryDriver (
54
+ _In_ DWORD IOCTLCode,
55
+ _In_ PVOID Input,
56
+ _In_ DWORD InputLength,
57
+ _Out_ PVOID Output,
58
+ _In_ DWORD OutputLength
59
+ )
60
+ {
61
+ DWORD bytesReturned;
62
+ return DeviceIoControl (this ->device , IOCTLCode, Input, InputLength, Output, OutputLength, &bytesReturned, NULL );
63
+ }
64
+
65
+ /* *
66
+ Query if there are alerts queued.
67
+ @return Whether or not alerts are queued.
68
+ */
69
+ BOOLEAN
70
+ IOCTLCommunication::QueuedAlerts (
71
+ VOID
72
+ )
73
+ {
74
+ BOOLEAN queued;
75
+
76
+ //
77
+ // Query the driver passing in an output boolean.
78
+ //
79
+ if (this ->GenericQueryDriver (IOCTL_ALERTS_QUEUED, NULL , 0 , &queued, sizeof (queued)) == FALSE )
80
+ {
81
+ printf (" IOCTLCommunication!QueuedAlerts: Failed to query driver with error code %i.\n " , GetLastError ());
82
+ return FALSE ;
83
+ }
84
+
85
+ return queued;
86
+ }
87
+
88
+ /* *
89
+ Pop a queued alert from the Alerts queue.
90
+ @return An allocated pointer to the alert or NULL if unable to pop an alert. Caller must free to prevent leak.
91
+ */
92
+ PBASE_ALERT_INFO
93
+ IOCTLCommunication::PopAlert (
94
+ VOID
95
+ )
96
+ {
97
+ BOOLEAN success;
98
+ PBASE_ALERT_INFO alert;
99
+
100
+ success = FALSE ;
101
+
102
+ alert = RCAST<PBASE_ALERT_INFO>(malloc (MAX_STACK_VIOLATION_ALERT_SIZE));
103
+ if (alert == NULL )
104
+ {
105
+ printf (" IOCTLCommunication!PopAlert: Failed to allocate space for alert.\n " );
106
+ goto Exit;
107
+ }
108
+ memset (alert, 0 , MAX_STACK_VIOLATION_ALERT_SIZE);
109
+
110
+ if (this ->GenericQueryDriver (IOCTL_POP_ALERT, NULL , 0 , alert, MAX_STACK_VIOLATION_ALERT_SIZE) == FALSE )
111
+ {
112
+ printf (" IOCTLCommunication!PopAlert: Failed to query driver with error code %i.\n " , GetLastError ());
113
+ goto Exit;
114
+ }
115
+ success = TRUE ;
116
+ Exit:
117
+ if (success == FALSE && alert)
118
+ {
119
+ free (alert);
120
+ alert = NULL ;
121
+ }
122
+ return alert;
123
+ }
124
+
125
+ /* *
126
+ Request a summary of the most recent processes up to RequestCount.
127
+ @param SkipCount - How many processes to "skip" in iteration.
128
+ @param RequestCount - How many proocesses to get the summary of.
129
+ @return The response to the summary request if any, otherwise NULL. Caller must free to prevent leak.
130
+ */
131
+ PPROCESS_SUMMARY_REQUEST
132
+ IOCTLCommunication::RequestProcessSummary (
133
+ _In_ ULONG SkipCount,
134
+ _In_ ULONG RequestCount
135
+ )
136
+ {
137
+ BOOLEAN success;
138
+ PPROCESS_SUMMARY_REQUEST summaryRequest;
139
+ ULONG summaryRequestSize;
140
+
141
+ success = FALSE ;
142
+ summaryRequestSize = MAX_PROCESS_SUMMARY_REQUEST_SIZE_RAW (RequestCount);
143
+
144
+ summaryRequest = RCAST<PPROCESS_SUMMARY_REQUEST>(malloc (summaryRequestSize));
145
+ if (summaryRequest == NULL )
146
+ {
147
+ printf (" IOCTLCommunication!RequestProcessSummary: Failed to allocate space for summaryRequest.\n " );
148
+ goto Exit;
149
+ }
150
+ memset (summaryRequest, 0 , summaryRequestSize);
151
+
152
+ summaryRequest->SkipCount = SkipCount;
153
+ summaryRequest->ProcessHistorySize = RequestCount;
154
+
155
+ if (this ->GenericQueryDriver (IOCTL_GET_PROCESSES, summaryRequest, summaryRequestSize, summaryRequest, summaryRequestSize) == FALSE )
156
+ {
157
+ printf (" IOCTLCommunication!RequestProcessSummary: Failed to query driver with error code %i.\n " , GetLastError ());
158
+ goto Exit;
159
+ }
160
+ success = TRUE ;
161
+ Exit:
162
+ if (success == FALSE && summaryRequest)
163
+ {
164
+ free (summaryRequest);
165
+ summaryRequest = NULL ;
166
+ }
167
+ return summaryRequest;
168
+ }
169
+
170
+ /* *
171
+ Request detailed information on a process.
172
+ @param ProcessId - The subject process.
173
+ @param EpochExecutionTime - The time the process was executed (in seconds since epoch).
174
+ @param MaxImageSize - The maximum number of image entries to copy.
175
+ @param MaxStackSize - The maximum number of stack entries to copy.
176
+ @return The response to the detailed request if any, otherwise NULL. Caller must free to prevent leak.
177
+ */
178
+ PPROCESS_DETAILED_REQUEST
179
+ IOCTLCommunication::RequestDetailedProcess (
180
+ _In_ HANDLE ProcessId,
181
+ _In_ ULONG EpochExecutionTime,
182
+ _In_ ULONG MaxImageSize,
183
+ _In_ ULONG MaxStackSize
184
+ )
185
+ {
186
+ BOOLEAN success;
187
+ PPROCESS_DETAILED_REQUEST detailedRequest;
188
+ ULONG detailedRequestSize;
189
+
190
+ success = FALSE ;
191
+ detailedRequestSize = sizeof (PROCESS_DETAILED_REQUEST);
192
+
193
+ //
194
+ // Allocate the necessary members.
195
+ //
196
+ detailedRequest = RCAST<PPROCESS_DETAILED_REQUEST>(malloc (detailedRequestSize));
197
+ if (detailedRequest == NULL )
198
+ {
199
+ printf (" IOCTLCommunication!RequestDetailedProcess: Failed to allocate space for detailedRequest.\n " );
200
+ goto Exit;
201
+ }
202
+ memset (detailedRequest, 0 , detailedRequestSize);
203
+
204
+ detailedRequest->ImageSummary = RCAST<PIMAGE_SUMMARY>(malloc (MaxImageSize * sizeof (IMAGE_SUMMARY)));
205
+ if (detailedRequest->ImageSummary == NULL )
206
+ {
207
+ printf (" IOCTLCommunication!RequestDetailedProcess: Failed to allocate space for detailedRequest->ImageSummary.\n " );
208
+ goto Exit;
209
+ }
210
+ memset (detailedRequest->ImageSummary , 0 , MaxImageSize * sizeof (IMAGE_SUMMARY));
211
+
212
+ detailedRequest->StackHistory = RCAST<PSTACK_RETURN_INFO>(malloc (MaxStackSize * sizeof (STACK_RETURN_INFO)));
213
+ if (detailedRequest->StackHistory == NULL )
214
+ {
215
+ printf (" IOCTLCommunication!RequestDetailedProcess: Failed to allocate space for detailedRequest->StackHistory.\n " );
216
+ goto Exit;
217
+ }
218
+ memset (detailedRequest->StackHistory , 0 , MaxStackSize * sizeof (STACK_RETURN_INFO));
219
+
220
+ detailedRequest->ProcessId = ProcessId;
221
+ detailedRequest->EpochExecutionTime = EpochExecutionTime;
222
+ detailedRequest->ImageSummarySize = MaxImageSize;
223
+ detailedRequest->StackHistorySize = MaxStackSize;
224
+
225
+ if (this ->GenericQueryDriver (IOCTL_GET_PROCESS_DETAILED, detailedRequest, detailedRequestSize, detailedRequest, detailedRequestSize) == FALSE )
226
+ {
227
+ printf (" IOCTLCommunication!RequestDetailedProcess: Failed to query driver with error code %i.\n " , GetLastError ());
228
+ goto Exit;
229
+ }
230
+ success = TRUE ;
231
+ Exit:
232
+ if (success == FALSE && detailedRequest)
233
+ {
234
+ free (detailedRequest);
235
+ detailedRequest = NULL ;
236
+ }
237
+ return detailedRequest;
238
+ }
239
+
240
+ /* *
241
+ Register a filter with the driver.
242
+ @param Type - The filter type.
243
+ @param Flags - The filter flags (EXECUTE/DELETE/WRITE/ETC).
244
+ @param Content - The content of the filter.
245
+ @param ContentLength - The size of the content.
246
+ @return The filter ID (if added successfully), otherwise 0.
247
+ */
248
+ ULONG
249
+ IOCTLCommunication::AddFilter (
250
+ _In_ STRING_FILTER_TYPE Type,
251
+ _In_ ULONG Flags,
252
+ _In_ PWCHAR Content,
253
+ _In_ ULONG ContentLength
254
+ )
255
+ {
256
+
257
+ STRING_FILTER_REQUEST filterRequest;
258
+
259
+ //
260
+ // Fill out the struct.
261
+ //
262
+ filterRequest.FilterType = Type;
263
+ filterRequest.Filter .Flags = Flags;
264
+ memcpy_s (filterRequest.Filter .MatchString , sizeof (filterRequest.Filter .MatchString ), Content, ContentLength * sizeof (WCHAR));
265
+ filterRequest.Filter .MatchStringSize = ContentLength;
266
+
267
+ //
268
+ // Query the driver passing in the filter request.
269
+ //
270
+ if (this ->GenericQueryDriver (IOCTL_ADD_FILTER, &filterRequest, sizeof (filterRequest), &filterRequest, sizeof (filterRequest)) == FALSE )
271
+ {
272
+ printf (" IOCTLCommunication!AddFilter: Failed to query driver with error code %i.\n " , GetLastError ());
273
+ return 0 ;
274
+ }
275
+
276
+ return filterRequest.Filter .Id ;
277
+ }
278
+
279
+ /* *
280
+ Request a list of filters with a constant size of 10. Grab more by using the SkipCount argument.
281
+ @param Type - The type of filters to grab.
282
+ @param SkipCount - The number of filters to skip during iteration.
283
+ @return The response to the request.
284
+ */
285
+ LIST_FILTERS_REQUEST
286
+ IOCTLCommunication::RequestFilters (
287
+ _In_ STRING_FILTER_TYPE Type,
288
+ _In_ ULONG SkipCount
289
+ )
290
+ {
291
+ LIST_FILTERS_REQUEST listRequest;
292
+
293
+ listRequest.FilterType = Type;
294
+ listRequest.SkipFilters = SkipCount;
295
+
296
+ //
297
+ // Query the driver passing in the list request.
298
+ //
299
+ if (this ->GenericQueryDriver (IOCTL_LIST_FILTERS, &listRequest, sizeof (listRequest), &listRequest, sizeof (listRequest)) == FALSE )
300
+ {
301
+ printf (" IOCTLCommunication!RequestFilters: Failed to query driver with error code %i.\n " , GetLastError ());
302
+ }
303
+
304
+ return listRequest;
305
+ }
306
+
307
+ /* *
308
+ Get the dynamic sizes in a process entry from the driver.
309
+ @param ProcessId - The target process ID.
310
+ @param EpochExecutionTime - The time the target process was executed.
311
+ @return The response.
312
+ */
313
+ PROCESS_SIZES_REQUEST
314
+ IOCTLCommunication::GetProcessSizes (
315
+ _In_ HANDLE ProcessId,
316
+ _In_ ULONG EpochExecutionTime
317
+ )
318
+ {
319
+ PROCESS_SIZES_REQUEST sizeRequest;
320
+
321
+ sizeRequest.ProcessId = ProcessId;
322
+ sizeRequest.EpochExecutionTime = EpochExecutionTime;
323
+
324
+ //
325
+ // Query the driver passing in the list request.
326
+ //
327
+ if (this ->GenericQueryDriver (IOCTL_GET_PROCESS_SIZES, &sizeRequest, sizeof (sizeRequest), &sizeRequest, sizeof (sizeRequest)) == FALSE )
328
+ {
329
+ printf (" IOCTLCommunication!GetProcessSizes: Failed to query driver with error code %i.\n " , GetLastError ());
330
+ }
331
+
332
+ return sizeRequest;
333
+ }
334
+
335
+ /* *
336
+ Request detailed information on an image.
337
+ @param ProcessId - The subject process.
338
+ @param EpochExecutionTime - The time the process was executed (in seconds since epoch).
339
+ @param MaxStackSize - The maximum number of stack entries to copy.
340
+ @return The response to the detailed request if any, otherwise NULL. Caller must free to prevent leak.
341
+ */
342
+ PIMAGE_DETAILED_REQUEST
343
+ IOCTLCommunication::RequestDetailedImage (
344
+ _In_ HANDLE ProcessId,
345
+ _In_ ULONG EpochExecutionTime,
346
+ _In_ ULONG ImageIndex,
347
+ _In_ ULONG MaxStackSize
348
+ )
349
+ {
350
+ BOOLEAN success;
351
+ PIMAGE_DETAILED_REQUEST imageRequest;
352
+ ULONG imageRequestSize;
353
+
354
+ success = FALSE ;
355
+ imageRequestSize = MAX_IMAGE_DETAILED_REQUEST_SIZE_RAW (MaxStackSize);
356
+
357
+ imageRequest = RCAST<PIMAGE_DETAILED_REQUEST>(malloc (imageRequestSize));
358
+ if (imageRequest == NULL )
359
+ {
360
+ printf (" IOCTLCommunication!RequestDetailedImage: Failed to allocate space for imageRequest.\n " );
361
+ goto Exit;
362
+ }
363
+ memset (imageRequest, 0 , imageRequestSize);
364
+
365
+ imageRequest->ProcessId = ProcessId;
366
+ imageRequest->EpochExecutionTime = EpochExecutionTime;
367
+ imageRequest->ImageIndex = ImageIndex;
368
+ imageRequest->StackHistorySize = MaxStackSize;
369
+
370
+ if (this ->GenericQueryDriver (IOCTL_GET_IMAGE_DETAILED, imageRequest, imageRequestSize, imageRequest, imageRequestSize) == FALSE )
371
+ {
372
+ printf (" IOCTLCommunication!RequestDetailedImage: Failed to query driver with error code %i.\n " , GetLastError ());
373
+ goto Exit;
374
+ }
375
+ success = TRUE ;
376
+ Exit:
377
+ if (success == FALSE && imageRequest)
378
+ {
379
+ free (imageRequest);
380
+ imageRequest = NULL ;
381
+ }
382
+ return imageRequest;
383
+ }
0 commit comments