Skip to content

Commit 13c1d16

Browse files
committed
Added CLI utility (mostly for testing), fixed major bugs, so far everything exposed by IOCTL working.
1 parent 0e0f6d6 commit 13c1d16

16 files changed

+1694
-116
lines changed

PeaceMaker CLI/IOCTLCommunication.cpp

+383
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
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

Comments
 (0)