Example #1
0
Status processRequest(Row& r) {
  try {
    osquery::http::Client client_;
    osquery::http::Response response_;
    osquery::http::Request request_(r["url"]);

    // Change the user-agent for the request to be osquery
    request_ << osquery::http::Request::Header("User-Agent", r["user_agent"]);

    // Measure the rtt using the system clock
    std::chrono::time_point<std::chrono::system_clock> start =
        std::chrono::system_clock::now();
    response_ = client_.get(request_);
    std::chrono::time_point<std::chrono::system_clock> end =
        std::chrono::system_clock::now();

    r["response_code"] = INTEGER(static_cast<int>(response_.status()));
    r["round_trip_time"] = BIGINT(
        std::chrono::duration_cast<std::chrono::microseconds>(end - start)
            .count());
    r["result"] = response_.body();
    r["bytes"] = BIGINT(r["result"].size());
  } catch (const std::exception& e) {
    return Status(1, e.what());
  }

  return Status();
}
Example #2
0
QueryData genProcesses(QueryContext& context) {
  QueryData results;

  proc_t* proc_info;
  PROCTAB* proc = openproc(PROC_SELECTS);

  // Populate proc struc for each process.
  while ((proc_info = readproc(proc, NULL))) {
    Row r;

    r["pid"] = INTEGER(proc_info->tid);
    r["uid"] = BIGINT((unsigned int)proc_info->ruid);
    r["gid"] = BIGINT((unsigned int)proc_info->rgid);
    r["euid"] = BIGINT((unsigned int)proc_info->euid);
    r["egid"] = BIGINT((unsigned int)proc_info->egid);
    r["name"] = proc_name(proc_info);
    r["cmdline"] = proc_cmdline(proc_info);
    r["path"] = proc_link(proc_info);
    r["on_disk"] = osquery::pathExists(r["path"]).toString();

    r["resident_size"] = INTEGER(proc_info->vm_rss);
    r["phys_footprint"] = INTEGER(proc_info->vm_size);
    r["user_time"] = INTEGER(proc_info->utime);
    r["system_time"] = INTEGER(proc_info->stime);
    r["start_time"] = INTEGER(proc_info->start_time);
    r["parent"] = INTEGER(proc_info->ppid);

    results.push_back(r);
    standard_freeproc(proc_info);
  }

  closeproc(proc);

  return results;
}
Example #3
0
/**
 * @brief Entry point for docker_images table.
 */
