osquery-1/osquery/core/windows/process_ops.cpp

231 lines
6.7 KiB
C++

/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#define _WIN32_DCOM
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// clang-format off
#include <LM.h>
// clang-format on
#include <vector>
#include <osquery/system.h>
#include <osquery/logger.h>
#include "osquery/core/process.h"
#include "osquery/core/windows/wmi.h"
namespace osquery {
std::string psidToString(PSID sid) {
LPTSTR sidOut = nullptr;
auto ret = ConvertSidToStringSidA(sid, &sidOut);
if (ret == 0) {
VLOG(1) << "ConvertSidToString failed with " << GetLastError();
return std::string("");
}
return std::string(sidOut);
}
int getUidFromSid(PSID sid) {
auto eUse = SidTypeUnknown;
unsigned long unameSize = 0;
unsigned long domNameSize = 1;
// LookupAccountSid first gets the size of the username buff required.
LookupAccountSidW(
nullptr, sid, nullptr, &unameSize, nullptr, &domNameSize, &eUse);
std::vector<wchar_t> uname(unameSize);
std::vector<wchar_t> domName(domNameSize);
auto ret = LookupAccountSidW(nullptr,
sid,
uname.data(),
&unameSize,
domName.data(),
&domNameSize,
&eUse);
if (ret == 0) {
return -1;
}
// USER_INFO_3 struct contains the RID (uid) of our user
unsigned long userInfoLevel = 3;
unsigned char* userBuff = nullptr;
ret = NetUserGetInfo(nullptr, uname.data(), userInfoLevel, &userBuff);
if (ret != NERR_Success || userBuff == nullptr) {
return -1;
}
auto uid = LPUSER_INFO_3(userBuff)->usri3_user_id;
NetApiBufferFree(userBuff);
return uid;
}
int getGidFromSid(PSID sid) {
auto eUse = SidTypeUnknown;
unsigned long unameSize = 0;
unsigned long domNameSize = 1;
// LookupAccountSid first gets the size of the username buff required.
LookupAccountSidW(
nullptr, sid, nullptr, &unameSize, nullptr, &domNameSize, &eUse);
std::vector<wchar_t> uname(unameSize);
std::vector<wchar_t> domName(domNameSize);
auto ret = LookupAccountSidW(nullptr,
sid,
uname.data(),
&unameSize,
domName.data(),
&domNameSize,
&eUse);
if (ret == 0) {
return -1;
}
// USER_INFO_3 struct contains the RID (uid) of our user
unsigned long userInfoLevel = 3;
unsigned char* userBuff = nullptr;
ret = NetUserGetInfo(nullptr, uname.data(), userInfoLevel, &userBuff);
if (ret != NERR_Success || userBuff == nullptr) {
return -1;
}
auto gid = LPUSER_INFO_3(userBuff)->usri3_primary_group_id;
NetApiBufferFree(userBuff);
return gid;
}
int platformGetUid() {
auto token = INVALID_HANDLE_VALUE;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token)) {
return -1;
}
unsigned long nbytes = 0;
::GetTokenInformation(token, TokenUser, nullptr, 0, &nbytes);
if (nbytes == 0) {
::CloseHandle(token);
return -1;
}
std::vector<char> tu_buffer;
tu_buffer.assign(nbytes, '\0');
auto status = ::GetTokenInformation(token,
TokenUser,
tu_buffer.data(),
static_cast<DWORD>(tu_buffer.size()),
&nbytes);
::CloseHandle(token);
if (status == 0) {
return -1;
}
auto tu = PTOKEN_USER(tu_buffer.data());
return getUidFromSid(tu->User.Sid);
}
bool isLauncherProcessDead(PlatformProcess& launcher) {
unsigned long code = 0;
if (!::GetExitCodeProcess(launcher.nativeHandle(), &code)) {
LOG(WARNING) << "GetExitCodeProcess did not return a value, error code ("
<< GetLastError() << ")";
return false;
}
return (code != STILL_ACTIVE);
}
bool setEnvVar(const std::string& name, const std::string& value) {
return (::SetEnvironmentVariableA(name.c_str(), value.c_str()) == TRUE);
}
bool unsetEnvVar(const std::string& name) {
return (::SetEnvironmentVariableA(name.c_str(), nullptr) == TRUE);
}
boost::optional<std::string> getEnvVar(const std::string& name) {
const auto kInitialBufferSize = 1024;
std::vector<char> buf;
buf.assign(kInitialBufferSize, '\0');
auto value_len =
::GetEnvironmentVariableA(name.c_str(), buf.data(), kInitialBufferSize);
if (value_len == 0) {
VLOG(1) << "Unable to find environment variable (" << GetLastError()
<< "): " << name;
return boost::none;
}
// It is always possible that between the first GetEnvironmentVariableA call
// and this one, a change was made to our target environment variable that
// altered the size. Currently, we ignore this scenario and fail if the
// returned size is greater than what we expect.
if (value_len > kInitialBufferSize) {
buf.assign(value_len, '\0');
value_len = ::GetEnvironmentVariableA(name.c_str(), buf.data(), value_len);
if (value_len == 0 || value_len > buf.size()) {
// The size returned is greater than the size we expected. Currently, we
// will not deal with this scenario and just return as if an error has
// occurred.
return boost::none;
}
}
return std::string(buf.data(), value_len);
}
ModuleHandle platformModuleOpen(const std::string& path) {
return ::LoadLibraryA(path.c_str());
}
void* platformModuleGetSymbol(ModuleHandle module, const std::string& symbol) {
return ::GetProcAddress(static_cast<HMODULE>(module), symbol.c_str());
}
std::string platformModuleGetError() {
return std::string("GetLastError() = " + ::GetLastError());
}
bool platformModuleClose(ModuleHandle module) {
return (::FreeLibrary(static_cast<HMODULE>(module)) != 0);
}
void setToBackgroundPriority() {}
// Helper function to determine if thread is running with admin privilege.
bool isUserAdmin() {
HANDLE hToken = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
return false;
}
TOKEN_ELEVATION Elevation;
DWORD cbSize = sizeof(TOKEN_ELEVATION);
if (GetTokenInformation(
hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize) ==
0) {
CloseHandle(hToken);
return false;
}
if (hToken != nullptr) {
CloseHandle(hToken);
}
return Elevation.TokenIsElevated ? true : false;
}
int platformGetPid() {
return static_cast<int>(GetCurrentProcessId());
}
int platformGetTid() {
return static_cast<int>(GetCurrentThreadId());
}
}