Skip to content

Commit 285e4c0

Browse files
committed
Add KProcessHacker hashing and verification code
1 parent bb5a00d commit 285e4c0

File tree

10 files changed

+540
-214
lines changed

10 files changed

+540
-214
lines changed

KProcessHacker/devctrl.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,16 @@ NTSTATUS KphDispatchDeviceControl(
5353
ioControlCode = stackLocation->Parameters.DeviceIoControl.IoControlCode;
5454
accessMode = Irp->RequestorMode;
5555

56-
// Make sure we actually have input if the input length
57-
// is non-zero.
56+
// Make sure we actually have input if the input length is non-zero.
5857
if (inputLength != 0 && !originalInput)
5958
{
6059
status = STATUS_INVALID_BUFFER_SIZE;
6160
goto ControlEnd;
6261
}
6362

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.
63+
// Make sure the caller isn't giving us a huge buffer. If they are, it can't be correct because
64+
// we have a compile-time check that makes sure our buffer can store the arguments for all the
65+
// calls.
6866
if (inputLength > sizeof(capturedInput))
6967
{
7068
status = STATUS_INVALID_BUFFER_SIZE;
@@ -116,6 +114,7 @@ NTSTATUS KphDispatchDeviceControl(
116114
PHANDLE ProcessHandle;
117115
ACCESS_MASK DesiredAccess;
118116
PCLIENT_ID ClientId;
117+
ULONGLONG Key;
119118
} *input = capturedInputPointer;
120119

121120
VERIFY_INPUT_LENGTH;
@@ -124,6 +123,7 @@ NTSTATUS KphDispatchDeviceControl(
124123
input->ProcessHandle,
125124
input->DesiredAccess,
126125
input->ClientId,
126+
input->Key,
127127
accessMode
128128
);
129129
}
@@ -153,13 +153,15 @@ NTSTATUS KphDispatchDeviceControl(
153153
{
154154
HANDLE ProcessHandle;
155155
NTSTATUS ExitStatus;
156+
ULONGLONG Key;
156157
} *input = capturedInputPointer;
157158

158159
VERIFY_INPUT_LENGTH;
159160

160161
status = KpiTerminateProcess(
161162
input->ProcessHandle,
162163
input->ExitStatus,
164+
input->Key,
163165
accessMode
164166
);
165167
}
@@ -173,6 +175,7 @@ NTSTATUS KphDispatchDeviceControl(
173175
PVOID Buffer;
174176
SIZE_T BufferSize;
175177
PSIZE_T NumberOfBytesRead;
178+
ULONGLONG Key;
176179
} *input = capturedInputPointer;
177180

178181
VERIFY_INPUT_LENGTH;
@@ -183,6 +186,7 @@ NTSTATUS KphDispatchDeviceControl(
183186
input->Buffer,
184187
input->BufferSize,
185188
input->NumberOfBytesRead,
189+
input->Key,
186190
accessMode
187191
);
188192
}
@@ -238,6 +242,7 @@ NTSTATUS KphDispatchDeviceControl(
238242
PHANDLE ThreadHandle;
239243
ACCESS_MASK DesiredAccess;
240244
PCLIENT_ID ClientId;
245+
ULONGLONG Key;
241246
} *input = capturedInputPointer;
242247

243248
VERIFY_INPUT_LENGTH;
@@ -246,6 +251,7 @@ NTSTATUS KphDispatchDeviceControl(
246251
input->ThreadHandle,
247252
input->DesiredAccess,
248253
input->ClientId,
254+
input->Key,
249255
accessMode
250256
);
251257
}

KProcessHacker/include/kph.h

Lines changed: 49 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define PHNT_MODE PHNT_MODE_KERNEL
66
#include <phnt.h>
77
#include <ntfill.h>
8+
#include <bcrypt.h>
89
#include <kphapi.h>
910

1011
// Debugging
@@ -15,6 +16,16 @@
1516
#define dprintf
1617
#endif
1718

