mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-09 02:36:46 +00:00
152 lines
4.5 KiB
C++
152 lines
4.5 KiB
C++
/*
|
|
* Copyright (c) 2014, 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 <boost/algorithm/string.hpp>
|
|
#include <boost/uuid/uuid.hpp>
|
|
#include <boost/uuid/uuid_io.hpp>
|
|
|
|
#include <osquery/hash.h>
|
|
#include <osquery/logger.h>
|
|
#include <osquery/tables.h>
|
|
|
|
#include "osquery/tables/system/darwin/iokit_utils.h"
|
|
#include "osquery/tables/system/efi_misc.h"
|
|
|
|
namespace osquery {
|
|
namespace tables {
|
|
|
|
#define kIODTChosenPath_ "IODeviceTree:/chosen"
|
|
|
|
#define MEDIA_DEVICE_PATH 0x04
|
|
#define MEDIA_FILEPATH_DP 0x04
|
|
#define MEDIA_HARDDRIVE_DP 0x01
|
|
|
|
std::string getCanonicalEfiDevicePath(const CFDataRef& data) {
|
|
std::string path;
|
|
|
|
// Iterate through the EFI_DEVICE_PATH_PROTOCOL stacked structs.
|
|
auto bytes = CFDataGetBytePtr((CFDataRef)data);
|
|
auto length = CFDataGetLength((CFDataRef)data);
|
|
size_t search_offset = 0;
|
|
|
|
while ((search_offset + sizeof(EFI_DEVICE_PATH_PROTOCOL)) < length) {
|
|
auto node = (const EFI_DEVICE_PATH_PROTOCOL*)(bytes + search_offset);
|
|
if (EfiIsDevicePathEnd(node)) {
|
|
// End of the EFI device path stacked structs.
|
|
break;
|
|
}
|
|
|
|
if (EfiDevicePathNodeLength(node) + search_offset > length) {
|
|
// Malformed EFI device header.
|
|
break;
|
|
}
|
|
|
|
// Only support paths and hard drive partitions.
|
|
if (EfiDevicePathType(node) == MEDIA_DEVICE_PATH) {
|
|
if (node->SubType == MEDIA_FILEPATH_DP) {
|
|
for (size_t i = 0; i < EfiDevicePathNodeLength(node); i += 2) {
|
|
// Strip UTF16 characters to UTF8.
|
|
path += (((char*)(node)) + sizeof(EFI_DEVICE_PATH_PROTOCOL))[i];
|
|
}
|
|
} else if (node->SubType == MEDIA_HARDDRIVE_DP) {
|
|
// Extract the device UUID to later join with block devices.
|
|
auto uuid = ((const HARDDRIVE_DEVICE_PATH*)node)->Signature;
|
|
boost::uuids::uuid hdd_signature = {{
|
|
uuid[3], uuid[2], uuid[1], uuid[0],
|
|
uuid[5], uuid[4],
|
|
uuid[7], uuid[6],
|
|
uuid[8], uuid[9],
|
|
uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15],
|
|
}};
|
|
path += boost::to_upper_copy(boost::uuids::to_string(hdd_signature));
|
|
}
|
|
}
|
|
|
|
search_offset += EfiDevicePathNodeLength(node);
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
QueryData genKernelInfo(QueryContext& context) {
|
|
QueryData results;
|
|
|
|
mach_port_t master_port;
|
|
auto kr = IOMasterPort(bootstrap_port, &master_port);
|
|
if (kr != KERN_SUCCESS) {
|
|
VLOG(1) << "Could not get the IOMaster port";
|
|
return {};
|
|
}
|
|
|
|
// NVRAM registry entry is :/options.
|
|
auto chosen = IORegistryEntryFromPath(master_port, kIODTChosenPath_);
|
|
if (chosen == 0) {
|
|
VLOG(1) << "Could not get IOKit boot device";
|
|
return {};
|
|
}
|
|
|
|
// Parse the boot arguments, usually none.
|
|
CFMutableDictionaryRef properties;
|
|
kr = IORegistryEntryCreateCFProperties(
|
|
chosen, &properties, kCFAllocatorDefault, 0);
|
|
IOObjectRelease(chosen);
|
|
|
|
if (kr != KERN_SUCCESS) {
|
|
VLOG(1) << "Could not get IOKit boot device properties";
|
|
return {};
|
|
}
|
|
|
|
Row r;
|
|
CFTypeRef property;
|
|
if (CFDictionaryGetValueIfPresent(
|
|
properties, CFSTR("boot-args"), &property)) {
|
|
r["arguments"] = stringFromCFData((CFDataRef)property);
|
|
}
|
|
|
|
if (CFDictionaryGetValueIfPresent(
|
|
properties, CFSTR("boot-device-path"), &property)) {
|
|
r["device"] = getCanonicalEfiDevicePath((CFDataRef)property);
|
|
}
|
|
|
|
if (CFDictionaryGetValueIfPresent(
|
|
properties, CFSTR("boot-file"), &property)) {
|
|
r["path"] = stringFromCFData((CFDataRef)property);
|
|
boost::trim(r["path"]);
|
|
}
|
|
// No longer need chosen properties.
|
|
CFRelease(properties);
|
|
|
|
// The kernel version, signature, and build information is stored in Root.
|
|
auto root = IORegistryGetRootEntry(master_port);
|
|
if (root != 0) {
|
|
property = (CFDataRef)IORegistryEntryCreateCFProperty(
|
|
root, CFSTR(kIOKitBuildVersionKey), kCFAllocatorDefault, 0);
|
|
if (property != nullptr) {
|
|
// The version is in the form:
|
|
// Darwin Kernel Version VERSION: DATE; root:BUILD/TAG
|
|
auto signature = stringFromCFString((CFStringRef)property);
|
|
CFRelease(property);
|
|
|
|
r["version"] = signature.substr(22, signature.find(":") - 22);
|
|
}
|
|
}
|
|
|
|
// With the path and device, try to locate the on-disk kernel
|
|
if (r.count("path") > 0) {
|
|
// This does not use the device path, potential invalidation.
|
|
r["md5"] = hashFromFile(HASH_TYPE_MD5, "/" + r["path"]);
|
|
}
|
|
|
|
results.push_back(r);
|
|
return results;
|
|
}
|
|
}
|
|
}
|