示例#1
0
文件: yara.cpp 项目: eastebry/osquery
QueryData genYara(QueryContext& context) {
  QueryData results;
  Status status;

  auto paths = context.constraints["path"].getAll(EQUALS);
  auto patterns = context.constraints["pattern"].getAll(EQUALS);
  auto groups = context.constraints["sig_group"].getAll(EQUALS);
  auto sigfiles = context.constraints["sigfile"].getAll(EQUALS);

  // Must specify a path constraint and at least one of sig_group or sigfile.
  if (groups.size() == 0 && sigfiles.size() == 0) {
    return results;
  }

  // XXX: Abstract this into a common "get rules for group" function.
  ConfigDataInstance config;
  const auto& parser = config.getParser("yara");
  if (parser == nullptr) {
    return results;
  }
  const auto& yaraParser = std::static_pointer_cast<YARAConfigParserPlugin>(parser);
  if (yaraParser == nullptr) {
    return results;
  }
  auto rules = yaraParser->rules();

  // Store resolved paths in a vector of pairs.
  // Each pair has the first element as the path to scan and the second
  // element as the pattern which generated it.
  std::vector<std::pair<std::string, std::string> > path_pairs;

  // Expand patterns and push onto path_pairs.
  for (const auto& pattern : patterns) {
    std::vector<std::string> expanded_patterns;
    auto status = resolveFilePattern(pattern, expanded_patterns);
    if (!status.ok()) {
      VLOG(1) << "Could not expand pattern properly: " << status.toString();
      return results;
    }

    for (const auto& resolved : expanded_patterns) {
      if (!isReadable(resolved)) {
        continue;
      }
      path_pairs.push_back(make_pair(resolved, pattern));
    }
  }

  // Collect all paths specified too.
  for (const auto& path_string : paths) {
    if (!isReadable(path_string)) {
      continue;
    }
    path_pairs.push_back(make_pair(path_string, ""));
  }

  // Compile all sigfiles into a map.
  std::map<std::string, YR_RULES*> compiled_rules;
  for (const auto& file : sigfiles) {
    YR_RULES *rules = nullptr;

    std::string full_path;
    if (file[0] != '/') {
      full_path = std::string("/etc/osquery/yara/") + file;
    } else {
      full_path = file;
    }

    status = compileSingleFile(full_path, &rules);
    if (!status.ok()) {
      VLOG(1) << "YARA error: " << status.toString();
    } else {
      compiled_rules[file] = rules;
    }
  }

  // Scan every path pair.
  for (const auto& path_pair : path_pairs) {
    // Scan using siggroups.
    for (const auto& group : groups) {
      if (rules.count(group) == 0) {
        continue;
      }

      VLOG(1) << "Scanning with group: " << group;
      status = doYARAScan(rules[group],
                          path_pair.first.c_str(),
                          path_pair.second,
                          results,
                          group,
                          "");
      if (!status.ok()) {
        VLOG(1) << "YARA error: " << status.toString();
      }
    }

    // Scan using files.
    for (const auto& element : compiled_rules) {
      VLOG(1) << "Scanning with file: " << element.first;
      status = doYARAScan(element.second,
                          path_pair.first.c_str(),
                          path_pair.second,
                          results,
                          "",
                          element.first);
      if (!status.ok()) {
        VLOG(1) << "YARA error: " << status.toString();
      }
    }
  }

  // Cleanup compiled rules
  for (const auto& element : compiled_rules) {
    yr_rules_destroy(element.second);
  }

  return results;
}
示例#2
0
QueryData genYara(QueryContext& context) {
  QueryData results;

  auto paths = context.constraints["path"].getAll(EQUALS);
  auto patterns = context.constraints["pattern"].getAll(EQUALS);
  auto groups = context.constraints["sig_group"].getAll(EQUALS);
  auto sigfiles = context.constraints["sigfile"].getAll(EQUALS);

  // Must specify a path constraint and at least one of sig_group or sigfile.
  if (groups.size() == 0 && sigfiles.size() == 0) {
    return results;
  }

  // XXX: Abstract this into a common "get rules for group" function.
  auto parser = Config::getParser("yara");
  if (parser == nullptr || parser.get() == nullptr) {
    LOG(ERROR) << "YARA config parser plugin has no pointer";
    return results;
  }

  std::shared_ptr<YARAConfigParserPlugin> yaraParser;
  try {
    yaraParser = std::dynamic_pointer_cast<YARAConfigParserPlugin>(parser);
  } catch (const std::bad_cast& e) {
    LOG(ERROR) << "Error casting yara config parser plugin";
    return results;
  }
  if (yaraParser == nullptr || yaraParser.get() == nullptr) {
    LOG(ERROR) << "YARA config parser plugin has no pointer";
    return results;
  }

  auto& rules = yaraParser->rules();

  // Store resolved paths in a vector of pairs.
  // Each pair has the first element as the path to scan and the second
  // element as the pattern which generated it.
  std::vector<std::pair<std::string, std::string> > path_pairs;

  // Expand patterns and push onto path_pairs.
  for (const auto& pattern : patterns) {
    std::vector<std::string> expanded_patterns;
    auto status = resolveFilePattern(pattern, expanded_patterns);
    if (!status.ok()) {
      VLOG(1) << "Could not expand pattern properly: " << status.toString();
      return results;
    }

    for (const auto& resolved : expanded_patterns) {
      if (!isReadable(resolved)) {
        continue;
      }
      path_pairs.push_back(make_pair(resolved, pattern));
    }
  }

  // Collect all paths specified too.
  for (const auto& path_string : paths) {
    if (!isReadable(path_string)) {
      continue;
    }
    path_pairs.push_back(make_pair(path_string, ""));
  }

  // Compile all sigfiles into a map.
  for (const auto& file : sigfiles) {
    // Check if this on-demand sigfile has not been used/compiled.
    if (rules.count(file) == 0) {
      auto path = (file[0] != '/') ? std::string("/etc/osquery/yara/") : "";
      path += file;

      YR_RULES* tmp_rules = nullptr;
      auto status = compileSingleFile(path, &tmp_rules);
      if (!status.ok()) {
        VLOG(1) << "YARA error: " << status.toString();
      } else {
        rules[file] = tmp_rules;
        groups.insert(file);
      }
    }
  }

  // Scan every path pair.
  for (const auto& path_pair : path_pairs) {
    // Scan using siggroups.
    for (const auto& group : groups) {
      if (rules.count(group) == 0) {
        continue;
      }

      VLOG(1) << "Scanning with group: " << group;
      auto status = doYARAScan(rules[group],
                               path_pair.first.c_str(),
                               path_pair.second,
                               results,
                               group,
                               group);
      if (!status.ok()) {
        VLOG(1) << "YARA error: " << status.toString();
      }
    }
  }

  return results;
}
示例#3
0
文件: yara.cpp 项目: tburgin/osquery
QueryData genYara(QueryContext& context) {
  QueryData results;

  // Must specify a path constraint and at least one of sig_group or sigfile.
  auto groups = context.constraints["sig_group"].getAll(EQUALS);
  auto sigfiles = context.constraints["sigfile"].getAll(EQUALS);
  if (groups.size() == 0 && sigfiles.size() == 0) {
    return results;
  }

  // This could be abstracted into a common "get rules for group" function.
  auto parser = Config::getParser("yara");
  if (parser == nullptr || parser.get() == nullptr) {
    LOG(ERROR) << "YARA config parser plugin has no pointer";
    return results;
  }

  std::shared_ptr<YARAConfigParserPlugin> yaraParser = nullptr;
  try {
    yaraParser = std::dynamic_pointer_cast<YARAConfigParserPlugin>(parser);
  } catch (const std::bad_cast& e) {
    LOG(ERROR) << "Error casting yara config parser plugin";
    return results;
  }
  if (yaraParser == nullptr || yaraParser.get() == nullptr) {
    LOG(ERROR) << "YARA config parser plugin has no pointer";
    return results;
  }

  auto& rules = yaraParser->rules();

  // Store resolved paths in a vector of pairs.
  // Each pair has the first element as the path to scan and the second
  // element as the pattern which generated it.
  std::vector<std::pair<std::string, std::string> > path_pairs;

  // Expand patterns and push onto path_pairs.
  auto patterns = context.constraints["pattern"].getAll(EQUALS);
  for (const auto& pattern : patterns) {
    std::vector<std::string> expanded_patterns;
    if (!resolveFilePattern(pattern, expanded_patterns).ok()) {
      continue;
    }
    // Check that each resolved path is readable.
    for (const auto& resolved : expanded_patterns) {
      if (isReadable(resolved)) {
        path_pairs.push_back(make_pair(resolved, pattern));
      }
    }
  }

  // Collect all paths specified too.
  auto paths = context.constraints["path"].getAll(EQUALS);
  for (const auto& path_string : paths) {
    if (isReadable(path_string)) {
      path_pairs.push_back(make_pair(path_string, ""));
    }
  }

  // Compile all sigfiles into a map.
  for (const auto& file : sigfiles) {
    // Check if this "ad-hoc" signature file has not been used/compiled.
    if (rules.count(file) == 0) {
      // If this is a relative path append the default yara search path.
      auto path = (file[0] != '/') ? std::string("/etc/osquery/yara/") : "";
      path += file;

      YR_RULES* tmp_rules = nullptr;
      auto status = compileSingleFile(path, &tmp_rules);
      if (!status.ok()) {
        VLOG(1) << "YARA compile error: " << status.toString();
        continue;
      }
      // Cache the compiled rules by setting the unique signature file path
      // as the lookup name. Additional signature file uses will skip the
      // compile step and be added as rule groups.
      rules[file] = tmp_rules;
    }
    // Assemble an "ad-hoc" group using the signature file path as the name.
    groups.insert(file);
  }

  // Scan every path pair.
  for (const auto& path_pair : path_pairs) {
    // Scan using the signature groups.
    for (const auto& group : groups) {
      if (rules.count(group) > 0) {
        doYARAScan(rules[group],
                   path_pair.first.c_str(),
                   path_pair.second,
                   results,
                   group,
                   group);
      }
    }
  }

  return results;
}