当前位置: 首页 > 工具软件 > osquery > 使用案例 >

06_osquery_源码解读_system_info

薛元忠
2023-12-01

一、表的结构

system_info.table在源码中相对位置为/specs/system_info.table

table_name("system_info")
description("System information for identification.")
schema([
    Column("hostname", TEXT, "Network hostname including domain"),
    Column("uuid", TEXT, "Unique ID provided by the system"),
    Column("cpu_type", TEXT, "CPU type"),
    Column("cpu_subtype", TEXT, "CPU subtype"),
    Column("cpu_brand", TEXT, "CPU brand string, contains vendor and model"),
    Column("cpu_physical_cores", INTEGER, "Number of physical CPU cores in to the system"),
    Column("cpu_logical_cores", INTEGER, "Number of logical CPU cores available to the system"),
    Column("cpu_microcode", TEXT, "Microcode version"),
    Column("physical_memory", BIGINT, "Total physical memory in bytes"),
    Column("hardware_vendor", TEXT, "Hardware vendor"),
    Column("hardware_model", TEXT, "Hardware model"),
    Column("hardware_version", TEXT, "Hardware version"),
    Column("hardware_serial", TEXT, "Device serial number"),
    Column("board_vendor", TEXT, "Board vendor"),
    Column("board_model", TEXT, "Board model"),
    Column("board_version", TEXT, "Board version"),
    Column("board_serial", TEXT, "Board serial number"),
    Column("computer_name", TEXT, "Friendly computer name (optional)"),
    Column("local_hostname", TEXT, "Local hostname (optional)"),
])
implementation("system/system_info@genSystemInfo")

二、Windows上的实现

system_info获取的表项较多,在Windows上通过多种方式进行获取,因此system_info.cpp(Windows)的代码在后续学习中具有一定指导意义。

QueryData genSystemInfo(QueryContext& context) {
  Row r;
  //通过WINAPI获取本地计算机的标准主机名。
  r["hostname"] = osquery::getFqdn();
  r["computer_name"] = osquery::getHostname();
  r["local_hostname"] = r["computer_name"];
  getHostUUID(r["uuid"]);

  auto qd = SQL::selectAllFrom("cpuid");
  for (const auto& row : qd) {
    if (row.at("feature") == "product_name") {
      r["cpu_brand"] = row.at("value");
      boost::trim(r["cpu_brand"]);
    }
  }

  //使用WMI获取信息
  const WmiRequest wmiSystemReq("select * from Win32_ComputerSystem");
  const WmiRequest wmiSystemReqProc("select * from Win32_Processor");
  const std::vector<WmiResultItem>& wmiResults = wmiSystemReq.results();
  const std::vector<WmiResultItem>& wmiResultsProc = wmiSystemReqProc.results();
  if (!wmiResults.empty() && !wmiResultsProc.empty()) {
    long numProcs = 0;
    wmiResults[0].GetLong("NumberOfLogicalProcessors", numProcs);
    r["cpu_logical_cores"] = INTEGER(numProcs);
    wmiResultsProc[0].GetLong("NumberOfCores", numProcs);
    r["cpu_physical_cores"] = INTEGER(numProcs);
    wmiResults[0].GetString("TotalPhysicalMemory", r["physical_memory"]);
    wmiResults[0].GetString("Manufacturer", r["hardware_vendor"]);
    wmiResults[0].GetString("Model", r["hardware_model"]);
  } else {
    r["cpu_logical_cores"] = "-1";
    r["cpu_physical_cores"] = "-1";
    r["physical_memory"] = "-1";
    r["hardware_vendor"] = "-1";
    r["hardware_model"] = "-1";
  }

  //通过注册表获取部分信息
  QueryData regResults;
  queryKey(
      "HKEY_LOCAL_MACHINE\\"
      "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\",
      regResults);
  for (const auto& key : regResults) {
    if (key.at("name") == "Update Revision") {
      if (key.at("data").size() >= 16) {
        auto revision_exp =
            tryTo<unsigned long int>(key.at("data").substr(8, 2), 16);
        r["cpu_microcode"] = std::to_string(revision_exp.takeOr(0ul));
      }
      break;
    }
  }
  
  //通过WMI查询获取hardware_serial
  const WmiRequest wmiBiosReq("select * from Win32_Bios");
  const std::vector<WmiResultItem>& wmiBiosResults = wmiBiosReq.results();
  if (wmiBiosResults.size() != 0) {
    wmiBiosResults[0].GetString("SerialNumber", r["hardware_serial"]);
  } else {
    r["hardware_serial"] = "-1";
  }

  //调用WInAPI接口获取cpu_type
  SYSTEM_INFO systemInfo;
  GetSystemInfo(&systemInfo);
  switch (systemInfo.wProcessorArchitecture) {
  case PROCESSOR_ARCHITECTURE_AMD64:
    r["cpu_type"] = "x86_64";
    break;
  case PROCESSOR_ARCHITECTURE_ARM:
    r["cpu_type"] = "ARM";
    break;
  case PROCESSOR_ARCHITECTURE_IA64:
    r["cpu_type"] = "x64 Itanium";
    break;
  case PROCESSOR_ARCHITECTURE_INTEL:
    r["cpu_type"] = "x86";
    break;
  case PROCESSOR_ARCHITECTURE_UNKNOWN:
    r["cpu_type"] = "Unknown";
  default:
    break;
  }

  r["cpu_subtype"] = "-1";
  r["hardware_version"] = "-1";
  return {r};
}

