Esempio n. 1
0
TEST_F(SQLTests, test_sql_sha1) {
  QueryData d;
  query("select sha1('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3");
}
Esempio n. 2
0
QueryData genUsbDevices() {
  QueryData results;

  io_service_t device;
  char vendor[256];
  char product[256];

  auto matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
  if (matchingDict == nullptr) {
    return results;
  }

  kern_return_t kr;
  io_iterator_t iter;
  kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);

  if (kr != KERN_SUCCESS) {
    return results;
  }

  memset(vendor, 0, 256);
  memset(product, 0, 256);
  while ((device = IOIteratorNext(iter))) {
    Row r;

    // Get the vendor of the device;
    CFMutableDictionaryRef vendor_dict;
    IORegistryEntryCreateCFProperties(
        device, &vendor_dict, kCFAllocatorDefault, kNilOptions);
    CFTypeRef vendor_obj =
        CFDictionaryGetValue(vendor_dict, CFSTR("USB Vendor Name"));
    if (vendor_obj) {
      CFStringRef cf_vendor =
          CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef)vendor_obj);
      CFStringGetCString(cf_vendor, vendor, 255, CFStringGetSystemEncoding());
      r["manufacturer"] = vendor;
      CFRelease(cf_vendor);
    }
    CFRelease(vendor_dict);

    // Get the product name of the device
    CFMutableDictionaryRef product_dict;
    IORegistryEntryCreateCFProperties(
        device, &product_dict, kCFAllocatorDefault, kNilOptions);
    CFTypeRef product_obj =
        CFDictionaryGetValue(product_dict, CFSTR("USB Product Name"));
    if (product_obj) {
      CFStringRef cf_product =
          CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef)product_obj);
      CFStringGetCString(cf_product, product, 255, CFStringGetSystemEncoding());
      r["product"] = product;
      CFRelease(cf_product);
    }
    CFRelease(product_dict);

    // Lets make sure we don't have an empty product & manufacturer
    if (r["product"].size() > 0 || r["manufacturer"].size() > 0) {
      results.push_back(r);
    }

    IOObjectRelease(device);
  }

  IOObjectRelease(iter);
  return results;
}
Esempio n. 3
0
TEST_F(SQLTests, test_sql_base64_decode) {
  QueryData d;
  query("select from_base64('dGVzdA==') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "test");
}
Esempio n. 4
0
TEST_F(SQLTests, test_sql_md5) {
  QueryData d;
  query("select md5('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "098f6bcd4621d373cade4e832627b4f6");
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
TEST_F(SQLTests, test_sql_base64_encode) {
  QueryData d;
  query("select to_base64('test') as test;", d);
  EXPECT_EQ(d.size(), 1U);
  EXPECT_EQ(d[0]["test"], "dGVzdA==");
}
Esempio n. 7
0
void genMemoryRegion(int pid,
                     const vm_address_t& address,
                     const vm_size_t& size,
                     struct vm_region_submap_info_64& info,
                     const std::map<vm_address_t, std::string>& libraries,
                     QueryData& results) {
  Row r;
  r["pid"] = INTEGER(pid);

  char addr_str[17] = {0};
  sprintf(addr_str, "%016lx", address);
  r["start"] = "0x" + std::string(addr_str);
  sprintf(addr_str, "%016lx", address + size);
  r["end"] = "0x" + std::string(addr_str);

  char perms[5] = {0};
  sprintf(perms,
          "%c%c%c",
          (info.protection & VM_PROT_READ) ? 'r' : '-',
          (info.protection & VM_PROT_WRITE) ? 'w' : '-',
          (info.protection & VM_PROT_EXECUTE) ? 'x' : '-');
  // Mimic Linux permissions reporting.
  r["permissions"] = std::string(perms) + 'p';

  char filename[PATH_MAX] = {0};
  // Eventually we'll arrive at dynamic memory COW regions.
  // OS X will return a dyld_shared_cache[...] substitute alias.
  int bytes = proc_regionfilename(pid, address, filename, sizeof(filename));

  if (info.share_mode == SM_COW && info.ref_count == 1) {
    // (psutil) Treat single reference SM_COW as SM_PRIVATE
    info.share_mode = SM_PRIVATE;
  }

  if (bytes == 0 || filename[0] == 0) {
    switch (info.share_mode) {
    case SM_COW:
      r["path"] = "[cow]";
      break;
    case SM_PRIVATE:
      r["path"] = "[private]";
      break;
    case SM_EMPTY:
      r["path"] = "[null]";
      break;
    case SM_SHARED:
    case SM_TRUESHARED:
      r["path"] = "[shared]";
      break;
    case SM_PRIVATE_ALIASED:
      r["path"] = "[private_aliased]";
      break;
    case SM_SHARED_ALIASED:
      r["path"] = "[shared_aliased]";
      break;
    default:
      r["path"] = "[unknown]";
    }
    // Labeling all non-path regions pseudo is not 100% appropriate.
    // Practically, pivoting on non-meta (actual) paths is helpful.
    r["pseudo"] = "1";
  } else {
    // The share mode is not a mutex for having a filled-in path.
    r["path"] = std::string(filename);
    r["pseudo"] = "0";
  }

  r["offset"] = INTEGER(info.offset);
  r["device"] = INTEGER(info.object_id);

  // Fields not applicable to OS X maps.
  r["inode"] = "0";

  // Increment the address/region request offset.
  results.push_back(r);

  // Submaps or offsets into regions may contain libraries mapped from the
  // dyld cache.
  for (const auto& library : libraries) {
    if (library.first > address && library.first < (address + size)) {
      r["offset"] = INTEGER(info.offset + (library.first - address));
      r["path"] = library.second;
      r["pseudo"] = "0";
      results.push_back(r);
    }
  }
}
Esempio n. 8
0
/// Given a pid, enumerates all loaded modules and memory pages for that process
Status genMemoryMap(unsigned long pid, QueryData& results) {
  auto proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
  if (proc == INVALID_HANDLE_VALUE) {
    Row r;
    r["pid"] = INTEGER(pid);
    r["start"] = INTEGER(-1);
    r["end"] = INTEGER(-1);
    r["permissions"] = "";
    r["offset"] = INTEGER(-1);
    r["device"] = "-1";
    r["inode"] = INTEGER(-1);
    r["path"] = "";
    r["pseudo"] = INTEGER(-1);
    results.push_back(r);
    return Status(1, "Failed to open handle to process " + std::to_string(pid));
  }
  auto modSnap =
      CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
  if (modSnap == INVALID_HANDLE_VALUE) {
    CloseHandle(proc);
    return Status(1, "Failed to enumerate modules for " + std::to_string(pid));
  }

  auto formatMemPerms = [](unsigned long perm) {
    std::vector<std::string> perms;
    for (const auto& kv : kMemoryConstants) {
      if (kv.first & perm) {
        perms.push_back(kv.second);
      }
    }
    return osquery::join(perms, " | ");
  };

  MODULEENTRY32 me;
  MEMORY_BASIC_INFORMATION mInfo;
  me.dwSize = sizeof(MODULEENTRY32);
  auto ret = Module32First(modSnap, &me);
  while (ret != FALSE) {
    for (auto p = me.modBaseAddr;
         VirtualQueryEx(proc, p, &mInfo, sizeof(mInfo)) == sizeof(mInfo) &&
         p < (me.modBaseAddr + me.modBaseSize);
         p += mInfo.RegionSize) {
      Row r;
      r["pid"] = INTEGER(pid);
      std::stringstream ssStart;
      ssStart << std::hex << mInfo.BaseAddress;
      r["start"] = "0x" + ssStart.str();
      std::stringstream ssEnd;
      ssEnd << std::hex << std::setfill('0') << std::setw(16)
            << reinterpret_cast<unsigned long long>(mInfo.BaseAddress) +
                   mInfo.RegionSize;
      r["end"] = "0x" + ssEnd.str();
      r["permissions"] = formatMemPerms(mInfo.Protect);
      r["offset"] =
          BIGINT(reinterpret_cast<unsigned long long>(mInfo.AllocationBase));
      r["device"] = "-1";
      r["inode"] = INTEGER(-1);
      r["path"] = me.szExePath;
      r["pseudo"] = INTEGER(-1);
      results.push_back(r);
    }
    ret = Module32Next(modSnap, &me);
  }
  CloseHandle(proc);
  CloseHandle(modSnap);
  return Status(0, "Ok");
}
Esempio n. 9
0
void genControlInfo(int* oid,
                    size_t oid_size,
                    QueryData& results,
                    const std::map<std::string, std::string>& config) {
  Row r;
  if (oid_size == 0) {
    return;
  }

  r["oid"] = stringFromMIB(oid, oid_size);
  // Request the description (the canonical name) for the MIB.
  char response[CTL_MAX_VALUE] = {0};
  size_t response_size = CTL_MAX_VALUE;

  int request[CTL_MAXNAME + 2] = {0, CTL_DEBUG_DESCRIPTION};
  memcpy(request + 2, oid, oid_size * sizeof(int));
  if (sysctl(request, oid_size + 2, response, &response_size, 0, 0) != 0) {
    return;
  }

  r["name"] = std::string(response);
  if (oid[0] > 0 && oid[0] < static_cast<int>(kControlNames.size())) {
    r["subsystem"] = kControlNames[oid[0]];
  }

  // Now request structure type.
  response_size = CTL_MAX_VALUE;
  request[1] = CTL_DEBUG_TYPE;
  if (sysctl(request, oid_size + 2, response, &response_size, 0, 0) != 0) {
    // Cannot request MIB type (int, string, struct, etc).
    return;
  }

  size_t oid_type = 0;
  if (response_size > 0) {
    oid_type = ((size_t)response[0] & CTLTYPE);
    if ((oid_type == 0 || oid_type == CTLTYPE_INT) && response_size > 4) {
      // For whatever reason, macOS defines fewer CTLTYPE's than BSD, and
      // sometimes uses the format character instead of (or in addition to)
      // the CTLTYPE to specify the type. Here we detect a few such cases and
      // map them to CTLTYPE's.
      // TODO: Both CTLTYPE_INT and CTLTYPE_QUAD can be specified as unsigned
      // using a similar method.
      char type_char = response[4];
      switch (type_char) {
      case 'I':
        oid_type = CTLTYPE_INT;
        break;
      case 'L':
        if (sizeof(long) == sizeof(long long)) {
          oid_type = CTLTYPE_QUAD;
        } else if (sizeof(long) == sizeof(int)) {
          oid_type = CTLTYPE_INT;
        }
        break;
      case 'S':
        oid_type = CTLTYPE_STRUCT;
        break;
      case 'Q':
        oid_type = CTLTYPE_QUAD;
        break;
        // Otherwise leave the type as it was; we have no additional knowledge
      }
    }
    if (oid_type < kControlTypes.size()) {
      r["type"] = kControlTypes[oid_type];
    }
  }

  // Finally request MIB value.
  if (oid_type > CTLTYPE_NODE && oid_type < CTLTYPE_OPAQUE) {
    size_t value_size = 0;
    sysctl(oid, oid_size, 0, &value_size, 0, 0);

    if (value_size > CTL_MAX_VALUE) {
      // If the value size is larger than the max value, limit.
      value_size = CTL_MAX_VALUE;
    }

    sysctl(oid, oid_size, response, &value_size, 0, 0);
    if (oid_type == CTLTYPE_INT) {
      unsigned int value;
      memcpy(&value, response, sizeof(int));
      r["current_value"] = INTEGER(value);
    } else if (oid_type == CTLTYPE_STRING) {
      r["current_value"] = std::string(response);
    } else if (oid_type == CTLTYPE_QUAD) {
      unsigned long long value;
      memcpy(&value, response, sizeof(unsigned long long));
      r["current_value"] = INTEGER(value);
    }
  }

  // If this MIB was set using sysctl.conf add the value.
  if (config.count(r.at("name")) > 0) {
    r["config_value"] = config.at(r["name"]);
  }

  results.push_back(r);
}
Esempio n. 10
0
QueryData genProcesses(QueryContext& context) {
  QueryData results;

  // Initialize time conversions.
  static mach_timebase_info_data_t time_base;
  if (time_base.denom == 0) {
    mach_timebase_info(&time_base);
  }

  auto pidlist = getProcList(context);
  int argmax = genMaxArgs();

  for (auto& pid : pidlist) {
    Row r;
    r["pid"] = INTEGER(pid);

    {
      // The command line invocation including arguments.
      auto args = getProcRawArgs(pid, argmax);
      std::string cmdline = boost::algorithm::join(args.args, " ");
      r["cmdline"] = cmdline;
    }

    // The process relative root and current working directory.
    genProcRootAndCWD(pid, r);

    proc_cred cred;
    if (getProcCred(pid, cred)) {
      r["parent"] = BIGINT(cred.parent);
      r["pgroup"] = BIGINT(cred.group);
      // check if process state is one of the expected ones
      r["state"] = (1 <= cred.status && cred.status <= 5)
                       ? TEXT(kProcessStateMapping[cred.status])
                       : TEXT('?');
      r["nice"] = INTEGER(cred.nice);
      r["uid"] = BIGINT(cred.real.uid);
      r["gid"] = BIGINT(cred.real.gid);
      r["euid"] = BIGINT(cred.effective.uid);
      r["egid"] = BIGINT(cred.effective.gid);
      r["suid"] = BIGINT(cred.saved.uid);
      r["sgid"] = BIGINT(cred.saved.gid);
    } else {
      continue;
    }

    // If the process is not a Zombie, try to find the path and name.
    if (cred.status != 5) {
      r["path"] = getProcPath(pid);
      // OS X proc_name only returns 16 bytes, use the basename of the path.
      r["name"] = fs::path(r["path"]).filename().string();
    } else {
      r["path"] = "";
      std::vector<char> name(17);
      proc_name(pid, name.data(), 16);
      r["name"] = std::string(name.data());
    }

    // If the path of the executable that started the process is available and
    // the path exists on disk, set on_disk to 1. If the path is not
    // available, set on_disk to -1. If, and only if, the path of the
    // executable is available and the file does NOT exist on disk, set on_disk
    // to 0.
    if (r["path"].empty()) {
      r["on_disk"] = INTEGER(-1);
    } else if (pathExists(r["path"])) {
      r["on_disk"] = INTEGER(1);
    } else {
      r["on_disk"] = INTEGER(0);
    }

    // systems usage and time information
    struct rusage_info_v2 rusage_info_data;
    int status =
        proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t*)&rusage_info_data);
    // proc_pid_rusage returns -1 if it was unable to gather information
    if (status == 0) {
      // size/memory information
      r["wired_size"] = TEXT(rusage_info_data.ri_wired_size);
      r["resident_size"] = TEXT(rusage_info_data.ri_resident_size);
      r["total_size"] = TEXT(rusage_info_data.ri_phys_footprint);

      // time information
      r["user_time"] = TEXT(rusage_info_data.ri_user_time / CPU_TIME_RATIO);
      r["system_time"] = TEXT(rusage_info_data.ri_system_time / CPU_TIME_RATIO);
      // Convert the time in CPU ticks since boot to seconds.
      // This is relative to time not-sleeping since boot.
      r["start_time"] =
          TEXT((rusage_info_data.ri_proc_start_abstime / START_TIME_RATIO) *
               time_base.numer / time_base.denom);
    } else {
      r["wired_size"] = "-1";
      r["resident_size"] = "-1";
      r["total_size"] = "-1";
      r["user_time"] = "-1";
      r["system_time"] = "-1";
      r["start_time"] = "-1";
    }

    struct proc_taskinfo task_info;
    status =
        proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &task_info, sizeof(task_info));
    if (status == sizeof(task_info)) {
      r["threads"] = INTEGER(task_info.pti_threadnum);
    } else {
      r["threads"] = "-1";
    }

    results.push_back(r);
  }

  return results;
}
Esempio n. 11
0
QueryData genProcesses(QueryContext &context) {
  QueryData results;

  auto pidlist = getProcList(context);
  auto parent_pid = getParentMap(pidlist);
  int argmax = genMaxArgs();

  for (auto &pid : pidlist) {
    if (!context.constraints["pid"].matches<int>(pid)) {
      // Optimize by not searching when a pid is a constraint.
      continue;
    }

    Row r;
    r["pid"] = INTEGER(pid);
    r["path"] = getProcPath(pid);
    // OS X proc_name only returns 16 bytes, use the basename of the path.
    r["name"] = boost::filesystem::path(r["path"]).filename().string();

    // The command line invocation including arguments.
    std::string cmdline = boost::algorithm::join(getProcArgs(pid, argmax), " ");
    boost::algorithm::trim(cmdline);
    r["cmdline"] = cmdline;
    genProcRootAndCWD(pid, r);

    proc_cred cred;
    if (getProcCred(pid, cred)) {
      r["uid"] = BIGINT(cred.real.uid);
      r["gid"] = BIGINT(cred.real.gid);
      r["euid"] = BIGINT(cred.effective.uid);
      r["egid"] = BIGINT(cred.effective.gid);
    } else {
      r["uid"] = "-1";
      r["gid"] = "-1";
      r["euid"] = "-1";
      r["egid"] = "-1";
    }

    // Find the parent process.
    const auto parent_it = parent_pid.find(pid);
    if (parent_it != parent_pid.end()) {
      r["parent"] = INTEGER(parent_it->second);
    } else {
      r["parent"] = "-1";
    }

    // If the path of the executable that started the process is available and
    // the path exists on disk, set on_disk to 1. If the path is not
    // available, set on_disk to -1. If, and only if, the path of the
    // executable is available and the file does NOT exist on disk, set on_disk
    // to 0.
    r["on_disk"] = osquery::pathExists(r["path"]).toString();

    // systems usage and time information
    struct rusage_info_v2 rusage_info_data;
    int rusage_status = proc_pid_rusage(
        pid, RUSAGE_INFO_V2, (rusage_info_t *)&rusage_info_data);
    // proc_pid_rusage returns -1 if it was unable to gather information
    if (rusage_status == 0) {
      // size/memory information
      r["wired_size"] = TEXT(rusage_info_data.ri_wired_size);
      r["resident_size"] = TEXT(rusage_info_data.ri_resident_size);
      r["phys_footprint"] = TEXT(rusage_info_data.ri_phys_footprint);

      // time information
      r["user_time"] = TEXT(rusage_info_data.ri_user_time / 1000000);
      r["system_time"] = TEXT(rusage_info_data.ri_system_time / 1000000);
      r["start_time"] = TEXT(rusage_info_data.ri_proc_start_abstime);
    } else {
      r["wired_size"] = "-1";
      r["resident_size"] = "-1";
      r["phys_footprint"] = "-1";
      r["user_time"] = "-1";
      r["system_time"] = "-1";
      r["start_time"] = "-1";
    }

    results.push_back(r);
  }

  return results;
}
Esempio n. 12
0
TEST_F(RegistryTablesTest, test_registry_non_existing_key) {
  QueryData results;
  auto ret = queryKey(kInvalidTestKey, results);
  EXPECT_TRUE(ret.ok());
  EXPECT_TRUE(results.size() == 0);
}
Esempio n. 13
0
SVAPI_API
bool PutValueIntoChildren(const NodeData & ndata, string pid, string addr)
{
	if(pid.empty()||addr.empty())
		return false;
	if(pid.find(".")==std::string::npos)
		return false;
	if(ndata.empty())
		return false;

	NodeData & ndata1= const_cast< NodeData & >( ndata );
	unsigned int tlen= GetNodeDataRawDataSize(ndata1);
	svutil::buffer tbuf;
	if(!tbuf.checksize(tlen))
		return false;
	const char *data= GetNodeDataRawData(ndata1,tbuf,tlen); 
	if(data==NULL)
		return false;

	QueryData qd;
	char *pdata=NULL;
	S_UINT rlen=0;

	S_UINT len=0;

	SVDBQUERY querybuf={0};
	querybuf.len = sizeof(SVDBQUERY);
	querybuf.querytype=QUERY_PUT_VALUE;
	querybuf.datatype=S_SVSE;
	strcpy(querybuf.qstr,pid.c_str());

	INIQUERY iquery={0};
	iquery.len=sizeof(INIQUERY);
	iquery.datatype=D_STRING;
	iquery.datalen=tlen;

	len+=sizeof(INIQUERY);
	len+=tlen;

	querybuf.datalen=len;

	buffer buf;
	if(!buf.checksize(len))
		return false;
	char *pt=buf.getbuffer();
	memcpy(pt,&iquery,sizeof(INIQUERY));
	pt+=sizeof(INIQUERY);
	memmove(pt,data,tlen);

	if(qd.Query(&querybuf,buf,len,(void **)&pdata,rlen,addr))
	{
		if(pdata!=NULL && rlen>0)
		{
			int *pret=(int*)pdata;
			if(*pret==SVDB_OK)
			{
				delete [] pdata;
				return true;
			}
		}
	}
	if(pdata!=NULL)
		delete [] pdata;
	return false;
}
Esempio n. 14
0
QueryData genCPUID(QueryContext& context) {
  QueryData results;

  if (!genStrings(results).ok()) {
    return results;
  }

  // Get the CPU meta-data about the model, stepping, family.
  genFamily(results);

  int regs[4] = {-1};
  for (const auto& feature_set : kCPUFeatures) {
    auto eax = feature_set.first;
    cpuid(eax, 0, regs);

    for (const auto& feature : feature_set.second) {
      Row r;

      r["feature"] = feature.first;

      // Get the return register holding the feature bit.
      auto feature_register = 0;
      if (feature.second.first == "edx") {
        feature_register = 3;
      } else if (feature.second.first == "ebx") {
        feature_register = 1;
      } else if (feature.second.first == "ecx") {
        feature_register = 2;
      }

      auto feature_bit = feature.second.second;
      r["value"] = isBitSet(feature_bit, regs[feature_register]) ? "1" : "0";
      r["output_register"] = feature.second.first;
      r["output_bit"] = INTEGER(feature_bit);
      r["input_eax"] = std::to_string(eax);
      results.push_back(r);
    }
  }

  {
    Row r;
    r["output_register"] = "eax,ebx,ecx,edx";
    r["output_bit"] = INTEGER(0);

    cpuid(0x12, 0, regs);
    std::stringstream sgx0;
    sgx0 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[0]);
    sgx0 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[1]);
    sgx0 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[2]);
    sgx0 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[3]);
    r["feature"] = "sgx0";
    r["value"] = sgx0.str();
    r["input_eax"] = std::to_string(0x12);
    results.push_back(r);

    cpuid(0x12, 1, regs);
    std::stringstream sgx1;
    sgx1 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[0]);
    sgx1 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[1]);
    sgx1 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[2]);
    sgx1 << std::hex << std::setw(8) << std::setfill('0')
         << static_cast<int>(regs[3]);
    r["feature"] = "sgx1";
    r["value"] = sgx1.str();
    r["input_eax"] = std::to_string(0x12) + ",1";
    results.push_back(r);
  }

  return results;
}
Esempio n. 15
0
void genDetailsFromAddr(const struct ifaddrs *addr, QueryData &results) {
  Row r;
  if (addr->ifa_name != nullptr) {
    r["interface"] = std::string(addr->ifa_name);
  } else {
    r["interface"] = "";
  }
  r["mac"] = macAsString(addr);

  if (addr->ifa_data != nullptr) {
#ifdef __linux__
    // Linux/Netlink interface details parsing.
    auto ifd = (struct rtnl_link_stats *)addr->ifa_data;
    r["mtu"] = "0";
    r["metric"] = "0";
    r["type"] = "0";
    r["ipackets"] = BIGINT_FROM_UINT32(ifd->rx_packets);
    r["opackets"] = BIGINT_FROM_UINT32(ifd->tx_packets);
    r["ibytes"] = BIGINT_FROM_UINT32(ifd->rx_bytes);
    r["obytes"] = BIGINT_FROM_UINT32(ifd->tx_bytes);
    r["ierrors"] = BIGINT_FROM_UINT32(ifd->rx_errors);
    r["oerrors"] = BIGINT_FROM_UINT32(ifd->tx_errors);

    // Get Linux physical properties for the AF_PACKET entry.
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd >= 0) {
      struct ifreq ifr;
      memcpy(ifr.ifr_name, addr->ifa_name, IFNAMSIZ);
      if (ioctl(fd, SIOCGIFMTU, &ifr) >= 0) {
        r["mtu"] = BIGINT_FROM_UINT32(ifr.ifr_mtu);
      }

      if (ioctl(fd, SIOCGIFMETRIC, &ifr) >= 0) {
       r["metric"] = BIGINT_FROM_UINT32(ifr.ifr_metric);
      }

      if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) {
        r["type"] = INTEGER_FROM_UCHAR(ifr.ifr_hwaddr.sa_family);
      }
    }

    // Last change is not implemented in Linux.
    r["last_change"] = "-1";
