Process Hacker
kph.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * KProcessHacker API
4  *
5  * Copyright (C) 2009-2011 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <ph.h>
24 #include <kphuser.h>
25 
26 NTSTATUS KphpDeviceIoControl(
27  _In_ ULONG KphControlCode,
28  _In_ PVOID InBuffer,
29  _In_ ULONG InBufferLength
30  );
31 
32 HANDLE PhKphHandle = NULL;
33 
34 NTSTATUS KphConnect(
35  _In_opt_ PWSTR DeviceName
36  )
37 {
38  NTSTATUS status;
39  HANDLE kphHandle;
40  UNICODE_STRING objectName;
41  OBJECT_ATTRIBUTES objectAttributes;
42  IO_STATUS_BLOCK isb;
43  OBJECT_HANDLE_FLAG_INFORMATION handleFlagInfo;
44 
45  if (PhKphHandle)
46  return STATUS_ADDRESS_ALREADY_EXISTS;
47 
48  if (DeviceName)
49  RtlInitUnicodeString(&objectName, DeviceName);
50  else
52 
54  &objectAttributes,
55  &objectName,
57  NULL,
58  NULL
59  );
60 
61  status = NtOpenFile(
62  &kphHandle,
63  FILE_GENERIC_READ | FILE_GENERIC_WRITE,
64  &objectAttributes,
65  &isb,
66  FILE_SHARE_READ | FILE_SHARE_WRITE,
68  );
69 
70  if (NT_SUCCESS(status))
71  {
72  // Protect the handle from being closed.
73 
74  handleFlagInfo.Inherit = FALSE;
75  handleFlagInfo.ProtectFromClose = TRUE;
76 
77  NtSetInformationObject(
78  kphHandle,
80  &handleFlagInfo,
82  );
83 
84  PhKphHandle = kphHandle;
85  }
86 
87  return status;
88 }
89 
90 NTSTATUS KphConnect2(
91  _In_opt_ PWSTR DeviceName,
92  _In_ PWSTR FileName
93  )
94 {
95  return KphConnect2Ex(DeviceName, FileName, NULL);
96 }
97 
98 NTSTATUS KphConnect2Ex(
99  _In_opt_ PWSTR DeviceName,
100  _In_ PWSTR FileName,
101  _In_opt_ PKPH_PARAMETERS Parameters
102  )
103 {
104  NTSTATUS status;
105  WCHAR fullDeviceName[256];
106  PH_FORMAT format[2];
107  SC_HANDLE scmHandle;
108  SC_HANDLE serviceHandle;
109  BOOLEAN started = FALSE;
110  BOOLEAN created = FALSE;
111 
112  if (!DeviceName)
113  DeviceName = KPH_DEVICE_SHORT_NAME;
114 
115  PhInitFormatS(&format[0], L"\\Device\\");
116  PhInitFormatS(&format[1], DeviceName);
117 
118  if (!PhFormatToBuffer(format, 2, fullDeviceName, sizeof(fullDeviceName), NULL))
119  return STATUS_NAME_TOO_LONG;
120 
121  // Try to open the device.
122  status = KphConnect(fullDeviceName);
123 
124  if (NT_SUCCESS(status) || status == STATUS_ADDRESS_ALREADY_EXISTS)
125  return status;
126 
127  if (
128  status != STATUS_NO_SUCH_DEVICE &&
129  status != STATUS_NO_SUCH_FILE &&
130  status != STATUS_OBJECT_NAME_NOT_FOUND &&
131  status != STATUS_OBJECT_PATH_NOT_FOUND
132  )
133  return status;
134 
135  // Load the driver, and try again.
136 
137  // Try to start the service, if it exists.
138 
139  scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
140 
141  if (scmHandle)
142  {
143  serviceHandle = OpenService(scmHandle, DeviceName, SERVICE_START);
144 
145  if (serviceHandle)
146  {
147  if (StartService(serviceHandle, 0, NULL))
148  started = TRUE;
149 
150  CloseServiceHandle(serviceHandle);
151  }
152 
153  CloseServiceHandle(scmHandle);
154  }
155 
156  if (!started && RtlDoesFileExists_U(FileName))
157  {
158  // Try to create the service.
159 
160  scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
161 
162  if (scmHandle)
163  {
164  serviceHandle = CreateService(
165  scmHandle,
166  DeviceName,
167  DeviceName,
168  SERVICE_ALL_ACCESS,
169  SERVICE_KERNEL_DRIVER,
170  SERVICE_DEMAND_START,
171  SERVICE_ERROR_IGNORE,
172  FileName,
173  NULL,
174  NULL,
175  NULL,
176  NULL,
177  L""
178  );
179 
180  if (serviceHandle)
181  {
182  created = TRUE;
183 
184  // Set parameters if the caller supplied them.
185  // Note that we fail the entire function if this fails,
186  // because failing to set parameters like SecurityLevel may
187  // result in security vulnerabilities.
188  if (Parameters)
189  {
190  status = KphSetParameters(DeviceName, Parameters);
191 
192  if (!NT_SUCCESS(status))
193  {
194  // Delete the service and fail.
195  goto CreateAndConnectEnd;
196  }
197  }
198 
199  if (StartService(serviceHandle, 0, NULL))
200  started = TRUE;
201  }
202 
203  CloseServiceHandle(scmHandle);
204  }
205  }
206 
207  if (started)
208  {
209  // Try to open the device again.
210  status = KphConnect(fullDeviceName);
211  }
212 
213 CreateAndConnectEnd:
214  if (created)
215  {
216  // "Delete" the service. Since we (may) have a handle to
217  // the device, the SCM will delete the service automatically
218  // when it is stopped (upon reboot). If we don't have a
219  // handle to the device, the service will get deleted immediately,
220  // which is a good thing anyway.
221  DeleteService(serviceHandle);
222  CloseServiceHandle(serviceHandle);
223  }
224 
225  return status;
226 }
227 
228 NTSTATUS KphDisconnect(
229  VOID
230  )
231 {
232  NTSTATUS status;
233  OBJECT_HANDLE_FLAG_INFORMATION handleFlagInfo;
234 
235  if (!PhKphHandle)
236  return STATUS_ALREADY_DISCONNECTED;
237 
238  // Unprotect the handle.
239 
240  handleFlagInfo.Inherit = FALSE;
241  handleFlagInfo.ProtectFromClose = FALSE;
242 
243  NtSetInformationObject(
244  PhKphHandle,
246  &handleFlagInfo,
248  );
249 
250  status = NtClose(PhKphHandle);
251  PhKphHandle = NULL;
252 
253  return status;
254 }
255 
257  VOID
258  )
259 {
260  return PhKphHandle != NULL;
261 }
262 
264  _In_opt_ PWSTR DeviceName,
265  _In_ PKPH_PARAMETERS Parameters
266  )
267 {
268  NTSTATUS status;
269  HANDLE parametersKeyHandle = NULL;
270  PPH_STRING parametersKeyName;
271  ULONG disposition;
272  UNICODE_STRING valueName;
273 
274  if (!DeviceName)
275  DeviceName = KPH_DEVICE_SHORT_NAME;
276 
277  parametersKeyName = PhConcatStrings(
278  3,
279  L"System\\CurrentControlSet\\Services\\",
280  DeviceName,
281  L"\\Parameters"
282  );
283  status = PhCreateKey(
284  &parametersKeyHandle,
285  KEY_WRITE | DELETE,
287  &parametersKeyName->sr,
288  0,
289  0,
290  &disposition
291  );
292  PhDereferenceObject(parametersKeyName);
293 
294  if (!NT_SUCCESS(status))
295  return status;
296 
297  RtlInitUnicodeString(&valueName, L"SecurityLevel");
298  status = NtSetValueKey(parametersKeyHandle, &valueName, 0, REG_DWORD, &Parameters->SecurityLevel, sizeof(ULONG));
299 
300  if (!NT_SUCCESS(status))
301  goto SetValuesEnd;
302 
303  if (Parameters->CreateDynamicConfiguration)
304  {
305  KPH_DYN_CONFIGURATION configuration;
306 
307  RtlInitUnicodeString(&valueName, L"DynamicConfiguration");
308 
309  configuration.Version = KPH_DYN_CONFIGURATION_VERSION;
310  configuration.NumberOfPackages = 1;
311 
312  if (NT_SUCCESS(KphInitializeDynamicPackage(&configuration.Packages[0])))
313  {
314  status = NtSetValueKey(parametersKeyHandle, &valueName, 0, REG_BINARY, &configuration, sizeof(KPH_DYN_CONFIGURATION));
315 
316  if (!NT_SUCCESS(status))
317  goto SetValuesEnd;
318  }
319  }
320 
321  // Put more parameters here...
322 
323 SetValuesEnd:
324  if (!NT_SUCCESS(status))
325  {
326  // Delete the key if we created it.
327  if (disposition == REG_CREATED_NEW_KEY)
328  NtDeleteKey(parametersKeyHandle);
329  }
330 
331  NtClose(parametersKeyHandle);
332 
333  return status;
334 }
335 
336 NTSTATUS KphInstall(
337  _In_opt_ PWSTR DeviceName,
338  _In_ PWSTR FileName
339  )
340 {
341  return KphInstallEx(DeviceName, FileName, NULL);
342 }
343 
344 NTSTATUS KphInstallEx(
345  _In_opt_ PWSTR DeviceName,
346  _In_ PWSTR FileName,
347  _In_opt_ PKPH_PARAMETERS Parameters
348  )
349 {
350  NTSTATUS status = STATUS_SUCCESS;
351  SC_HANDLE scmHandle;
352  SC_HANDLE serviceHandle;
353 
354  if (!DeviceName)
355  DeviceName = KPH_DEVICE_SHORT_NAME;
356 
357  scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
358 
359  if (!scmHandle)
361 
362  serviceHandle = CreateService(
363  scmHandle,
364  DeviceName,
365  DeviceName,
366  SERVICE_ALL_ACCESS,
367  SERVICE_KERNEL_DRIVER,
368  SERVICE_SYSTEM_START,
369  SERVICE_ERROR_IGNORE,
370  FileName,
371  NULL,
372  NULL,
373  NULL,
374  NULL,
375  L""
376  );
377 
378  if (serviceHandle)
379  {
380  // See KphConnect2Ex for more details.
381  if (Parameters)
382  {
383  status = KphSetParameters(DeviceName, Parameters);
384 
385  if (!NT_SUCCESS(status))
386  {
387  DeleteService(serviceHandle);
388  goto CreateEnd;
389  }
390  }
391 
392  if (!StartService(serviceHandle, 0, NULL))
394 
395 CreateEnd:
396  CloseServiceHandle(serviceHandle);
397  }
398  else
399  {
401  }
402 
403  CloseServiceHandle(scmHandle);
404 
405  return status;
406 }
407 
408 NTSTATUS KphUninstall(
409  _In_opt_ PWSTR DeviceName
410  )
411 {
412  NTSTATUS status = STATUS_SUCCESS;
413  SC_HANDLE scmHandle;
414  SC_HANDLE serviceHandle;
415 
416  if (!DeviceName)
417  DeviceName = KPH_DEVICE_SHORT_NAME;
418 
419  scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
420 
421  if (!scmHandle)
423 
424  serviceHandle = OpenService(scmHandle, DeviceName, SERVICE_STOP | DELETE);
425 
426  if (serviceHandle)
427  {
428  SERVICE_STATUS serviceStatus;
429 
430  ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus);
431 
432  if (!DeleteService(serviceHandle))
434 
435  CloseServiceHandle(serviceHandle);
436  }
437  else
438  {
440  }
441 
442  CloseServiceHandle(scmHandle);
443 
444  return status;
445 }
446 
448  _In_ ULONG KphControlCode,
449  _In_ PVOID InBuffer,
450  _In_ ULONG InBufferLength
451  )
452 {
453  IO_STATUS_BLOCK isb;
454 
455  return NtDeviceIoControlFile(
456  PhKphHandle,
457  NULL,
458  NULL,
459  NULL,
460  &isb,
461  KphControlCode,
462  InBuffer,
463  InBufferLength,
464  NULL,
465  0
466  );
467 }
468 
469 NTSTATUS KphGetFeatures(
470  _Out_ PULONG Features
471  )
472 {
473  struct
474  {
475  PULONG Features;
476  } input = { Features };
477 
478  return KphpDeviceIoControl(
480  &input,
481  sizeof(input)
482  );
483 }
484 
485 NTSTATUS KphOpenProcess(
486  _Out_ PHANDLE ProcessHandle,
487  _In_ ACCESS_MASK DesiredAccess,
488  _In_ PCLIENT_ID ClientId
489  )
490 {
491  struct
492  {
493  PHANDLE ProcessHandle;
494  ACCESS_MASK DesiredAccess;
495  PCLIENT_ID ClientId;
496  } input = { ProcessHandle, DesiredAccess, ClientId };
497 
498  return KphpDeviceIoControl(
500  &input,
501  sizeof(input)
502  );
503 }
504 
506  _In_ HANDLE ProcessHandle,
507  _In_ ACCESS_MASK DesiredAccess,
508  _Out_ PHANDLE TokenHandle
509  )
510 {
511  struct
512  {
513  HANDLE ProcessHandle;
514  ACCESS_MASK DesiredAccess;
515  PHANDLE TokenHandle;
516  } input = { ProcessHandle, DesiredAccess, TokenHandle };
517 
518  return KphpDeviceIoControl(
520  &input,
521  sizeof(input)
522  );
523 }
524 
526  _In_ HANDLE ProcessHandle,
527  _In_ ACCESS_MASK DesiredAccess,
528  _Out_ PHANDLE JobHandle
529  )
530 {
531  struct
532  {
533  HANDLE ProcessHandle;
534  ACCESS_MASK DesiredAccess;
535  PHANDLE JobHandle;
536  } input = { ProcessHandle, DesiredAccess, JobHandle };
537 
538  return KphpDeviceIoControl(
540  &input,
541  sizeof(input)
542  );
543 }
544 
546  _In_ HANDLE ProcessHandle
547  )
548 {
549  struct
550  {
551  HANDLE ProcessHandle;
552  } input = { ProcessHandle };
553 
554  return KphpDeviceIoControl(
556  &input,
557  sizeof(input)
558  );
559 }
560 
562  _In_ HANDLE ProcessHandle
563  )
564 {
565  struct
566  {
567  HANDLE ProcessHandle;
568  } input = { ProcessHandle };
569 
570  return KphpDeviceIoControl(
572  &input,
573  sizeof(input)
574  );
575 }
576 
578  _In_ HANDLE ProcessHandle,
579  _In_ NTSTATUS ExitStatus
580  )
581 {
582  NTSTATUS status;
583  struct
584  {
585  HANDLE ProcessHandle;
586  NTSTATUS ExitStatus;
587  } input = { ProcessHandle, ExitStatus };
588 
589  status = KphpDeviceIoControl(
591  &input,
592  sizeof(input)
593  );
594 
595  // Check if we're trying to terminate the current process,
596  // because kernel-mode can't do it.
597  if (status == STATUS_CANT_TERMINATE_SELF)
598  {
599  RtlExitUserProcess(ExitStatus);
600  }
601 
602  return status;
603 }
604 
606  _In_ HANDLE ProcessHandle,
607  _In_ PVOID BaseAddress,
608  _Out_writes_bytes_(BufferSize) PVOID Buffer,
609  _In_ SIZE_T BufferSize,
610  _Out_opt_ PSIZE_T NumberOfBytesRead
611  )
612 {
613  struct
614  {
615  HANDLE ProcessHandle;
616  PVOID BaseAddress;
617  PVOID Buffer;
618  SIZE_T BufferSize;
619  PSIZE_T NumberOfBytesRead;
620  } input = { ProcessHandle, BaseAddress, Buffer, BufferSize, NumberOfBytesRead };
621 
622  return KphpDeviceIoControl(
624  &input,
625  sizeof(input)
626  );
627 }
628 
630  _In_ HANDLE ProcessHandle,
631  _In_opt_ PVOID BaseAddress,
632  _In_reads_bytes_(BufferSize) PVOID Buffer,
633  _In_ SIZE_T BufferSize,
634  _Out_opt_ PSIZE_T NumberOfBytesWritten
635  )
636 {
637  struct
638  {
639  HANDLE ProcessHandle;
640  PVOID BaseAddress;
641  PVOID Buffer;
642  SIZE_T BufferSize;
643  PSIZE_T NumberOfBytesWritten;
644  } input = { ProcessHandle, BaseAddress, Buffer, BufferSize, NumberOfBytesWritten };
645 
646  return KphpDeviceIoControl(
648  &input,
649  sizeof(input)
650  );
651 }
652 
654  _In_opt_ HANDLE ProcessHandle,
655  _In_ PVOID BaseAddress,
656  _Out_writes_bytes_(BufferSize) PVOID Buffer,
657  _In_ SIZE_T BufferSize,
658  _Out_opt_ PSIZE_T NumberOfBytesRead
659  )
660 {
661  struct
662  {
663  HANDLE ProcessHandle;
664  PVOID BaseAddress;
665  PVOID Buffer;
666  SIZE_T BufferSize;
667  PSIZE_T NumberOfBytesRead;
668  } input = { ProcessHandle, BaseAddress, Buffer, BufferSize, NumberOfBytesRead };
669 
670  return KphpDeviceIoControl(
672  &input,
673  sizeof(input)
674  );
675 }
676 
678  _In_ HANDLE ProcessHandle,
679  _In_ KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
680  _Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,
681  _In_ ULONG ProcessInformationLength,
682  _Out_opt_ PULONG ReturnLength
683  )
684 {
685  struct
686  {
687  HANDLE ProcessHandle;
688  KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass;
689  PVOID ProcessInformation;
690  ULONG ProcessInformationLength;
691  PULONG ReturnLength;
692  } input = { ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength };
693 
694  return KphpDeviceIoControl(
696  &input,
697  sizeof(input)
698  );
699 }
700 
702  _In_ HANDLE ProcessHandle,
703  _In_ KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
704  _In_reads_bytes_(ProcessInformationLength) PVOID ProcessInformation,
705  _In_ ULONG ProcessInformationLength
706  )
707 {
708  struct
709  {
710  HANDLE ProcessHandle;
711  KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass;
712  PVOID ProcessInformation;
713  ULONG ProcessInformationLength;
714  } input = { ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength };
715 
716  return KphpDeviceIoControl(
718  &input,
719  sizeof(input)
720  );
721 }
722 
723 NTSTATUS KphOpenThread(
724  _Out_ PHANDLE ThreadHandle,
725  _In_ ACCESS_MASK DesiredAccess,
726  _In_ PCLIENT_ID ClientId
727  )
728 {
729  struct
730  {
731  PHANDLE ThreadHandle;
732  ACCESS_MASK DesiredAccess;
733  PCLIENT_ID ClientId;
734  } input = { ThreadHandle, DesiredAccess, ClientId };
735 
736  return KphpDeviceIoControl(
738  &input,
739  sizeof(input)
740  );
741 }
742 
744  _In_ HANDLE ThreadHandle,
745  _In_ ACCESS_MASK DesiredAccess,
746  _Out_ PHANDLE ProcessHandle
747  )
748 {
749  struct
750  {
751  HANDLE ThreadHandle;
752  ACCESS_MASK DesiredAccess;
753  PHANDLE ProcessHandle;
754  } input = { ThreadHandle, DesiredAccess, ProcessHandle };
755 
756  return KphpDeviceIoControl(
758  &input,
759  sizeof(input)
760  );
761 }
762 
764  _In_ HANDLE ThreadHandle,
765  _In_ NTSTATUS ExitStatus
766  )
767 {
768  NTSTATUS status;
769  struct
770  {
771  HANDLE ThreadHandle;
772  NTSTATUS ExitStatus;
773  } input = { ThreadHandle, ExitStatus };
774 
775  status = KphpDeviceIoControl(
777  &input,
778  sizeof(input)
779  );
780 
781  if (status == STATUS_CANT_TERMINATE_SELF)
782  {
783  RtlExitUserThread(ExitStatus);
784  }
785 
786  return status;
787 }
788 
790  _In_ HANDLE ThreadHandle,
791  _In_ NTSTATUS ExitStatus
792  )
793 {
794  struct
795  {
796  HANDLE ThreadHandle;
797  NTSTATUS ExitStatus;
798  } input = { ThreadHandle, ExitStatus };
799 
800  return KphpDeviceIoControl(
802  &input,
803  sizeof(input)
804  );
805 }
806 
808  _In_ HANDLE ThreadHandle,
809  _Inout_ PCONTEXT ThreadContext
810  )
811 {
812  struct
813  {
814  HANDLE ThreadHandle;
815  PCONTEXT ThreadContext;
816  } input = { ThreadHandle, ThreadContext };
817 
818  return KphpDeviceIoControl(
820  &input,
821  sizeof(input)
822  );
823 }
824 
826  _In_ HANDLE ThreadHandle,
827  _In_ PCONTEXT ThreadContext
828  )
829 {
830  struct
831  {
832  HANDLE ThreadHandle;
833  PCONTEXT ThreadContext;
834  } input = { ThreadHandle, ThreadContext };
835 
836  return KphpDeviceIoControl(
838  &input,
839  sizeof(input)
840  );
841 }
842 
844  _In_ HANDLE ThreadHandle,
845  _In_ ULONG FramesToSkip,
846  _In_ ULONG FramesToCapture,
847  _Out_writes_(FramesToCapture) PVOID *BackTrace,
848  _Out_opt_ PULONG CapturedFrames,
849  _Out_opt_ PULONG BackTraceHash
850  )
851 {
852  struct
853  {
854  HANDLE ThreadHandle;
855  ULONG FramesToSkip;
856  ULONG FramesToCapture;
857  PVOID *BackTrace;
858  PULONG CapturedFrames;
859  PULONG BackTraceHash;
860  } input = { ThreadHandle, FramesToSkip, FramesToCapture, BackTrace, CapturedFrames, BackTraceHash };
861 
862  return KphpDeviceIoControl(
864  &input,
865  sizeof(input)
866  );
867 }
868 
870  _In_ HANDLE ThreadHandle,
871  _In_ KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
872  _Out_writes_bytes_(ThreadInformationLength) PVOID ThreadInformation,
873  _In_ ULONG ThreadInformationLength,
874  _Out_opt_ PULONG ReturnLength
875  )
876 {
877  struct
878  {
879  HANDLE ThreadHandle;
880  KPH_THREAD_INFORMATION_CLASS ThreadInformationClass;
881  PVOID ThreadInformation;
882  ULONG ThreadInformationLength;
883  PULONG ReturnLength;
884  } input = { ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength, ReturnLength };
885 
886  return KphpDeviceIoControl(
888  &input,
889  sizeof(input)
890  );
891 }
892 
894  _In_ HANDLE ThreadHandle,
895  _In_ KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
896  _In_reads_bytes_(ThreadInformationLength) PVOID ThreadInformation,
897  _In_ ULONG ThreadInformationLength
898  )
899 {
900  struct
901  {
902  HANDLE ThreadHandle;
903  KPH_THREAD_INFORMATION_CLASS ThreadInformationClass;
904  PVOID ThreadInformation;
905  ULONG ThreadInformationLength;
906  } input = { ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength };
907 
908  return KphpDeviceIoControl(
910  &input,
911  sizeof(input)
912  );
913 }
914 
916  _In_ HANDLE ProcessHandle,
917  _Out_writes_bytes_(BufferLength) PVOID Buffer,
918  _In_opt_ ULONG BufferLength,
919  _Out_opt_ PULONG ReturnLength
920  )
921 {
922  struct
923  {
924  HANDLE ProcessHandle;
925  PVOID Buffer;
926  ULONG BufferLength;
927  PULONG ReturnLength;
928  } input = { ProcessHandle, Buffer, BufferLength, ReturnLength };
929 
930  return KphpDeviceIoControl(
932  &input,
933  sizeof(input)
934  );
935 }
936 
938  _In_ HANDLE ProcessHandle,
939  _Out_ PKPH_PROCESS_HANDLE_INFORMATION *Handles
940  )
941 {
942  NTSTATUS status;
943  PVOID buffer;
944  ULONG bufferSize = 2048;
945 
946  buffer = PhAllocate(bufferSize);
947 
948  while (TRUE)
949  {
951  ProcessHandle,
952  buffer,
953  bufferSize,
954  &bufferSize
955  );
956 
957  if (status == STATUS_BUFFER_TOO_SMALL)
958  {
959  PhFree(buffer);
960  buffer = PhAllocate(bufferSize);
961  }
962  else
963  {
964  break;
965  }
966  }
967 
968  if (!NT_SUCCESS(status))
969  {
970  PhFree(buffer);
971  return status;
972  }
973 
974  *Handles = buffer;
975 
976  return status;
977 }
978 
980  _In_ HANDLE ProcessHandle,
981  _In_ HANDLE Handle,
982  _In_ KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass,
983  _Out_writes_bytes_(ObjectInformationLength) PVOID ObjectInformation,
984  _In_ ULONG ObjectInformationLength,
985  _Out_opt_ PULONG ReturnLength
986  )
987 {
988  struct
989  {
990  HANDLE ProcessHandle;
991  HANDLE Handle;
992  KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass;
993  PVOID ObjectInformation;
994  ULONG ObjectInformationLength;
995  PULONG ReturnLength;
996  } input = { ProcessHandle, Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength };
997 
998  return KphpDeviceIoControl(
1000  &input,
1001  sizeof(input)
1002  );
1003 }
1004 
1006  _In_ HANDLE ProcessHandle,
1007  _In_ HANDLE Handle,
1008  _In_ KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass,
1009  _In_reads_bytes_(ObjectInformationLength) PVOID ObjectInformation,
1010  _In_ ULONG ObjectInformationLength
1011  )
1012 {
1013  struct
1014  {
1015  HANDLE ProcessHandle;
1016  HANDLE Handle;
1017  KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass;
1018  PVOID ObjectInformation;
1019  ULONG ObjectInformationLength;
1020  } input = { ProcessHandle, Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength };
1021 
1022  return KphpDeviceIoControl(
1024  &input,
1025  sizeof(input)
1026  );
1027 }
1028 
1030  _In_ HANDLE SourceProcessHandle,
1031  _In_ HANDLE SourceHandle,
1032  _In_opt_ HANDLE TargetProcessHandle,
1033  _Out_opt_ PHANDLE TargetHandle,
1034  _In_ ACCESS_MASK DesiredAccess,
1035  _In_ ULONG HandleAttributes,
1036  _In_ ULONG Options
1037  )
1038 {
1039  NTSTATUS status;
1040  struct
1041  {
1042  HANDLE SourceProcessHandle;
1043  HANDLE SourceHandle;
1044  HANDLE TargetProcessHandle;
1045  PHANDLE TargetHandle;
1046  ACCESS_MASK DesiredAccess;
1047  ULONG HandleAttributes;
1048  ULONG Options;
1049  } input = { SourceProcessHandle, SourceHandle, TargetProcessHandle, TargetHandle, DesiredAccess, HandleAttributes, Options };
1050 
1051  status = KphpDeviceIoControl(
1053  &input,
1054  sizeof(input)
1055  );
1056 
1057  if (status == STATUS_CANT_TERMINATE_SELF)
1058  {
1059  // We tried to close a handle in the current process.
1060  if (Options & DUPLICATE_CLOSE_SOURCE)
1061  status = NtClose(SourceHandle);
1062  }
1063 
1064  return status;
1065 }
1066 
1067 NTSTATUS KphOpenDriver(
1068  _Out_ PHANDLE DriverHandle,
1069  _In_ POBJECT_ATTRIBUTES ObjectAttributes
1070  )
1071 {
1072  struct
1073  {
1074  PHANDLE DriverHandle;
1075  POBJECT_ATTRIBUTES ObjectAttributes;
1076  } input = { DriverHandle, ObjectAttributes };
1077 
1078  return KphpDeviceIoControl(
1080  &input,
1081  sizeof(input)
1082  );
1083 }
1084 
1086  _In_ HANDLE DriverHandle,
1087  _In_ DRIVER_INFORMATION_CLASS DriverInformationClass,
1088  _Out_writes_bytes_(DriverInformationLength) PVOID DriverInformation,
1089  _In_ ULONG DriverInformationLength,
1090  _Out_opt_ PULONG ReturnLength
1091  )
1092 {
1093  struct
1094  {
1095  HANDLE DriverHandle;
1096  DRIVER_INFORMATION_CLASS DriverInformationClass;
1097  PVOID DriverInformation;
1098  ULONG DriverInformationLength;
1099  PULONG ReturnLength;
1100  } input = { DriverHandle, DriverInformationClass, DriverInformation, DriverInformationLength, ReturnLength };
1101 
1102  return KphpDeviceIoControl(
1104  &input,
1105  sizeof(input)
1106  );
1107 }