QueryData genImages(QueryContext& context) {
  QueryData results;
  pt::ptree tree;
  Status s = dockerApi("/images/json", tree);
  if (!s.ok()) {
    VLOG(1) << "Error getting docker images: " << s.what();
    return results;
  }

  for (const auto& entry : tree) {
    try {
      const pt::ptree& node = entry.second;
      Row r;
      r["id"] = node.get<std::string>("Id", "");
      if (r["id"].find("sha256:") == 0) {
        r["id"].erase(0, 7);
      }
      r["created"] = BIGINT(node.get<uint64_t>("Created", 0));
      r["size_bytes"] = BIGINT(node.get<uint64_t>("Size", 0));
      std::string tags;
      for (const auto& tag : node.get_child("RepoTags")) {
        if (!tags.empty()) {
          tags.append(",");
        }
        tags.append(tag.second.data());
      }
      r["tags"] = tags;
      results.push_back(r);
    } catch (const pt::ptree_error& e) {
      VLOG(1) << "Error getting docker image details: " << e.what();
    }
  }

  return results;
}
void getModelSpecificRegisterData(QueryData &results, int cpu_number) {
  auto msr_filename =
    std::string("/dev/cpu/") + std::to_string(cpu_number) + "/msr";

  int fd = open(msr_filename.c_str(), O_RDONLY);
  if (fd < 0) {
    int err = errno;
    TLOG << "Could not open msr file " << msr_filename
         << " check the msr kernel module is enabled.";
    if (err == EACCES) {
      TLOG << "Could not access msr device.  Run osquery as root.";
    }
    return;
  }

  Row r;
  r["processor_number"] = BIGINT(cpu_number);
  for (const msr_record_t &field : fields) {
    uint64_t output;
    ssize_t size = pread(fd, &output, sizeof(uint64_t), field.offset);
    if (size != sizeof(uint64_t)) {
      // Processor does not have a record of this type.
      continue;
    }
    if (field.is_flag) {
      r[field.name] = BIGINT((output & field.mask) ? 1 : 0);
    } else {
      r[field.name] = BIGINT(output & field.mask);
    }
  }
  results.push_back(r);
  close(fd);

  return;
}
void genSocketDescriptor(int pid, int descriptor, QueryData& results) {
  struct socket_fdinfo si;
  if (proc_pidfdinfo(pid,
                     descriptor,
                     PROC_PIDFDSOCKETINFO,
                     &si,
                     PROC_PIDFDSOCKETINFO_SIZE) <= 0) {
    return;
  }

  if (si.psi.soi_family == AF_INET || si.psi.soi_family == AF_INET6) {
    Row r;

    r["pid"] = INTEGER(pid);
    r["fd"] = BIGINT(descriptor);
    r["socket"] = BIGINT(si.psi.soi_so);
    r["path"] = "";

    // Darwin/OSX SOCKINFO_TCP is not IPPROTO_TCP
    if (si.psi.soi_kind == SOCKINFO_TCP) {
      r["protocol"] = INTEGER(6);
    } else {
      r["protocol"] = INTEGER(17);
    }

    // Darwin/OSX AF_INET6 == 30
    if (si.psi.soi_family == AF_INET) {
      r["family"] = INTEGER(2);
    } else {
      r["family"] = INTEGER(10);
    }

    parseNetworkSocket(si, r);
    results.push_back(r);
  } else if (si.psi.soi_family == AF_UNIX) {
    Row r;

    r["pid"] = INTEGER(pid);
    r["socket"] = INTEGER(descriptor);
    r["family"] = "0";
    r["protocol"] = "0";
    r["local_address"] = "";
    r["local_port"] = "0";
    r["remote_address"] = "";
    r["remote_port"] = "0";
    if ((char*)si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path != nullptr) {
      r["path"] = si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path;
    } else {
      r["path"] = "";
    }
    results.push_back(r);
  } else if (si.psi.soi_family == AF_APPLETALK) {
    // AF_APPLETALK = 17
  } else if (si.psi.soi_family == AF_NATM) {
    // AF_NATM = 32
  } else {
    // Unsupported socket type.
  }
}
Example #6
0
void genUser(const struct passwd* pwd, QueryData& results) {
  Row r;
  r["uid"] = BIGINT(pwd->pw_uid);
  r["gid"] = BIGINT(pwd->pw_gid);
  r["uid_signed"] = BIGINT((int32_t)pwd->pw_uid);
  r["gid_signed"] = BIGINT((int32_t)pwd->pw_gid);
  r["username"] = TEXT(pwd->pw_name);
  r["description"] = TEXT(pwd->pw_gecos);
  r["directory"] = TEXT(pwd->pw_dir);
  r["shell"] = TEXT(pwd->pw_shell);
  results.push_back(r);
}
Example #7
0
Status WindowsEventSubscriber::Callback(const ECRef& ec, const SCRef& sc) {
  Row r;
  FILETIME cTime;
  GetSystemTimeAsFileTime(&cTime);
  r["time"] = BIGINT(filetimeToUnixtime(cTime));
  r["datetime"] =
      ec->eventRecord.get("Event.System.TimeCreated.<xmlattr>.SystemTime", "");
  r["source"] = ec->eventRecord.get("Event.System.Channel", "");
  r["provider_name"] =
      ec->eventRecord.get("Event.System.Provider.<xmlattr>.Name", "");
  r["provider_guid"] =
      ec->eventRecord.get("Event.System.Provider.<xmlattr>.Guid", "");
  r["eventid"] = INTEGER(ec->eventRecord.get("Event.System.EventID", -1));
  r["task"] = INTEGER(ec->eventRecord.get("Event.System.Task", -1));
  r["level"] = INTEGER(ec->eventRecord.get("Event.System.Level", -1));
  r["keywords"] = BIGINT(ec->eventRecord.get("Event.System.Keywords", -1));

  /*
   * From the MSDN definition of the Event Schema, each event will have
   * an XML choice element containing the event data, if any. The first
   * iteration enumerates this choice, and the second iteration enumerates
   * all data elements belonging to the choice.
   */
  pt::ptree jsonOut;
  std::map<std::string, std::string> results;
  std::string eventDataType;

  for (const auto& node : ec->eventRecord.get_child("Event", pt::ptree())) {
    /// We have already processed the System event data above
    if (node.first == "System" || node.first == "<xmlattr>") {
      continue;
    }
    eventDataType = node.first;
    parseTree(node.second, results);
  }
  for (const auto& val : results) {
    /// Reconstruct the event format as much as possible
    jsonOut.put(eventDataType + "." + val.first, val.second);
  }

  std::stringstream ss;
  boost::property_tree::write_json(ss, jsonOut, false);

  auto s = ss.str();
  if (s.at(s.size() - 1) == '\n') {
    s.erase(s.end());
  }
  r["data"] = s;

  add(r);
  return Status(0, "OK");
}
Example #8
0
void genFileInfo(const fs::path& path,
                 const fs::path& parent,
                 const std::string& pattern,
                 QueryData& results) {
#ifndef WIN32
  // Must provide the path, filename, directory separate from boost path->string
  // helpers to match any explicit (query-parsed) predicate constraints.
  struct stat file_stat, link_stat;
  if (lstat(path.string().c_str(), &link_stat) < 0 ||
      stat(path.string().c_str(), &file_stat)) {
    // Path was not real, had too may links, or could not be accessed.
    return;
  }

  Row r;
  r["path"] = path.string();
  r["filename"] = path.filename().string();
  r["directory"] = parent.string();

  r["inode"] = BIGINT(file_stat.st_ino);
  r["uid"] = BIGINT(file_stat.st_uid);
  r["gid"] = BIGINT(file_stat.st_gid);
  r["mode"] = lsperms(file_stat.st_mode);
  r["device"] = BIGINT(file_stat.st_rdev);
  r["size"] = BIGINT(file_stat.st_size);
  r["block_size"] = INTEGER(file_stat.st_blksize);
  r["hard_links"] = INTEGER(file_stat.st_nlink);

  // Times
  r["atime"] = BIGINT(file_stat.st_atime);
  r["mtime"] = BIGINT(file_stat.st_mtime);
  r["ctime"] = BIGINT(file_stat.st_ctime);
#if defined(__linux__)
  // No 'birth' or create time in Linux.
  r["btime"] = "0";
#else
  r["btime"] = BIGINT(file_stat.st_birthtimespec.tv_sec);
#endif

  // Type booleans
  boost::system::error_code ec;
  auto status = fs::status(path, ec);
  if (kTypeNames.count(status.type())) {
    r["type"] = kTypeNames.at(status.type());
  } else {
    r["type"] = "unknown";
  }

  r["is_file"] = (!S_ISDIR(file_stat.st_mode)) ? "1" : "0";
  r["is_dir"] = (S_ISDIR(file_stat.st_mode)) ? "1" : "0";
  r["is_link"] = (S_ISLNK(link_stat.st_mode)) ? "1" : "0";
  r["is_char"] = (S_ISCHR(file_stat.st_mode)) ? "1" : "0";
  r["is_block"] = (S_ISBLK(file_stat.st_mode)) ? "1" : "0";
  results.push_back(r);
#endif
}
Example #9
0
QueryData genKextstat(QueryContext &context) {
  QueryData results;

  // Populate dict of kernel extensions.
  CFDictionaryRef dict = OSKextCopyLoadedKextInfo(NULL, NULL);
  CFIndex count = CFDictionaryGetCount(dict);

  // Allocate memory for each extension parse.
  auto values = (void **)malloc(sizeof(void *) * count);
  CFDictionaryGetKeysAndValues(dict, nullptr, (const void **)values);
  for (CFIndex j = 0; j < count; j++) {
    // name
    auto name = getKextString(values[j], CFSTR("CFBundleIdentifier"));
    auto kextTag = getKextInt(values[j], CFSTR("OSBundleLoadTag"));

    // Possibly limit expensive lookups.
    if (!context.constraints["name"].matches(name)) {
      continue;
    }

    if (!context.constraints["idx"].matches<int>(kextTag)) {
      continue;
    }

    auto references = getKextInt(values[j], CFSTR("OSBundleRetainCount"));

    // size
    auto load_size = getKextBigInt(values[j], CFSTR("OSBundleLoadSize"));
    auto wired_size = getKextBigInt(values[j], CFSTR("OSBundleWiredSize"));
    auto version = getKextString(values[j], CFSTR("CFBundleVersion"));

    // linked_against
    auto linked = getKextLinked(values[j], CFSTR("OSBundleDependencies"));

    Row r;
    r["idx"] = INTEGER(kextTag);
    r["refs"] = INTEGER(references);
    r["size"] = BIGINT(load_size);
    r["wired"] = BIGINT(wired_size);
    r["name"] = name;
    r["version"] = version;
    r["linked_against"] = linked;
    results.push_back(r);
  }

  CFRelease(dict);
  free(values);
  return results;
}
Example #10
0
	void Create()
	{
		// 灵活性与高效性并存
		const std::string strSql(
			"CREATE TABLE `AM_TAP_XDR` (	\
				`ID` BIGINT(10) AUTO_INCREMENT,	\
				`XDR_FILE` VARCHAR(256) NOT NULL,	\
				`TOTAL_CDR_COUNT` BIGINT(10) NOT NULL,	\
				`CREATE_TIME` DATETIME NOT NULL,	\
				PRIMARY KEY (`ID`)	\
			)"
		);

		m_pConn->Execute(strSql);
	}
