Driver: PsTree: Fix copying info from user-mode process

This commit is contained in:
Nodir Temirkhodjaev 2022-02-10 01:09:26 +03:00
parent 9d6ad0a137
commit 3725b62b1f

View File

@ -107,6 +107,10 @@ NTSTATUS NTAPI ZwQuerySystemInformation(ULONG systemInformationClass, PVOID syst
NTSTATUS NTAPI ZwQueryInformationProcess(HANDLE processHandle, ULONG processInformationClass, NTSTATUS NTAPI ZwQueryInformationProcess(HANDLE processHandle, ULONG processInformationClass,
PVOID processInformation, ULONG processInformationLength, PULONG returnLength); PVOID processInformation, ULONG processInformationLength, PULONG returnLength);
NTSTATUS NTAPI MmCopyVirtualMemory(PEPROCESS sourceProcess, PVOID sourceAddress,
PEPROCESS targetProcess, PVOID targetAddress, SIZE_T bufferSize,
KPROCESSOR_MODE previousMode, PSIZE_T returnSize);
#endif #endif
#define fort_pstree_get_proc(ps_tree, index) \ #define fort_pstree_get_proc(ps_tree, index) \
@ -424,7 +428,31 @@ static PWCHAR GetUnicodeStringBuffer(PCUNICODE_STRING string, PRTL_USER_PROCESS_
return string->Buffer; return string->Buffer;
} }
static NTSTATUS GetCurrentProcessPathArgs(PUNICODE_STRING path, PUNICODE_STRING commandLine) static NTSTATUS ReadProcessMemoryBuffer(
PEPROCESS process, PVOID processData, PVOID out, USHORT size)
{
SIZE_T outLength = 0;
const NTSTATUS status = MmCopyVirtualMemory(
process, processData, IoGetCurrentProcess(), out, size, KernelMode, &outLength);
if (!NT_SUCCESS(status))
return status;
return (size == outLength) ? STATUS_SUCCESS : STATUS_INVALID_BUFFER_SIZE;
}
static NTSTATUS ReadProcessStringBuffer(
PEPROCESS process, PVOID processData, PUNICODE_STRING out, USHORT size)
{
const NTSTATUS status = ReadProcessMemoryBuffer(process, processData, out->Buffer, size);
if (NT_SUCCESS(status)) {
out->Buffer[size / sizeof(WCHAR)] = L'\0';
out->Length = (USHORT) size;
}
return status;
}
static NTSTATUS GetProcessPathArgs(
PEPROCESS process, PUNICODE_STRING path, PUNICODE_STRING commandLine)
{ {
NTSTATUS status; NTSTATUS status;
@ -437,24 +465,25 @@ static NTSTATUS GetCurrentProcessPathArgs(PUNICODE_STRING path, PUNICODE_STRING
if (procBasicInfo.PebBaseAddress == NULL) if (procBasicInfo.PebBaseAddress == NULL)
return STATUS_INVALID_ADDRESS; return STATUS_INVALID_ADDRESS;
PRTL_USER_PROCESS_PARAMETERS params = procBasicInfo.PebBaseAddress->ProcessParameters; PEB peb;
status = ReadProcessMemoryBuffer(process, procBasicInfo.PebBaseAddress, &peb, sizeof(PEB));
if (!NT_SUCCESS(status))
return status;
PRTL_USER_PROCESS_PARAMETERS params = peb.ProcessParameters;
if (params == NULL) if (params == NULL)
return STATUS_INVALID_ADDRESS; return STATUS_INVALID_ADDRESS;
const USHORT pathLength = params->ImagePathName.Length; const USHORT pathLength = params->ImagePathName.Length;
if (pathLength != 0 && pathLength <= path->MaximumLength - sizeof(WCHAR)) { if (pathLength != 0 && pathLength <= path->MaximumLength - sizeof(WCHAR)) {
PCWCHAR userBuffer = GetUnicodeStringBuffer(&params->ImagePathName, params); PVOID userBuffer = (PVOID) GetUnicodeStringBuffer(&params->ImagePathName, params);
RtlCopyMemory(path->Buffer, userBuffer, pathLength); ReadProcessStringBuffer(process, userBuffer, path, pathLength);
path->Buffer[pathLength / sizeof(WCHAR)] = L'\0';
path->Length = pathLength;
} }
const USHORT commandLineLength = params->CommandLine.Length; const USHORT commandLineLength = params->CommandLine.Length;
if (commandLineLength != 0 && commandLineLength <= commandLine->MaximumLength - sizeof(WCHAR)) { if (commandLineLength != 0 && commandLineLength <= commandLine->MaximumLength - sizeof(WCHAR)) {
PCWCHAR userBuffer = GetUnicodeStringBuffer(&params->CommandLine, params); PVOID userBuffer = (PVOID) GetUnicodeStringBuffer(&params->CommandLine, params);
RtlCopyMemory(commandLine->Buffer, userBuffer, commandLineLength); ReadProcessStringBuffer(process, userBuffer, commandLine, commandLineLength);
commandLine->Buffer[commandLineLength / sizeof(WCHAR)] = L'\0';
commandLine->Length = commandLineLength;
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -464,7 +493,7 @@ static void fort_pstree_attach_process(PSYSTEM_PROCESSES processEntry, HANDLE pr
{ {
NTSTATUS status; NTSTATUS status;
PRKPROCESS process; PEPROCESS process;
status = ObReferenceObjectByHandle( status = ObReferenceObjectByHandle(
processHandle, 0, *PsProcessType, KernelMode, (PVOID *) &process, NULL); processHandle, 0, *PsProcessType, KernelMode, (PVOID *) &process, NULL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
@ -486,7 +515,7 @@ static void fort_pstree_attach_process(PSYSTEM_PROCESSES processEntry, HANDLE pr
KAPC_STATE apcState; KAPC_STATE apcState;
KeStackAttachProcess(process, &apcState); KeStackAttachProcess(process, &apcState);
{ {
status = GetCurrentProcessPathArgs(&path, &commandLine); status = GetProcessPathArgs(process, &path, &commandLine);
} }
KeUnstackDetachProcess(&apcState); KeUnstackDetachProcess(&apcState);
@ -495,7 +524,10 @@ static void fort_pstree_attach_process(PSYSTEM_PROCESSES processEntry, HANDLE pr
// Process the info // Process the info
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
LOG("PsTree: Query Process Error: pid=%d %x\n", processEntry->ProcessId, status); LOG("PsTree: Query Process Error: pid=%d %x\n", processEntry->ProcessId, status);
} else if (path.Length != 0 && commandLine.Length != 0) { return;
}
if (path.Length != 0 && commandLine.Length != 0) {
const HANDLE processId = (HANDLE) (ptrdiff_t) processEntry->ProcessId; const HANDLE processId = (HANDLE) (ptrdiff_t) processEntry->ProcessId;
const HANDLE parentProcessId = (HANDLE) (ptrdiff_t) processEntry->ParentProcessId; const HANDLE parentProcessId = (HANDLE) (ptrdiff_t) processEntry->ParentProcessId;