19+
typedef struct _KPH_CLIENT
20+
{
21+
// Validated process image address range
22+
PVOID ValidatedRangeStart;
23+
SIZE_T ValidatedRangeSize;
24+
// Level 1 and 2 secret keys
25+
ULONGLONG L1Key;
26+
ULONGLONG L2Key;
27+
} KPH_CLIENT, *PKPH_CLIENT;
28+
1829
typedef struct _KPH_PARAMETERS
1930
{
2031
KPH_SECURITY_LEVEL SecurityLevel;
@@ -30,15 +41,6 @@ NTSTATUS KpiGetFeatures(
3041
__in KPROCESSOR_MODE AccessMode
3142
);
3243

33-
NTSTATUS KphEnumerateSystemModules(
34-
__out PRTL_PROCESS_MODULES *Modules
35-
);
36-
37-
NTSTATUS KphValidateAddressForSystemModules(
38-
__in PVOID Address,
39-
__in SIZE_T Length
40-
);
41-
4244
// devctrl
4345

4446
__drv_dispatchType(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH KphDispatchDeviceControl;
@@ -137,6 +139,7 @@ NTSTATUS KpiOpenProcess(
137139
__out PHANDLE ProcessHandle,
138140
__in ACCESS_MASK DesiredAccess,
139141
__in PCLIENT_ID ClientId,
142+
__in_opt ULONGLONG Key,
140143
__in KPROCESSOR_MODE AccessMode
141144
);
142145

@@ -150,6 +153,7 @@ NTSTATUS KpiOpenProcessJob(
150153
NTSTATUS KpiTerminateProcess(
151154
__in HANDLE ProcessHandle,
152155
__in NTSTATUS ExitStatus,
156+
__in_opt ULONGLONG Key,
153157
__in KPROCESSOR_MODE AccessMode
154158
);
155159

@@ -201,6 +205,7 @@ NTSTATUS KpiOpenThread(
201205
__out PHANDLE ThreadHandle,
202206
__in ACCESS_MASK DesiredAccess,
203207
__in PCLIENT_ID ClientId,
208+
__in_opt ULONGLONG Key,
204209
__in KPROCESSOR_MODE AccessMode
205210
);
206211

@@ -256,6 +261,40 @@ NTSTATUS KpiSetInformationThread(
256261
__in KPROCESSOR_MODE AccessMode
257262
);
258263

264+
// util
265+
266+
VOID KphFreeCapturedUnicodeString(
267+
__in PUNICODE_STRING CapturedUnicodeString
268+
);
269+
270+
NTSTATUS KphCaptureUnicodeString(
271+
__in PUNICODE_STRING UnicodeString,
272+
__out PUNICODE_STRING CapturedUnicodeString
273+
);
274+
275+
NTSTATUS KphEnumerateSystemModules(
276+
__out PRTL_PROCESS_MODULES *Modules
277+
);
278+
279+
NTSTATUS KphValidateAddressForSystemModules(
280+
__in PVOID Address,
281+
__in SIZE_T Length
282+
);
283+
284+
// verify
285+
286+
NTSTATUS KphHashFile(
287+
__in PUNICODE_STRING FileName,
288+
__out PVOID *Hash,
289+
__out PULONG HashSize
290+
);
291+
292+
NTSTATUS KphVerifyFile(
293+
__in PUNICODE_STRING FileName,
294+
__in_bcount(SignatureSize) PVOID Signature,
295+
__in ULONG SignatureSize
296+
);
297+
259298
// vm
260299

261300
NTSTATUS KphCopyVirtualMemory(
@@ -274,76 +313,8 @@ NTSTATUS KpiReadVirtualMemoryUnsafe(
274313
__out_bcount(BufferSize) PVOID Buffer,
275314
__in SIZE_T BufferSize,
276315
__out_opt PSIZE_T NumberOfBytesRead,
316+
__in_opt ULONGLONG Key,
277317
__in KPROCESSOR_MODE AccessMode
278318
);
279319

280-
// Inline support functions
281-
282-
FORCEINLINE VOID KphFreeCapturedUnicodeString(
283-
__in PUNICODE_STRING CapturedUnicodeString
284-
)
285-
{
286-
if (CapturedUnicodeString->Buffer)
287-
ExFreePoolWithTag(CapturedUnicodeString->Buffer, 'UhpK');
288-
}
289-
290-
FORCEINLINE NTSTATUS KphCaptureUnicodeString(
291-
__in PUNICODE_STRING UnicodeString,
292-
__out PUNICODE_STRING CapturedUnicodeString
293-
)
294-
{
295-
UNICODE_STRING unicodeString;
296-
PWSTR userBuffer;
297-
298-
__try
299-
{
300-
ProbeForRead(UnicodeString, sizeof(UNICODE_STRING), sizeof(ULONG));
301-
unicodeString.Length = UnicodeString->Length;
302-
unicodeString.MaximumLength = unicodeString.Length;
303-
unicodeString.Buffer = NULL;
304-
305-
userBuffer = UnicodeString->Buffer;
306-
ProbeForRead(userBuffer, unicodeString.Length, sizeof(WCHAR));
307-
}
308-
__except (EXCEPTION_EXECUTE_HANDLER)
309-
{
310-
return GetExceptionCode();
311-
}
312-
313-
if (unicodeString.Length & 1)
314-
{
315-
return STATUS_INVALID_PARAMETER;
316-
}
317-
318-
if (unicodeString.Length != 0)
319-
{
320-
unicodeString.Buffer = ExAllocatePoolWithTag(
321-
PagedPool,
322-
unicodeString.Length,
323-
'UhpK'
324-
);
325-
326-
if (!unicodeString.Buffer)
327-
return STATUS_INSUFFICIENT_RESOURCES;
328-
329-
__try
330-
{
331-
memcpy(
332-
unicodeString.Buffer,
333-
userBuffer,
334-
unicodeString.Length
335-
);
336-
}
337-
__except (EXCEPTION_EXECUTE_HANDLER)
338-
{
339-
KphFreeCapturedUnicodeString(&unicodeString);
340-
return GetExceptionCode();
341-
}
342-
}
343-
344-
*CapturedUnicodeString = unicodeString;
345-
346-
return STATUS_SUCCESS;
347-
}
348-
349320
#endif

KProcessHacker/main.c

Lines changed: 0 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -302,105 +302,3 @@ NTSTATUS KpiGetFeatures(
302302

303303
return STATUS_SUCCESS;
304304
}
305-
306-
/**
307-
* Enumerates the modules loaded by the kernel.
308-
*
309-
* \param Modules A variable which receives a pointer
310-
* to a structure containing information about
311-
* the kernel modules. The structure must be freed with
312-
* the tag 'ThpK'.
313-
*/
314-
NTSTATUS KphEnumerateSystemModules(
315-
__out PRTL_PROCESS_MODULES *Modules
316-
)
317-
{
318-
NTSTATUS status;
319-
PVOID buffer;
320-
ULONG bufferSize;
321-
ULONG attempts;
322-
323-
bufferSize = 2048;
324-
attempts = 8;
325-
326-
do
327-
{
328-
buffer = ExAllocatePoolWithTag(PagedPool, bufferSize, 'ThpK');
329-
330-
if (!buffer)
331-
{
332-
status = STATUS_INSUFFICIENT_RESOURCES;
333-
break;
334-
}
335-
336-
status = ZwQuerySystemInformation(
337-
SystemModuleInformation,
338-
buffer,
339-
bufferSize,
340-
&bufferSize
341-
);
342-
343-
if (NT_SUCCESS(status))
344-
{
345-
*Modules = buffer;
346-
347-
return status;
348-
}
349-
350-
ExFreePoolWithTag(buffer, 'ThpK');
351-
352-
if (status != STATUS_INFO_LENGTH_MISMATCH)
353-
{
354-
break;
355-
}
356-
} while (--attempts);
357-
358-
return status;
359-
}
360-
361-
/**
362-
* Checks if an address range lies within a kernel module.
363-
*
364-
* \param Address The beginning of the address range.
365-
* \param Length The number of bytes in the address range.
366-
*/
367-
NTSTATUS KphValidateAddressForSystemModules(
368-
__in PVOID Address,
369-
__in SIZE_T Length
370-
)
371-
{
372-
NTSTATUS status;
373-
PRTL_PROCESS_MODULES modules;
374-
ULONG i;
375-
BOOLEAN valid;
376-
377-
status = KphEnumerateSystemModules(&modules);
378-
379-
if (!NT_SUCCESS(status))
380-
return status;
381-
382-
valid = FALSE;
383-
384-
for (i = 0; i < modules->NumberOfModules; i++)
385-
{
386-
if (
387-
(ULONG_PTR)Address + Length >= (ULONG_PTR)Address &&
388-
(ULONG_PTR)Address >= (ULONG_PTR)modules->Modules[i].ImageBase &&
389-
(ULONG_PTR)Address + Length <= (ULONG_PTR)modules->Modules[i].ImageBase + modules->Modules[i].ImageSize
390-
)
391-
{
392-
dprintf("Validated address 0x%Ix in %s\n", Address, modules->Modules[i].FullPathName);
393-
valid = TRUE;
394-
break;
395-
}
396-
}
397-
398-
ExFreePoolWithTag(modules, 'ThpK');
399-
400-
if (valid)
401-
status = STATUS_SUCCESS;
402-
else
403-
status = STATUS_ACCESS_VIOLATION;
404-
405-
return status;
406-
}

0 commit comments

Comments
 (0)