Example #11
0
/**
 * @brief Entry point for docker_containers table.
 */
QueryData genContainers(QueryContext& context) {
  QueryData results;
  std::set<std::string> ids;
  pt::ptree containers;
  Status s = getContainers(context, ids, containers);
  if (!s.ok()) {
    return results;
  }

  for (const auto& entry : containers) {
    const pt::ptree& container = entry.second;
    Row r;
    r["id"] = getValue(container, ids, "Id");
    if (container.count("Names") > 0) {
      for (const auto& name : container.get_child("Names")) {
        r["name"] = name.second.data();
        break;
      }
    }
    r["image_id"] = container.get<std::string>("ImageID", "");
    if (r["image_id"].find("sha256:") == 0) {
      r["image_id"].erase(0, 7);
    }
    r["image"] = container.get<std::string>("Image", "");
    r["command"] = container.get<std::string>("Command", "");
    r["created"] = BIGINT(container.get<uint64_t>("Created", 0));
    r["state"] = container.get<std::string>("State", "");
    r["status"] = container.get<std::string>("Status", "");
    results.push_back(r);
  }

  return results;
}
Example #12
0
/**
 * @brief Utility method to get cumulative value for specified "key" from
 *        child node in provided "tree".
 *
 * @param tree Tree to iterate.
 * @param key Key to look for in the child nodes.
 * @return Cumulative value for "key".
 */
std::string getNetworkBytes(const pt::ptree& tree, const std::string& key) {
  uint64_t value = 0;
  for (const auto& node : tree) {
    value += node.second.get<uint64_t>(key, 0);
  }

  return BIGINT(value);
}
Example #13
0
QueryData genOsquerySchedule(QueryContext& context) {
  QueryData results;

  Config::getInstance().scheduledQueries(
      [&results](const std::string& name, const ScheduledQuery& query) {
        Row r;
        r["name"] = TEXT(name);
        r["query"] = TEXT(query.query);
        r["interval"] = INTEGER(query.interval);
        // Set default (0) values for each query if it has not yet executed.
        r["executions"] = "0";
        r["output_size"] = "0";
        r["wall_time"] = "0";
        r["user_time"] = "0";
        r["system_time"] = "0";
        r["average_memory"] = "0";
        r["last_executed"] = "0";

        // Report optional performance information.
        Config::getInstance().getPerformanceStats(
            name,
            [&r](const QueryPerformance& perf) {
              r["executions"] = BIGINT(perf.executions);
              r["last_executed"] = BIGINT(perf.last_executed);
              r["output_size"] = BIGINT(perf.output_size);
              r["wall_time"] = BIGINT(perf.wall_time);
              r["user_time"] = BIGINT(perf.user_time);
              r["system_time"] = BIGINT(perf.system_time);
              r["average_memory"] = BIGINT(perf.average_memory);
            });

        results.push_back(r);
      });
  return results;
}
Example #14
0
QueryData genSharedMemory(QueryContext &context) {
  QueryData results;

  // Use shared memory control (shmctl) to get the max SHMID.
  struct shm_info shm_info;
  int maxid = shmctl(0, SHM_INFO, (struct shmid_ds *)(void *)&shm_info);
  if (maxid < 0) {
    VLOG(1) << "Linux kernel not configured for shared memory";
    return {};
  }

  // Use a static pointer to access IPC permissions structure.
  struct shmid_ds shmseg;
  struct ipc_perm *ipcp = &shmseg.shm_perm;

  // Then iterate each shared memory ID up to the max.
  for (int id = 0; id <= maxid; id++) {
    int shmid = shmctl(id, SHM_STAT, &shmseg);
    if (shmid < 0) {
      continue;
    }

    Row r;
    r["shmid"] = INTEGER(shmid);

    struct passwd *pw = getpwuid(shmseg.shm_perm.uid);
    if (pw != nullptr) {
      r["owner_uid"] = BIGINT(pw->pw_uid);
    }

    pw = getpwuid(shmseg.shm_perm.cuid);
    if (pw != nullptr) {
      r["creator_uid"] = BIGINT(pw->pw_uid);
    }

    // Accessor, creator pids.
    r["pid"] = BIGINT(shmseg.shm_lpid);
    r["creator_pid"] = BIGINT(shmseg.shm_cpid);

    // Access, detached, creator times
    r["atime"] = BIGINT(shmseg.shm_atime);
    r["dtime"] = BIGINT(shmseg.shm_dtime);
    r["ctime"] = BIGINT(shmseg.shm_ctime);

    r["permissions"] = lsperms(ipcp->mode);
    r["size"] = BIGINT(shmseg.shm_segsz);
    r["attached"] = INTEGER(shmseg.shm_nattch);
    r["status"] = (ipcp->mode & SHM_DEST) ? "dest" : "";
    r["locked"] = (ipcp->mode & SHM_LOCKED) ? "1" : "0";

    results.push_back(r);
  }

  return results;
}
Example #15
0
QueryData genSystemInfo(QueryContext &context) {
  Row r;
  r["hostname"] = osquery::getHostname();
  r["computer_name"] = r["hostname"];

  std::string uuid;
  r["uuid"] = (osquery::getHostUUID(uuid)) ? uuid : "";

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

  // Can parse /proc/cpuinfo or /proc/meminfo for this data.
  static long cores = sysconf(_SC_NPROCESSORS_CONF);
  if (cores > 0) {
    r["cpu_logical_cores"] = INTEGER(cores);
    r["cpu_physical_cores"] = INTEGER(cores);
  } else {
    r["cpu_logical_cores"] = "-1";
    r["cpu_physical_cores"] = "-1";
  }

  static long pages = sysconf(_SC_PHYS_PAGES);
  static long pagesize = sysconf(_SC_PAGESIZE);

  if (pages > 0 && pagesize > 0) {
    r["physical_memory"] = BIGINT((long long)pages * (long long)pagesize);
  } else {
    r["physical_memory"] = "-1";
  }

  r["cpu_type"] = "0";
  r["cpu_subtype"] = "0";
  // Read the types from CPU info within proc.
  std::string content;
  if (readFile("/proc/cpuinfo", content)) {
    for (const auto& line : osquery::split(content, "\n")) {
      // Iterate each line and look for labels (there is also a model type).
      if (line.find("cpu family") == 0 || line.find("model\t") == 0) {
        auto details = osquery::split(line, ":");
        if (details.size() == 2) {
          // Not the most elegant but prevents us from splitting each line.
          r[(line[0] == 'c') ? "cpu_type" : "cpu_subtype"] = details[1];
        }
      }
    }
  }

  // Will require parsing DMI/SMBIOS data.
  r["hardware_model"] = "";
  r["hardware_serial"] = "";
  return {r};
}
Example #16
0
/**
 * @brief Utility method to get cumulative value for specified "op" from
 *        child node in provided "tree".
 *
 * @param tree Tree to iterate.
 * @param op IO operation to look for in the child nodes.
 * @return Cumulative value for type "op".
 */
std::string getIOBytes(const pt::ptree& tree, const std::string& op) {
  uint64_t value = 0;
  for (const auto& entry : tree) {
    const pt::ptree& node = entry.second;
    if (node.get<std::string>("op", "") == op) {
      value += node.get<uint64_t>("value", 0);
    }
  }

  return BIGINT(value);
}
Example #17
0
QueryData genMounts(QueryContext& context) {
  QueryData results;

  struct statfs *mnt;
  int mnts = 0;
  int i;
  char real_path[PATH_MAX];

  mnts = getmntinfo(&mnt, MNT_WAIT);
  if (mnts == 0) {
    // Failed to get mount informaton.
    return results;
  }

  for (i = 0; i < mnts; i++) {
    Row r;
    r["path"] = TEXT(mnt[i].f_mntonname);
    r["device"] = TEXT(mnt[i].f_mntfromname);
    r["device_alias"] = std::string(realpath(mnt[i].f_mntfromname, real_path)
                                        ? real_path
                                        : mnt[i].f_mntfromname);
    r["type"] = TEXT(mnt[i].f_fstypename);
    r["flags"] = INTEGER(mnt[i].f_flags);
    r["blocks"] = BIGINT(mnt[i].f_blocks);
    r["blocks_free"] = BIGINT(mnt[i].f_bfree);
    r["blocks_available"] = BIGINT(mnt[i].f_bavail);
    r["blocks_size"] = BIGINT(mnt[i].f_bsize);
    r["inodes"] = BIGINT(mnt[i].f_files);
    r["inodes_free"] = BIGINT(mnt[i].f_ffree);
    r["owner"] = INTEGER(mnt[i].f_owner);
    results.push_back(r);
  }
  return results;
}
Example #18
0
QueryData genMounts(QueryContext &context) {
  QueryData results;
  FILE *mounts;
  struct mntent *ent;
  char real_path[PATH_MAX];
  struct statfs st;

  if ((mounts = setmntent("/proc/mounts", "r"))) {
    while ((ent = getmntent(mounts))) {
      Row r;

      r["device"] = std::string(ent->mnt_fsname);
      r["device_alias"] = std::string(
          realpath(ent->mnt_fsname, real_path) ? real_path : ent->mnt_fsname);
      r["path"] = std::string(ent->mnt_dir);
      r["type"] = std::string(ent->mnt_type);
      r["flags"] = std::string(ent->mnt_opts);
      if (!statfs(ent->mnt_dir, &st)) {
        r["blocks_size"] = BIGINT(st.f_bsize);
        r["blocks"] = BIGINT(st.f_blocks);
        r["blocks_free"] = BIGINT(st.f_bfree);
        r["blocks_available"] = BIGINT(st.f_bavail);
        r["inodes"] = BIGINT(st.f_files);
        r["inodes_free"] = BIGINT(st.f_ffree);
      }

      results.push_back(r);
    }
    endmntent(mounts);
  }

  return results;
}
Example #19
0
QueryData genCpuTime(QueryContext& context) {
  QueryData results;

  natural_t processor_count;
  processor_cpu_load_info_data_t* processor_times;
  mach_port_t host = mach_host_self();
  mach_msg_type_number_t processor_msg_count;

  kern_return_t ret =
      host_processor_info(host,
                          PROCESSOR_CPU_LOAD_INFO,
                          &processor_count,
                          reinterpret_cast<processor_info_t*>(&processor_times),
                          &processor_msg_count);

  if (ret == KERN_SUCCESS) {
    // Loop through the cores and add rows for each core.
    for (unsigned int core = 0; core < processor_count; core++) {
      Row r;
      r["core"] = INTEGER(core);
      r["user"] = BIGINT(
          ticks_to_usecs(processor_times[core].cpu_ticks[CPU_STATE_USER]));
      r["idle"] = BIGINT(
          ticks_to_usecs(processor_times[core].cpu_ticks[CPU_STATE_IDLE]));
      r["system"] = BIGINT(
          ticks_to_usecs(processor_times[core].cpu_ticks[CPU_STATE_SYSTEM]));
      r["nice"] = BIGINT(
          ticks_to_usecs(processor_times[core].cpu_ticks[CPU_STATE_NICE]));

      results.push_back(r);
    }
    vm_deallocate(
        mach_task_self(),
        reinterpret_cast<vm_address_t>(processor_times),
        static_cast<vm_size_t>(processor_count * sizeof(*processor_times)));
  }
  return results;
}
Example #20
0
void genProcessMap(const std::string& pid, QueryData& results) {
  auto map = getProcAttr("maps", pid);

  std::string content;
  readFile(map, content);
  for (auto& line : osquery::split(content, "\n")) {
    auto fields = osquery::split(line, " ");
    // If can't read address, not sure.
    if (fields.size() < 5) {
      continue;
    }

    Row r;
    r["pid"] = pid;
    if (!fields[0].empty()) {
      auto addresses = osquery::split(fields[0], "-");
      if (addresses.size() >= 2) {
        r["start"] = "0x" + addresses[0];
        r["end"] = "0x" + addresses[1];
      } else {
        // Problem with the address format.
        continue;
      }
    }

    r["permissions"] = fields[1];
    try {
      auto offset = std::stoll(fields[2], nullptr, 16);
      r["offset"] = (offset != 0) ? BIGINT(offset) : r["start"];

    } catch (const std::exception& e) {
      // Value was out of range or could not be interpreted as a hex long long.
      r["offset"] = "-1";
    }
    r["device"] = fields[3];
    r["inode"] = fields[4];

    // Path name must be trimmed.
    if (fields.size() > 5) {
      boost::trim(fields[5]);
      r["path"] = fields[5];
    }

    // BSS with name in pathname.
    r["pseudo"] = (fields[4] == "0" && !r["path"].empty()) ? "1" : "0";
    results.push_back(std::move(r));
  }
}
Example #21
0
QueryData genUptime(QueryContext& context) {
    Row r;
    QueryData results;
    long uptime_in_seconds = getUptime();

    if (uptime_in_seconds >= 0) {
        r["days"] = INTEGER(uptime_in_seconds / 60 / 60 / 24);
        r["hours"] = INTEGER((uptime_in_seconds / 60 / 60) % 24);
        r["minutes"] = INTEGER((uptime_in_seconds / 60) % 60);
        r["seconds"] = INTEGER(uptime_in_seconds % 60);
        r["total_seconds"] = BIGINT(uptime_in_seconds);
        results.push_back(r);
    }

    return results;
}
Example #22
0
void genFileInfo(const std::string& path,
                 const std::string& filename,
                 const std::string& dir,
                 const std::string& pattern,
                 QueryData& results) {
  // Must provide the path, filename, directory separate from boost path->string
  // helpers to match any explicit (query-parsed) predicate constraints.
  struct stat file_stat, link_stat;
  if (lstat(path.c_str(), &link_stat) < 0 || stat(path.c_str(), &file_stat)) {
    // Path was not real, had too may links, or could not be accessed.
    return;
  }

  Row r;
  r["path"] = path;
  r["filename"] = filename;
  r["directory"] = dir;

  r["inode"] = BIGINT(file_stat.st_ino);
  r["uid"] = BIGINT(file_stat.st_uid);
  r["gid"] = BIGINT(file_stat.st_gid);
  r["mode"] = lsperms(file_stat.st_mode);
  r["device"] = BIGINT(file_stat.st_rdev);
  r["size"] = BIGINT(file_stat.st_size);
  r["block_size"] = INTEGER(file_stat.st_blksize);
  r["hard_links"] = INTEGER(file_stat.st_nlink);

  // Times
  r["atime"] = BIGINT(file_stat.st_atime);
  r["mtime"] = BIGINT(file_stat.st_mtime);
  r["ctime"] = BIGINT(file_stat.st_ctime);

  // Type booleans
  r["is_file"] = (!S_ISDIR(file_stat.st_mode)) ? "1" : "0";
  r["is_dir"] = (S_ISDIR(file_stat.st_mode)) ? "1" : "0";
  r["is_link"] = (S_ISLNK(link_stat.st_mode)) ? "1" : "0";
  r["is_char"] = (S_ISCHR(file_stat.st_mode)) ? "1" : "0";
  r["is_block"] = (S_ISBLK(file_stat.st_mode)) ? "1" : "0";

  // pattern
  r["pattern"] = pattern;

  results.push_back(r);
}
Example #23
0
void genFDEStatusForBSDName(const std::string& bsd_name,
                            const std::string& uuid,
                            QueryData& results) {

  auto matching_dict =
      IOBSDNameMatching(kIOMasterPortDefault, kNilOptions, bsd_name.c_str());
  if (matching_dict == nullptr) {
    return;
  }

  auto service =
      IOServiceGetMatchingService(kIOMasterPortDefault, matching_dict);
  if (!service) {
    return;
  }

  CFMutableDictionaryRef properties;
  if (IORegistryEntryCreateCFProperties(
          service, &properties, kCFAllocatorDefault, kNilOptions) !=
      KERN_SUCCESS) {
    IOObjectRelease(service);
    return;
  }

  Row r;
  r["name"] = kDeviceNamePrefix + bsd_name;
  r["uuid"] = uuid;

  auto encrypted = getIOKitProperty(properties, kCoreStorageIsEncryptedKey_);
  if (encrypted.empty()) {
    r["encrypted"] = "0";
  } else {
    r["encrypted"] = encrypted;
    id_t uid;
    uuid_string_t uuid_string = {0};
    if (genUid(uid, uuid_string).ok()) {
      r["uid"] = BIGINT(uid);
      r["user_uuid"] = TEXT(uuid_string);
    }
  }
  r["type"] = (r.at("encrypted") == "1") ? kEncryptionType : std::string();

  results.push_back(r);
  CFRelease(properties);
  IOObjectRelease(service);
}
Example #24
0
void genSMBIOSTables(const uint8_t* tables, size_t length, QueryData& results) {
  // Keep a pointer to the end of the SMBIOS data for comparison.
  auto tables_end = tables + length;
  auto table = tables;

  // Iterate through table structures within SMBIOS data range.
  size_t index = 0;
  while (table + sizeof(SMBStructHeader) <= tables_end) {
    auto header = (const SMBStructHeader*)table;
    if (table + header->length > tables_end) {
      // Invalid header, length must be within SMBIOS data range.
      break;
    }

    Row r;
    // The index is a supliment that keeps track of table order.
    r["number"] = INTEGER(index++);
    r["type"] = INTEGER((unsigned short)header->type);
    if (kSMBIOSTypeDescriptions.count(header->type) > 0) {
      r["description"] = kSMBIOSTypeDescriptions.at(header->type);
    }

    r["handle"] = BIGINT((unsigned long long)header->handle);
    r["header_size"] = INTEGER((unsigned short)header->length);

    // The SMBIOS structure may have unformatted, double-NULL delimited trailing
    // data, which are usually strings.
    auto next_table = table + header->length;
    for (; next_table + sizeof(SMBStructHeader) <= tables_end; next_table++) {
      if (next_table[0] == 0 && next_table[1] == 0) {
        next_table += 2;
        break;
      }
    }

    auto table_length = next_table - table;
    r["size"] = INTEGER(table_length);
    r["md5"] = hashFromBuffer(HASH_TYPE_MD5, table, table_length);

    table = next_table;
    results.push_back(r);
  }
}
Example #25
0
void genSMBIOSTable(size_t index,
                    const SMBStructHeader* hdr,
                    uint8_t* address,
                    size_t size,
                    QueryData& results) {
  Row r;
  // The index is a supliment that keeps track of table order.
  r["number"] = INTEGER(index++);
  r["type"] = INTEGER((unsigned short)hdr->type);
  if (kSMBIOSTypeDescriptions.count(hdr->type) > 0) {
    r["description"] = kSMBIOSTypeDescriptions.at(hdr->type);
  } else {
    r["description"] = "Unknown";
  }

  r["handle"] = BIGINT((unsigned long long)hdr->handle);
  r["header_size"] = INTEGER((unsigned short)hdr->length);

  r["size"] = INTEGER(size);
  r["md5"] = hashFromBuffer(HASH_TYPE_MD5, address, size);
  results.push_back(r);
}
Example #26
0
/**
 * @brief Return a string representation of the RPM tag type.
 *
 * @param header A librpm header.
 * @param tag A librpm rpmTag_t name.
 * @param td A librpm rpmtd.
 *
 * Given a librpm iterator header and a requested tag name:
 * 1. Determine the type of the tag (the class of value).
 * 2. Request a const pointer or cast of numerate to that class.
 * 3. Lexical-cast the value for SQL.
 *
 * @return The string representation of the tag type.
 */
static std::string getRpmAttribute(const Header& header,
                                   rpmTag tag,
                                   const rpmtd& td) {
  std::string result;
  if (headerGet(header, tag, td, HEADERGET_DEFAULT) == 0) {
    // Intentional check for a 0 = failure.
    TLOG << "Could not get RPM header flag.";
    return result;
  }

  if (rpmTagGetClass(tag) == RPM_NUMERIC_CLASS) {
    long long int attr = rpmtdGetNumber(td);
    result = BIGINT(attr);
  } else if (rpmTagGetClass(tag) == RPM_STRING_CLASS) {
    const char* attr = rpmtdGetString(td);
    if (attr != nullptr) {
      result = TEXT(attr);
    }
  }

  return result;
}
Example #27
0
/**
 * @brief Entry point for docker_networks table.
 */
QueryData genNetworks(QueryContext& context) {
  std::string query;
  std::set<std::string> ids;
  getQuery(context, "id", query, ids, false);

  QueryData results;
  pt::ptree tree;
  Status s = dockerApi("/networks" + query, tree);
  if (!s.ok()) {
    VLOG(1) << "Error getting docker networks: " << s.what();
    return results;
  }

  for (const auto& entry : tree) {
    try {
      const pt::ptree& node = entry.second;
      Row r;
      r["id"] = getValue(node, ids, "Id");
      r["name"] = node.get<std::string>("Name", "");
      r["driver"] = node.get<std::string>("Driver", "");
      r["created"] =
          BIGINT(getUnixTime(node.get<std::string>("Created", ""), true));
      r["enable_ipv6"] =
          (node.get<bool>("EnableIPv6", false) ? INTEGER(1) : INTEGER(0));
      for (const auto& config : node.get_child("IPAM.Config")) {
        const pt::ptree& details = config.second;
        r["subnet"] = details.get<std::string>("Subnet", "");
        r["gateway"] = details.get<std::string>("Gateway", "");
        break;
      }
      results.push_back(r);
    } catch (const pt::ptree_error& e) {
      VLOG(1) << "Error getting docker network details: " << e.what();
    }
  }

  return results;
}
Example #28
0
void genProcessMap(const std::string& pid, QueryData& results) {
  auto map = getProcAttr("maps", pid);

  std::string content;
  readFile(map, content);
  for (auto& line : osquery::split(content, "\n")) {
    auto fields = osquery::split(line, " ");

    Row r;
    r["pid"] = pid;

    // If can't read address, not sure.
    if (fields.size() < 5) {
      continue;
    }

    if (fields[0].size() > 0) {
      auto addresses = osquery::split(fields[0], "-");
      r["start"] = "0x" + addresses[0];
      r["end"] = "0x" + addresses[1];
    }

    r["permissions"] = fields[1];
    r["offset"] = BIGINT(std::stoll(fields[2], nullptr, 16));
    r["device"] = fields[3];
    r["inode"] = fields[4];

    // Path name must be trimmed.
    if (fields.size() > 5) {
      boost::trim(fields[5]);
      r["path"] = fields[5];
    }

    // BSS with name in pathname.
    r["pseudo"] = (fields[4] == "0" && r["path"].size() > 0) ? "1" : "0";
    results.push_back(r);
  }
}
void genIOKitDevice(const io_service_t& device,
                    const io_service_t& parent,
                    const io_name_t plane,
                    int depth,
                    QueryData& results) {
  Row r;
  io_name_t name, device_class;
  auto kr = IORegistryEntryGetName(device, name);
  if (kr == KERN_SUCCESS) {
    r["name"] = std::string(name);
  }

  // Get the device class.
  kr = IOObjectGetClass(device, device_class);
  if (kr == KERN_SUCCESS) {
    r["class"] = std::string(device_class);
  }

  // The entry into the registry is the ID, and is used for children as parent.
  uint64_t device_id, parent_id;
  kr = IORegistryEntryGetRegistryEntryID(device, &device_id);
  if (kr == KERN_SUCCESS) {
    r["id"] = BIGINT(device_id);
  } else {
    r["id"] = "-1";
  }

  kr = IORegistryEntryGetRegistryEntryID(parent, &parent_id);
  if (kr == KERN_SUCCESS) {
    r["parent"] = BIGINT(parent_id);
  } else {
    r["parent"] = "-1";
  }

  r["depth"] = INTEGER(depth);

  if (IORegistryEntryInPlane(device, kIODeviceTreePlane)) {
    io_string_t device_path;
    kr = IORegistryEntryGetPath(device, kIODeviceTreePlane, device_path);
    if (kr == KERN_SUCCESS) {
      // Remove the "IODeviceTree:" from the device tree path.
      r["device_path"] = std::string(device_path).substr(13);
    }
  }

  // Fill in service bits and busy/latency time.
  if (IOObjectConformsTo(device, "IOService")) {
    r["service"] = "1";
  } else {
    r["service"] = "0";
  }

  uint32_t busy_state;
  kr = IOServiceGetBusyState(device, &busy_state);
  if (kr == KERN_SUCCESS) {
    r["busy_state"] = INTEGER(busy_state);
  } else {
    r["busy_state"] = "0";
  }

  auto retain_count = IOObjectGetKernelRetainCount(device);
  r["retain_count"] = INTEGER(retain_count);

  results.push_back(r);
}
Example #30
0
QueryData genUsers(QueryContext& context) {
  QueryData results;

  // USER_INFO_3 conains generic user information
  LPUSER_INFO_3 pUserBuffer = nullptr;
  DWORD dwGenericUserLevel = 3;
  DWORD dwPreferredMaxLength = MAX_PREFERRED_LENGTH;
  DWORD dwEntriesRead = 0;
  DWORD dwTotalEntries = 0;
  DWORD dwResumeHandle = 0;
  NET_API_STATUS nEnumStatus;

  nEnumStatus = NetUserEnum(nullptr,
                            dwGenericUserLevel,
                            FILTER_NORMAL_ACCOUNT,
                            (LPBYTE*)&pUserBuffer,
                            dwPreferredMaxLength,
                            &dwEntriesRead,
                            &dwTotalEntries,
                            &dwResumeHandle);

  // We save the original pointer to the USER_INFO_3 buff for mem management
  LPUSER_INFO_3 pUserIterationBuffer = pUserBuffer;
  if (pUserIterationBuffer == nullptr || nEnumStatus != NERR_Success) {
    if (pUserBuffer != nullptr) {
      NetApiBufferFree(pUserBuffer);
    }
    return results;
  }

  for (DWORD i = 0; i < dwEntriesRead; i++) {
    Row r;
    r["username"] = wstringToString(pUserIterationBuffer->usri3_name);
    r["description"] = wstringToString(pUserIterationBuffer->usri3_comment);
    r["uid"] = BIGINT(pUserIterationBuffer->usri3_user_id);
    r["gid"] = BIGINT(pUserIterationBuffer->usri3_primary_group_id);
    r["uid_signed"] = r["uid"];
    r["gid_signed"] = r["gid"];
    r["shell"] = "C:\\Windows\\system32\\cmd.exe";

    // USER_INFO_23 contains detailed info, like the user Sid
    DWORD dwDetailedUserLevel = 23;
    LPUSER_INFO_23 pSidUserBuffer = nullptr;
    NET_API_STATUS nStatus;
    nStatus = NetUserGetInfo(nullptr,
                             pUserIterationBuffer->usri3_name,
                             dwDetailedUserLevel,
                             (LPBYTE*)&pSidUserBuffer);
    if (nStatus != NERR_Success) {
      if (pSidUserBuffer != nullptr) {
        NetApiBufferFree(pSidUserBuffer);
        pSidUserBuffer = nullptr;
      }
      continue;
    }

    LPTSTR sStringSid = nullptr;
    auto ret =
        ConvertSidToStringSid(pSidUserBuffer->usri23_user_sid, &sStringSid);
    if (ret == 0) {
      if (pSidUserBuffer != nullptr) {
        NetApiBufferFree(pSidUserBuffer);
      }
      continue;
    }
    r["uuid"] = sStringSid;
    std::string query = "SELECT LocalPath FROM Win32_UserProfile where SID=\"" +
                        std::string(sStringSid) + "\"";
    WmiRequest wmiRequest(query);
    std::vector<WmiResultItem>& wmiResults = wmiRequest.results();
    if (wmiResults.size() != 0) {
      wmiResults[0].GetString("LocalPath", r["directory"]);
    }
    LocalFree(sStringSid);
    NetApiBufferFree(pSidUserBuffer);

    results.push_back(r);
    pUserIterationBuffer++;
  }
  NetApiBufferFree(pUserBuffer);

  if (nEnumStatus == ERROR_MORE_DATA) {
    LOG(WARNING)
        << "NetUserEnum contains more data: users table may be incomplete";
  }

  return results;
}