2.1. 通过WMI查询获取

从上面摘取部分code进行解析,如下,WmiRequest是一个类,创建时传入查询指令,在其私有的results数据结构中会存储查询结果。

//使用WMI获取信息
  const WmiRequest wmiSystemReq("select * from Win32_ComputerSystem");
  const WmiRequest wmiSystemReqProc("select * from Win32_Processor");
  const std::vector<WmiResultItem>& wmiResults = wmiSystemReq.results();
  const std::vector<WmiResultItem>& wmiResultsProc = wmiSystemReqProc.results();
  if (!wmiResults.empty() && !wmiResultsProc.empty()) {
    long numProcs = 0;
    wmiResults[0].GetLong("NumberOfLogicalProcessors", numProcs);
    r["cpu_logical_cores"] = INTEGER(numProcs);
    wmiResultsProc[0].GetLong("NumberOfCores", numProcs);
    r["cpu_physical_cores"] = INTEGER(numProcs);
    wmiResults[0].GetString("TotalPhysicalMemory", r["physical_memory"]);
    wmiResults[0].GetString("Manufacturer", r["hardware_vendor"]);
    wmiResults[0].GetString("Model", r["hardware_model"]);
  } else {
    r["cpu_logical_cores"] = "-1";
    r["cpu_physical_cores"] = "-1";
    r["physical_memory"] = "-1";
    r["hardware_vendor"] = "-1";
    r["hardware_model"] = "-1";
  }

2.2. 通过注册表获取

注册表(Registry)是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息。
query(key,value)是osquery的一个函数,key输入的是注册表的路径,value输出的是该路径中的信息。

//通过注册表获取部分信息
  QueryData regResults;
  queryKey(
      "HKEY_LOCAL_MACHINE\\"
      "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\",
      regResults);
  for (const auto& key : regResults) {
    if (key.at("name") == "Update Revision") {
      if (key.at("data").size() >= 16) {
        auto revision_exp =
            tryTo<unsigned long int>(key.at("data").substr(8, 2), 16);
        r["cpu_microcode"] = std::to_string(revision_exp.takeOr(0ul));
      }
      break;
    }

2.3. 通过WinAPI进行获取

通过调用WINAPI提供的GetSystemInfo()函数获取cpu_type的值。

//调用WInAPI接口获取cpu_type
  SYSTEM_INFO systemInfo;
  GetSystemInfo(&systemInfo);
  switch (systemInfo.wProcessorArchitecture) {
  case PROCESSOR_ARCHITECTURE_AMD64:
    r["cpu_type"] = "x86_64";
    break;
  case PROCESSOR_ARCHITECTURE_ARM:
    r["cpu_type"] = "ARM";
    break;
  case PROCESSOR_ARCHITECTURE_IA64:
    r["cpu_type"] = "x64 Itanium";
    break;
  case PROCESSOR_ARCHITECTURE_INTEL:
    r["cpu_type"] = "x86";
    break;
  case PROCESSOR_ARCHITECTURE_UNKNOWN:
    r["cpu_type"] = "Unknown";
  default:
    break;
  }

3. 总结

osquery底层通过各种方式获取系统信息,值得学习。

 类似资料: