Correct the 'cwd' and 'root' columns of processes table on Windows (#6459)

Correct the 'cwd' and 'root' columns of processes table on Windows
This commit is contained in:
Mike Myers 2020-05-26 11:29:49 -07:00 committed by GitHub
parent d1feab7bf2
commit 8a9fb0558e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -86,8 +86,18 @@ typedef struct {
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StdInputHandle;
HANDLE StdOutputHandle;
HANDLE StdErrorHandle;
UNICODE_STRING CurrentDirectoryPath;
HANDLE CurrentDirectoryHandle;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
@ -218,10 +228,10 @@ Status getProcList(std::set<long>& pids) {
return Status::success();
}
/// For legacy systems, we retrieve the commandline from the PEB
Status getProcessCommandLineLegacy(HANDLE proc,
std::string& out,
const unsigned long pid) {
/// Helper function for getting the User Process Parameters from the PEB
Status getUserProcessParameters(HANDLE proc,
RTL_USER_PROCESS_PARAMETERS& out,
const unsigned long pid) {
PROCESS_BASIC_INFORMATION pbi;
unsigned long len{0};
NTSTATUS status = NtQueryInformationProcess(
@ -242,13 +252,28 @@ Status getProcessCommandLineLegacy(HANDLE proc,
" with " + std::to_string(status));
}
RTL_USER_PROCESS_PARAMETERS upp;
if (!ReadProcessMemory(
proc, peb.ProcessParameters, &upp, sizeof(upp), &bytes_read)) {
proc, peb.ProcessParameters, &out, sizeof(out), &bytes_read)) {
return Status::failure("Reading USER_PROCESS_PARAMETERS failed for " +
std::to_string(pid));
}
return Status::success();
}
/// For legacy systems, we retrieve the commandline from the PEB
Status getProcessCommandLineLegacy(HANDLE proc,
std::string& out,
const unsigned long pid) {
RTL_USER_PROCESS_PARAMETERS upp;
auto s = getUserProcessParameters(proc, upp, pid);
if (!s.ok()) {
LOG(INFO) << "Failed to get PEB UPP for " << pid << " with "
<< GetLastError();
return s;
}
size_t bytes_read = 0;
std::vector<wchar_t> command_line(kMaxPathSize, 0x0);
SecureZeroMemory(command_line.data(), kMaxPathSize);
if (!ReadProcessMemory(proc,
@ -301,6 +326,34 @@ Status getProcessCommandLine(HANDLE& proc,
return Status::success();
}
// Regardless of the Windows version, the CWD of a process is only possible to
// retrieve by reading it from the process's PEB structure.
Status getProcessCurrentDirectory(HANDLE proc,
std::string& out,
const unsigned long pid) {
RTL_USER_PROCESS_PARAMETERS upp;
auto s = getUserProcessParameters(proc, upp, pid);
if (!s.ok()) {
LOG(INFO) << "Failed to get PEB UPP for " << pid << " with "
<< GetLastError();
return s;
}
size_t bytes_read = 0;
std::vector<wchar_t> current_directory(kMaxPathSize, 0x0);
SecureZeroMemory(current_directory.data(), kMaxPathSize);
if (!ReadProcessMemory(proc,
upp.CurrentDirectoryPath.Buffer,
current_directory.data(),
upp.CurrentDirectoryPath.Length,
&bytes_read)) {
return Status::failure("Failed to read current working directory for " +
std::to_string(pid));
}
out = wstringToString(current_directory.data());
return Status::success();
}
void getProcessPathInfo(HANDLE& proc,
const unsigned long pid,
DynamicTableRowHolder& r) {
@ -320,18 +373,12 @@ void getProcessPathInfo(HANDLE& proc,
boost_path.empty() ? -1 : osquery::pathExists(path.data()).ok());
}
path.clear();
path.resize(kMaxPathSize, 0x0);
if (pid == GetCurrentProcessId()) {
ret = GetModuleFileNameW(nullptr, path.data(), kMaxPathSize);
} else {
ret = GetModuleFileNameExW(proc, nullptr, path.data(), kMaxPathSize);
}
if (ret == FALSE) {
std::string currDir{""};
auto s = getProcessCurrentDirectory(proc, currDir, pid);
if (!s.ok()) {
LOG(INFO) << "Failed to get cwd for " << pid << " with " << GetLastError();
} else {
r["cwd"] = SQL_TEXT(wstringToString(path.data()));
r["cwd"] = SQL_TEXT(currDir);
}
r["root"] = r["cwd"];
}