#else
    // Apple and FreeBSD interface details parsing.
    auto ifd = (struct if_data *)addr->ifa_data;
    r["type"] = INTEGER_FROM_UCHAR(ifd->ifi_type);
    r["mtu"] = BIGINT_FROM_UINT32(ifd->ifi_mtu);
    r["metric"] = BIGINT_FROM_UINT32(ifd->ifi_metric);
    r["ipackets"] = BIGINT_FROM_UINT32(ifd->ifi_ipackets);
    r["opackets"] = BIGINT_FROM_UINT32(ifd->ifi_opackets);
    r["ibytes"] = BIGINT_FROM_UINT32(ifd->ifi_ibytes);
    r["obytes"] = BIGINT_FROM_UINT32(ifd->ifi_obytes);
    r["ierrors"] = BIGINT_FROM_UINT32(ifd->ifi_ierrors);
    r["oerrors"] = BIGINT_FROM_UINT32(ifd->ifi_oerrors);
    r["last_change"] = BIGINT_FROM_UINT32(ifd->ifi_lastchange.tv_sec);
#endif
  }

  results.push_back(r);
}
Esempio n. 16
0
void getDrivesForArray(const std::string& arrayName,
                       MDInterface& md,
                       QueryData& data) {
  std::string path(md.getPathByDevName(arrayName));
  if (path.empty()) {
    LOG(ERROR) << "Could not get file path for " << arrayName;
    return;
  }

  mdu_array_info_t array;
  if (!md.getArrayInfo(path, array)) {
    return;
  }

  /* Create a vector of with all expected slot positions.  As we work through
   * the RAID disks, we remove discovered slots */
  std::vector<size_t> missingSlots(array.raid_disks);
  std::iota(missingSlots.begin(), missingSlots.end(), 0);

  /* Keep track of index in QueryData that have removed slots since we can't
   * make safe assumptions about it's original slot position if disk_number >=
   * total_disk and we're unable to deteremine total number of missing slots
   * until we walk thru all MD_SB_DISKS */
  std::vector<size_t> removedSlots;

  size_t qdPos = data.size();
  for (size_t i = 0; i < MD_SB_DISKS; i++) {
    mdu_disk_info_t disk;
    disk.number = i;
    if (!md.getDiskInfo(path, disk)) {
      continue;
    }

    if (disk.major > 0) {
      Row r;
      r["md_device_name"] = arrayName;
      r["drive_name"] = md.getDevName(disk.major, disk.minor);
      r["state"] = getDiskStateStr(disk.state);

      if (disk.raid_disk >= 0) {
        r["slot"] = INTEGER(disk.raid_disk);
        missingSlots.erase(
            std::remove(
                missingSlots.begin(), missingSlots.end(), disk.raid_disk),
            missingSlots.end());

        /* We assume that if the disk number is less than the total disk count
         * of the array, then it assumes its original slot position;  If the
         * number is greater than the disk count, then it's not safe to make
         * that assumption. We do this check here b/c if a recovery is targeted
         * for the same slot, we potentially miss identifying the original slot
         * position of the bad disk. */
      } else if (disk.raid_disk < 0 && disk.number < array.raid_disks) {
        r["slot"] = std::to_string(disk.number);
        missingSlots.erase(
            std::remove(missingSlots.begin(), missingSlots.end(), disk.number),
            missingSlots.end());

        /* Mark QueryData position as a removedSlot to handle later*/
      } else {
        removedSlots.push_back(qdPos);
      }

      qdPos++;
      data.push_back(r);
    }
  }

  /* Handle all missing slots.  See `scattered_faulty_and_removed` unit test in
   * `./tests/md_tables_tests.cpp`*/
  for (const auto& slot : missingSlots) {
    if (!removedSlots.empty()) {
      data[removedSlots[0]]["slot"] = INTEGER(slot);
      removedSlots.erase(removedSlots.begin());

    } else {
      Row r;
      r["md_device_name"] = arrayName;
      r["drive_name"] = "unknown";
      r["state"] = "removed";
      r["slot"] = std::to_string(slot);
      data.push_back(r);
    }
  }
}
Esempio n. 17
0
void genProcess(const WmiResultItem& result, QueryData& results_data) {
  Row r;
  Status s;
  long pid;
  long lPlaceHolder;
  std::string sPlaceHolder;

  /// Store current process pid for more efficient API use.
  auto currentPid = GetCurrentProcessId();

  s = result.GetLong("ProcessId", pid);
  r["pid"] = s.ok() ? BIGINT(pid) : BIGINT(-1);

  long uid = -1;
  long gid = -1;
  HANDLE hProcess = nullptr;
  if (pid == currentPid) {
    hProcess = GetCurrentProcess();
  } else {
    hProcess =
        OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid);
  }

  if (GetLastError() == ERROR_ACCESS_DENIED) {
    uid = 0;
    gid = 0;
  }

  result.GetString("Name", r["name"]);
  result.GetString("ExecutablePath", r["path"]);
  result.GetString("CommandLine", r["cmdline"]);
  result.GetString("ExecutionState", r["state"]);
  result.GetLong("ParentProcessId", lPlaceHolder);
  r["parent"] = BIGINT(lPlaceHolder);
  result.GetLong("Priority", lPlaceHolder);
  r["nice"] = INTEGER(lPlaceHolder);
  r["on_disk"] = osquery::pathExists(r["path"]).toString();
  result.GetLong("ThreadCount", lPlaceHolder);
  r["threads"] = INTEGER(lPlaceHolder);

  std::vector<char> fileName(MAX_PATH);
  fileName.assign(MAX_PATH + 1, '\0');
  if (pid == currentPid) {
    GetModuleFileName(nullptr, fileName.data(), MAX_PATH);
  } else {
    GetModuleFileNameEx(hProcess, nullptr, fileName.data(), MAX_PATH);
  }
  r["cwd"] = SQL_TEXT(fileName.data());
  r["root"] = r["cwd"];

  r["pgroup"] = "-1";
  r["euid"] = "-1";
  r["suid"] = "-1";
  r["egid"] = "-1";
  r["sgid"] = "-1";

  FILETIME createTime;
  FILETIME exitTime;
  FILETIME kernelTime;
  FILETIME userTime;
  auto procRet =
      GetProcessTimes(hProcess, &createTime, &exitTime, &kernelTime, &userTime);
  if (procRet == FALSE) {
    r["user_time"] = BIGINT(-1);
    r["system_time"] = BIGINT(-1);
    r["start_time"] = BIGINT(-1);
  } else {
    // Windows stores proc times in 100 nanosecond ticks
    ULARGE_INTEGER utime;
    utime.HighPart = userTime.dwHighDateTime;
    utime.LowPart = userTime.dwLowDateTime;
    r["user_time"] = BIGINT(utime.QuadPart / 10000000);
    utime.HighPart = kernelTime.dwHighDateTime;
    utime.LowPart = kernelTime.dwLowDateTime;
    r["system_time"] = BIGINT(utime.QuadPart / 10000000);
    r["start_time"] = BIGINT(osquery::filetimeToUnixtime(createTime));
  }

  result.GetString("PrivatePageCount", sPlaceHolder);
  r["wired_size"] = BIGINT(sPlaceHolder);
  result.GetString("WorkingSetSize", sPlaceHolder);
  r["resident_size"] = sPlaceHolder;
  result.GetString("VirtualSize", sPlaceHolder);
  r["total_size"] = BIGINT(sPlaceHolder);

  /// Get the process UID and GID from its SID
  HANDLE tok = nullptr;
  std::vector<char> tokOwner(sizeof(TOKEN_OWNER), 0x0);
  auto ret = OpenProcessToken(hProcess, TOKEN_READ, &tok);
  if (ret != 0 && tok != nullptr) {
    unsigned long tokOwnerBuffLen;
    ret = GetTokenInformation(tok, TokenUser, nullptr, 0, &tokOwnerBuffLen);
    if (ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
      tokOwner.resize(tokOwnerBuffLen);
      ret = GetTokenInformation(
          tok, TokenUser, tokOwner.data(), tokOwnerBuffLen, &tokOwnerBuffLen);
    }

    // Check if the process is using an elevated token
    auto elevated = FALSE;
    TOKEN_ELEVATION Elevation;
    DWORD cbSize = sizeof(TOKEN_ELEVATION);
    if (GetTokenInformation(
            tok, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) {
      elevated = Elevation.TokenIsElevated;
    }

    r["is_elevated_token"] = elevated ? INTEGER(1) : INTEGER(0);
  }
  if (uid != 0 && ret != 0 && !tokOwner.empty()) {
    auto sid = PTOKEN_OWNER(tokOwner.data())->Owner;
    r["uid"] = INTEGER(getUidFromSid(sid));
    r["gid"] = INTEGER(getGidFromSid(sid));
  } else {
    r["uid"] = INTEGER(uid);
    r["gid"] = INTEGER(gid);
  }

  if (hProcess != nullptr) {
    CloseHandle(hProcess);
  }
  if (tok != nullptr) {
    CloseHandle(tok);
    tok = nullptr;
  }
  results_data.push_back(r);
}