Process Hacker
devctrl.c
Go to the documentation of this file.
1 /*
2  * KProcessHacker
3  *
4  * Copyright (C) 2010-2011 wj32
5  *
6  * This file is part of Process Hacker.
7  *
8  * Process Hacker is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Process Hacker is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <kph.h>
23 
25  __in PDEVICE_OBJECT DeviceObject,
26  __in PIRP Irp
27  )
28 {
29  NTSTATUS status;
30  PIO_STACK_LOCATION stackLocation;
31  PVOID originalInput;
32  ULONG inputLength;
33  ULONG ioControlCode;
34  KPROCESSOR_MODE accessMode;
35  UCHAR capturedInput[16 * sizeof(ULONG_PTR)];
36  PVOID capturedInputPointer;
37 
38 #define VERIFY_INPUT_LENGTH \
39  do { \
40  /* Ensure at compile time that our local buffer fits this particular call. */ \
41  C_ASSERT(sizeof(*input) <= sizeof(capturedInput)); \
42  \
43  if (inputLength != sizeof(*input)) \
44  { \
45  status = STATUS_INFO_LENGTH_MISMATCH; \
46  goto ControlEnd; \
47  } \
48  } while (0)
49 
50  stackLocation = IoGetCurrentIrpStackLocation(Irp);
51  originalInput = stackLocation->Parameters.DeviceIoControl.Type3InputBuffer;
52  inputLength = stackLocation->Parameters.DeviceIoControl.InputBufferLength;
53  ioControlCode = stackLocation->Parameters.DeviceIoControl.IoControlCode;
54  accessMode = Irp->RequestorMode;
55 
56  // Make sure we actually have input if the input length
57  // is non-zero.
58  if (inputLength != 0 && !originalInput)
59  {
60  status = STATUS_INVALID_BUFFER_SIZE;
61  goto ControlEnd;
62  }
63 
64  // Make sure the caller isn't giving us a huge buffer.
65  // If they are, it can't be correct because we have a
66  // compile-time check that makes sure our buffer can
67  // store the arguments for all the calls.
68  if (inputLength > sizeof(capturedInput))
69  {
70  status = STATUS_INVALID_BUFFER_SIZE;
71  goto ControlEnd;
72  }
73 
74  // Probe and capture the input buffer.
75  if (accessMode != KernelMode)
76  {
77  __try
78  {
79  ProbeForRead(originalInput, inputLength, sizeof(UCHAR));
80  memcpy(capturedInput, originalInput, inputLength);
81  }
82  __except (EXCEPTION_EXECUTE_HANDLER)
83  {
84  status = GetExceptionCode();
85  goto ControlEnd;
86  }
87  }
88  else
89  {
90  memcpy(capturedInput, originalInput, inputLength);
91  }
92 
93  capturedInputPointer = capturedInput; // avoid casting below
94 
95  switch (ioControlCode)
96  {
97  case KPH_GETFEATURES:
98  {
99  struct
100  {
101  PULONG Features;
102  } *input = capturedInputPointer;
103 
105 
106  status = KpiGetFeatures(
107  input->Features,
108  accessMode
109  );
110  }
111  break;
112  case KPH_OPENPROCESS:
113  {
114  struct
115  {
116  PHANDLE ProcessHandle;
117  ACCESS_MASK DesiredAccess;
118  PCLIENT_ID ClientId;
119  } *input = capturedInputPointer;
120 
122 
123  status = KpiOpenProcess(
124  input->ProcessHandle,
125  input->DesiredAccess,
126  input->ClientId,
127  accessMode
128  );
129  }
130  break;
132  {
133  struct
134  {
135  HANDLE ProcessHandle;
136  ACCESS_MASK DesiredAccess;
137  PHANDLE TokenHandle;
138  } *input = capturedInputPointer;
139 
141 
142  status = KpiOpenProcessToken(
143  input->ProcessHandle,
144  input->DesiredAccess,
145  input->TokenHandle,
146  accessMode
147  );
148  }
149  break;
150  case KPH_OPENPROCESSJOB:
151  {
152  struct
153  {
154  HANDLE ProcessHandle;
155  ACCESS_MASK DesiredAccess;
156  PHANDLE JobHandle;
157  } *input = capturedInputPointer;
158 
160 
161  status = KpiOpenProcessJob(
162  input->ProcessHandle,
163  input->DesiredAccess,
164  input->JobHandle,
165  accessMode
166  );
167  }
168  break;
169  case KPH_SUSPENDPROCESS:
170  {
171  struct
172  {
173  HANDLE ProcessHandle;
174  } *input = capturedInputPointer;
175 
177 
178  status = KpiSuspendProcess(
179  input->ProcessHandle,
180  accessMode
181  );
182  }
183  break;
184  case KPH_RESUMEPROCESS:
185  {
186  struct
187  {
188  HANDLE ProcessHandle;
189  } *input = capturedInputPointer;
190 
192 
193  status = KpiResumeProcess(
194  input->ProcessHandle,
195  accessMode
196  );
197  }
198  break;
200  {
201  struct
202  {
203  HANDLE ProcessHandle;
204  NTSTATUS ExitStatus;
205  } *input = capturedInputPointer;
206 
208 
209  status = KpiTerminateProcess(
210  input->ProcessHandle,
211  input->ExitStatus,
212  accessMode
213  );
214  }
215  break;
217  {
218  struct
219  {
220  HANDLE ProcessHandle;
221  PVOID BaseAddress;
222  PVOID Buffer;
223  SIZE_T BufferSize;
224  PSIZE_T NumberOfBytesRead;
225  } *input = capturedInputPointer;
226 
228 
229  status = KpiReadVirtualMemory(
230  input->ProcessHandle,
231  input->BaseAddress,
232  input->Buffer,
233  input->BufferSize,
234  input->NumberOfBytesRead,
235  accessMode
236  );
237  }
238  break;
240  {
241  struct
242  {
243  HANDLE ProcessHandle;
244  PVOID BaseAddress;
245  PVOID Buffer;
246  SIZE_T BufferSize;
247  PSIZE_T NumberOfBytesRead;
248  } *input = capturedInputPointer;
249 
251 
252  status = KpiWriteVirtualMemory(
253  input->ProcessHandle,
254  input->BaseAddress,
255  input->Buffer,
256  input->BufferSize,
257  input->NumberOfBytesRead,
258  accessMode
259  );
260  }
261  break;
263  {
264  struct
265  {
266  HANDLE ProcessHandle;
267  PVOID BaseAddress;
268  PVOID Buffer;
269  SIZE_T BufferSize;
270  PSIZE_T NumberOfBytesRead;
271  } *input = capturedInputPointer;
272 
274 
276  input->ProcessHandle,
277  input->BaseAddress,
278  input->Buffer,
279  input->BufferSize,
280  input->NumberOfBytesRead,
281  accessMode
282  );
283  }
284  break;
286  {
287  struct
288  {
289  HANDLE ProcessHandle;
290  KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass;
291  PVOID ProcessInformation;
292  ULONG ProcessInformationLength;
293  PULONG ReturnLength;
294  } *input = capturedInputPointer;
295 
297 
299  input->ProcessHandle,
300  input->ProcessInformationClass,
301  input->ProcessInformation,
302  input->ProcessInformationLength,
303  input->ReturnLength,
304  accessMode
305  );
306  }
307  break;
309  {
310  struct
311  {
312  HANDLE ProcessHandle;
313  KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass;
314  PVOID ProcessInformation;
315  ULONG ProcessInformationLength;
316  } *input = capturedInputPointer;
317 
319 
320  status = KpiSetInformationProcess(
321  input->ProcessHandle,
322  input->ProcessInformationClass,
323  input->ProcessInformation,
324  input->ProcessInformationLength,
325  accessMode
326  );
327  }
328  break;
329  case KPH_OPENTHREAD:
330  {
331  struct
332  {
333  PHANDLE ThreadHandle;
334  ACCESS_MASK DesiredAccess;
335  PCLIENT_ID ClientId;
336  } *input = capturedInputPointer;
337 
339 
340  status = KpiOpenThread(
341  input->ThreadHandle,
342  input->DesiredAccess,
343  input->ClientId,
344  accessMode
345  );
346  }
347  break;
349  {
350  struct
351  {
352  HANDLE ThreadHandle;
353  ACCESS_MASK DesiredAccess;
354  PHANDLE ProcessHandle;
355  } *input = capturedInputPointer;
356 
358 
359  status = KpiOpenThreadProcess(
360  input->ThreadHandle,
361  input->DesiredAccess,
362  input->ProcessHandle,
363  accessMode
364  );
365  }
366  break;
367  case KPH_TERMINATETHREAD:
368  {
369  struct
370  {
371  HANDLE ThreadHandle;
372  NTSTATUS ExitStatus;
373  } *input = capturedInputPointer;
374 
376 
377  status = KpiTerminateThread(
378  input->ThreadHandle,
379  input->ExitStatus,
380  accessMode
381  );
382  }
383  break;
385  {
386  struct
387  {
388  HANDLE ThreadHandle;
389  NTSTATUS ExitStatus;
390  } *input = capturedInputPointer;
391 
393 
394  status = KpiTerminateThreadUnsafe(
395  input->ThreadHandle,
396  input->ExitStatus,
397  accessMode
398  );
399  }
400  break;
402  {
403  struct
404  {
405  HANDLE ThreadHandle;
406  PCONTEXT ThreadContext;
407  } *input = capturedInputPointer;
408 
410 
411  status = KpiGetContextThread(
412  input->ThreadHandle,
413  input->ThreadContext,
414  accessMode
415  );
416  }
417  break;
419  {
420  struct
421  {
422  HANDLE ThreadHandle;
423  PCONTEXT ThreadContext;
424  } *input = capturedInputPointer;
425 
427 
428  status = KpiSetContextThread(
429  input->ThreadHandle,
430  input->ThreadContext,
431  accessMode
432  );
433  }
434  break;
436  {
437  struct
438  {
439  HANDLE ThreadHandle;
440  ULONG FramesToSkip;
441  ULONG FramesToCapture;
442  PVOID *BackTrace;
443  PULONG CapturedFrames;
444  PULONG BackTraceHash;
445  } *input = capturedInputPointer;
446 
448 
450  input->ThreadHandle,
451  input->FramesToSkip,
452  input->FramesToCapture,
453  input->BackTrace,
454  input->CapturedFrames,
455  input->BackTraceHash,
456  accessMode
457  );
458  }
459  break;
461  {
462  struct
463  {
464  HANDLE ThreadHandle;
465  KPH_THREAD_INFORMATION_CLASS ThreadInformationClass;
466  PVOID ThreadInformation;
467  ULONG ThreadInformationLength;
468  PULONG ReturnLength;
469  } *input = capturedInputPointer;
470 
472 
473  status = KpiQueryInformationThread(
474  input->ThreadHandle,
475  input->ThreadInformationClass,
476  input->ThreadInformation,
477  input->ThreadInformationLength,
478  input->ReturnLength,
479  accessMode
480  );
481  }
482  break;
484  {
485  struct
486  {
487  HANDLE ThreadHandle;
488  KPH_THREAD_INFORMATION_CLASS ThreadInformationClass;
489  PVOID ThreadInformation;
490  ULONG ThreadInformationLength;
491  } *input = capturedInputPointer;
492 
494 
495  status = KpiSetInformationThread(
496  input->ThreadHandle,
497  input->ThreadInformationClass,
498  input->ThreadInformation,
499  input->ThreadInformationLength,
500  accessMode
501  );
502  }
503  break;
505  {
506  struct
507  {
508  HANDLE ProcessHandle;
509  PVOID Buffer;
510  ULONG BufferLength;
511  PULONG ReturnLength;
512  } *input = capturedInputPointer;
513 
515 
517  input->ProcessHandle,
518  input->Buffer,
519  input->BufferLength,
520  input->ReturnLength,
521  accessMode
522  );
523  }
524  break;
526  {
527  struct
528  {
529  HANDLE ProcessHandle;
530  HANDLE Handle;
531  KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass;
532  PVOID ObjectInformation;
533  ULONG ObjectInformationLength;
534  PULONG ReturnLength;
535  } *input = capturedInputPointer;
536 
538 
539  status = KpiQueryInformationObject(
540  input->ProcessHandle,
541  input->Handle,
542  input->ObjectInformationClass,
543  input->ObjectInformation,
544  input->ObjectInformationLength,
545  input->ReturnLength,
546  accessMode
547  );
548  }
549  break;
551  {
552  struct
553  {
554  HANDLE ProcessHandle;
555  HANDLE Handle;
556  KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass;
557  PVOID ObjectInformation;
558  ULONG ObjectInformationLength;
559  } *input = capturedInputPointer;
560 
562 
563  status = KpiSetInformationObject(
564  input->ProcessHandle,
565  input->Handle,
566  input->ObjectInformationClass,
567  input->ObjectInformation,
568  input->ObjectInformationLength,
569  accessMode
570  );
571  }
572  break;
573  case KPH_DUPLICATEOBJECT:
574  {
575  struct
576  {
577  HANDLE SourceProcessHandle;
578  HANDLE SourceHandle;
579  HANDLE TargetProcessHandle;
580  PHANDLE TargetHandle;
581  ACCESS_MASK DesiredAccess;
582  ULONG HandleAttributes;
583  ULONG Options;
584  } *input = capturedInputPointer;
585 
587 
588  status = KpiDuplicateObject(
589  input->SourceProcessHandle,
590  input->SourceHandle,
591  input->TargetProcessHandle,
592  input->TargetHandle,
593  input->DesiredAccess,
594  input->HandleAttributes,
595  input->Options,
596  accessMode
597  );
598  }
599  break;
600  case KPH_OPENDRIVER:
601  {
602  struct
603  {
604  PHANDLE DriverHandle;
605  POBJECT_ATTRIBUTES ObjectAttributes;
606  } *input = capturedInputPointer;
607 
609 
610  status = KpiOpenDriver(
611  input->DriverHandle,
612  input->ObjectAttributes,
613  accessMode
614  );
615  }
616  break;
618  {
619  struct
620  {
621  HANDLE DriverHandle;
622  DRIVER_INFORMATION_CLASS DriverInformationClass;
623  PVOID DriverInformation;
624  ULONG DriverInformationLength;
625  PULONG ReturnLength;
626  } *input = capturedInputPointer;
627 
629 
630  status = KpiQueryInformationDriver(
631  input->DriverHandle,
632  input->DriverInformationClass,
633  input->DriverInformation,
634  input->DriverInformationLength,
635  input->ReturnLength,
636  accessMode
637  );
638  }
639  break;
640  default:
641  status = STATUS_INVALID_DEVICE_REQUEST;
642  break;
643  }
644 
645 ControlEnd:
646  Irp->IoStatus.Status = status;
647  Irp->IoStatus.Information = 0;
648  IoCompleteRequest(Irp, IO_NO_INCREMENT);
649 
650  return status;
651 }