2016-09-08 01:04:33 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <locale>
|
|
|
|
#include <string>
|
|
|
|
|
2016-09-26 18:08:57 +00:00
|
|
|
#include "osquery/core/windows/wmi.h"
|
2016-09-08 01:04:33 +00:00
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring stringToWstring(const std::string& src) {
|
2016-09-08 01:04:33 +00:00
|
|
|
std::wstring utf16le_str = converter.from_bytes(src);
|
|
|
|
return utf16le_str;
|
|
|
|
}
|
|
|
|
|
2016-09-25 01:18:40 +00:00
|
|
|
std::string wstringToString(const wchar_t* src) {
|
2016-09-08 01:04:33 +00:00
|
|
|
if (src == nullptr) {
|
|
|
|
return std::string("");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string utf8_str = converter.to_bytes(src);
|
|
|
|
return utf8_str;
|
|
|
|
}
|
|
|
|
|
2016-09-25 01:18:40 +00:00
|
|
|
std::string bstrToString(const BSTR src) {
|
|
|
|
return wstringToString(static_cast<const wchar_t*>(src));
|
2016-09-08 01:04:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WmiResultItem::WmiResultItem(WmiResultItem&& src) {
|
|
|
|
result_ = nullptr;
|
|
|
|
std::swap(result_, src.result_);
|
|
|
|
}
|
|
|
|
|
|
|
|
WmiResultItem::~WmiResultItem() {
|
|
|
|
if (result_ != nullptr) {
|
|
|
|
result_->Release();
|
|
|
|
result_ = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WmiResultItem::PrintType(const std::string& name) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
std::cerr << "Failed: " << name << "\n";
|
|
|
|
} else {
|
|
|
|
std::cout << "Name=" << name << ", Type=" << value.vt << "\n";
|
|
|
|
if (value.vt == VT_I4) {
|
|
|
|
std::cout << " Value=" << value.lVal << "\n";
|
|
|
|
} else if (value.vt == VT_BSTR) {
|
|
|
|
std::wcout << " Value=" << value.bstrVal << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VariantClear(&value);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status WmiResultItem::GetBool(const std::string& name, bool& ret) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_BOOL) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.boolVal == VARIANT_TRUE ? true : false;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
2016-10-12 16:01:32 +00:00
|
|
|
Status WmiResultItem::GetUChar(const std::string& name,
|
|
|
|
unsigned char& ret) const {
|
|
|
|
std::wstring property_name = stringToWstring(name);
|
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_UI1) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.bVal;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
2017-01-11 03:09:46 +00:00
|
|
|
Status WmiResultItem::GetUnsignedShort(const std::string& name,
|
|
|
|
unsigned short& ret) const {
|
|
|
|
std::wstring property_name = stringToWstring(name);
|
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_I4) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.uiVal;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status WmiResultItem::GetUnsignedInt32(const std::string& name,
|
|
|
|
unsigned int& ret) const {
|
|
|
|
std::wstring property_name = stringToWstring(name);
|
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_I4) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.uiVal;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
2016-09-08 01:04:33 +00:00
|
|
|
Status WmiResultItem::GetLong(const std::string& name, long& ret) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_I4) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.lVal;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status WmiResultItem::GetUnsignedLong(const std::string& name,
|
|
|
|
unsigned long& ret) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_UI4) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.lVal;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status WmiResultItem::GetLongLong(const std::string& name,
|
|
|
|
long long& ret) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_I8) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.lVal;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status WmiResultItem::GetUnsignedLongLong(const std::string& name,
|
|
|
|
unsigned long long& ret) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_UI8) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
ret = value.lVal;
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status WmiResultItem::GetString(const std::string& name,
|
|
|
|
std::string& ret) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
ret = "";
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != VT_BSTR) {
|
|
|
|
ret = "";
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
2016-09-25 01:18:40 +00:00
|
|
|
ret = bstrToString(value.bstrVal);
|
2016-09-08 01:04:33 +00:00
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status WmiResultItem::GetVectorOfStrings(const std::string& name,
|
|
|
|
std::vector<std::string>& ret) const {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring property_name = stringToWstring(name);
|
2016-09-08 01:04:33 +00:00
|
|
|
VARIANT value;
|
|
|
|
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
return Status(-1, "Error retrieving data from WMI query.");
|
|
|
|
}
|
|
|
|
if (value.vt != (VT_BSTR | VT_ARRAY)) {
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(-1, "Invalid data type returned.");
|
|
|
|
}
|
|
|
|
long lbound, ubound;
|
|
|
|
SafeArrayGetLBound(value.parray, 1, &lbound);
|
|
|
|
SafeArrayGetUBound(value.parray, 1, &ubound);
|
|
|
|
long count = ubound - lbound + 1;
|
|
|
|
|
|
|
|
BSTR* pData = nullptr;
|
|
|
|
SafeArrayAccessData(value.parray, (void**)&pData);
|
|
|
|
ret.reserve(count);
|
|
|
|
for (long i = 0; i < count; i++) {
|
2016-09-25 01:18:40 +00:00
|
|
|
ret.push_back(bstrToString(pData[i]));
|
2016-09-08 01:04:33 +00:00
|
|
|
}
|
|
|
|
SafeArrayUnaccessData(value.parray);
|
|
|
|
VariantClear(&value);
|
|
|
|
return Status(0);
|
|
|
|
}
|
|
|
|
|
2016-09-23 21:33:44 +00:00
|
|
|
WmiRequest::WmiRequest(const std::string& query, BSTR nspace) {
|
2016-09-25 01:18:40 +00:00
|
|
|
std::wstring wql = stringToWstring(query);
|
2016-09-08 01:04:33 +00:00
|
|
|
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
|
|
|
|
hr = ::CoInitializeSecurity(nullptr,
|
|
|
|
-1,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
RPC_C_AUTHN_LEVEL_DEFAULT,
|
|
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
|
|
nullptr,
|
|
|
|
EOAC_NONE,
|
|
|
|
nullptr);
|
|
|
|
hr = ::CoCreateInstance(CLSID_WbemLocator,
|
|
|
|
0,
|
|
|
|
CLSCTX_INPROC_SERVER,
|
|
|
|
IID_IWbemLocator,
|
|
|
|
(LPVOID*)&locator_);
|
|
|
|
if (hr != S_OK) {
|
|
|
|
locator_ = nullptr;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-23 21:33:44 +00:00
|
|
|
hr = locator_->ConnectServer(
|
|
|
|
nspace, nullptr, nullptr, nullptr, 0, nullptr, nullptr, &services_);
|
2016-09-08 01:04:33 +00:00
|
|
|
if (hr != S_OK) {
|
|
|
|
services_ = nullptr;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = services_->ExecQuery(
|
2016-12-12 08:23:08 +00:00
|
|
|
(BSTR)L"WQL", (BSTR)wql.c_str(), WBEM_FLAG_FORWARD_ONLY, nullptr, &enum_);
|
2016-09-08 01:04:33 +00:00
|
|
|
if (hr != S_OK) {
|
|
|
|
enum_ = nullptr;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
while (hr == WBEM_S_NO_ERROR) {
|
|
|
|
IWbemClassObject* result = nullptr;
|
|
|
|
ULONG result_count = 0;
|
|
|
|
|
|
|
|
hr = enum_->Next(WBEM_INFINITE, 1, &result, &result_count);
|
|
|
|
if (SUCCEEDED(hr) && result_count > 0) {
|
|
|
|
results_.push_back(WmiResultItem(result));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
status_ = Status(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
WmiRequest::WmiRequest(WmiRequest&& src) {
|
|
|
|
locator_ = nullptr;
|
|
|
|
std::swap(locator_, src.locator_);
|
|
|
|
|
|
|
|
services_ = nullptr;
|
|
|
|
std::swap(services_, src.services_);
|
|
|
|
|
|
|
|
enum_ = nullptr;
|
|
|
|
std::swap(enum_, src.enum_);
|
|
|
|
}
|
|
|
|
|
|
|
|
WmiRequest::~WmiRequest() {
|
|
|
|
results_.clear();
|
|
|
|
|
|
|
|
if (enum_ != nullptr) {
|
|
|
|
enum_->Release();
|
|
|
|
enum_ = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (services_ != nullptr) {
|
|
|
|
services_->Release();
|
|
|
|
services_ = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (locator_ != nullptr) {
|
|
|
|
locator_->Release();
|
|
|
|
locator_ = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|