YR_RULES* compile_rule( char* string) { YR_COMPILER* compiler = NULL; YR_RULES* rules = NULL; compile_error[0] = '\0'; if (yr_compiler_create(&compiler) != ERROR_SUCCESS) { perror("yr_compiler_create"); goto _exit; } yr_compiler_set_callback(compiler, callback_function, NULL); if (yr_compiler_add_string(compiler, string, NULL) != 0) { goto _exit; } if (yr_compiler_get_rules(compiler, &rules) != ERROR_SUCCESS) { goto _exit; } _exit: yr_compiler_destroy(compiler); return rules; }
int compile_rule( char* string, YR_RULES** rules) { YR_COMPILER* compiler = NULL; int result = ERROR_SUCCESS; compile_error[0] = '\0'; if (yr_compiler_create(&compiler) != ERROR_SUCCESS) { perror("yr_compiler_create"); goto _exit; } yr_compiler_set_callback(compiler, callback_function, NULL); if (yr_compiler_add_string(compiler, string, NULL) != 0) { result = compiler->last_error; goto _exit; } result = yr_compiler_get_rules(compiler, rules); _exit: yr_compiler_destroy(compiler); return result; }
/** * Compile a single rule file and load it into rule pointer. */ Status compileSingleFile(const std::string& file, YR_RULES** rules) { YR_COMPILER *compiler = nullptr; int result = yr_compiler_create(&compiler); if (result != ERROR_SUCCESS) { VLOG(1) << "Could not create compiler: " + std::to_string(result); return Status(1, "Could not create compiler: " + std::to_string(result)); } yr_compiler_set_callback(compiler, YARACompilerCallback, nullptr); bool compiled = false; YR_RULES *tmp_rules; VLOG(1) << "Loading " << file; // First attempt to load the file, in case it is saved (pre-compiled) // rules. // // If you want to use saved rule files you must have them all in a single // file. This is easy to accomplish with yarac(1). result = yr_rules_load(file.c_str(), &tmp_rules); if (result != ERROR_SUCCESS && result != ERROR_INVALID_FILE) { yr_compiler_destroy(compiler); return Status(1, "Error loading YARA rules: " + std::to_string(result)); } else if (result == ERROR_SUCCESS) { *rules = tmp_rules; } else { compiled = true; // Try to compile the rules. FILE *rule_file = fopen(file.c_str(), "r"); if (rule_file == nullptr) { yr_compiler_destroy(compiler); return Status(1, "Could not open file: " + file); } int errors = yr_compiler_add_file(compiler, rule_file, nullptr, file.c_str()); fclose(rule_file); rule_file = nullptr; if (errors > 0) { yr_compiler_destroy(compiler); // Errors printed via callback. return Status(1, "Compilation errors"); } } if (compiled) { // All the rules for this category have been compiled, save them in the map. result = yr_compiler_get_rules(compiler, *(&rules)); if (result != ERROR_SUCCESS) { yr_compiler_destroy(compiler); return Status(1, "Insufficient memory to get YARA rules"); } } if (compiler != nullptr) { yr_compiler_destroy(compiler); compiler = nullptr; } return Status(0, "OK"); }
/** * Given a vector of strings, attempt to compile them and store the result * in the map under the given category. */ Status handleRuleFiles(const std::string& category, const pt::ptree& rule_files, std::map<std::string, YR_RULES*>* rules) { YR_COMPILER *compiler = nullptr; int result = yr_compiler_create(&compiler); if (result != ERROR_SUCCESS) { VLOG(1) << "Could not create compiler: " + std::to_string(result); return Status(1, "Could not create compiler: " + std::to_string(result)); } yr_compiler_set_callback(compiler, YARACompilerCallback, nullptr); bool compiled = false; for (const auto& item : rule_files) { YR_RULES *tmp_rules; const auto rule = item.second.get("", ""); VLOG(1) << "Loading " << rule; std::string full_path; if (rule[0] != '/') { full_path = std::string("/etc/osquery/yara/") + rule; } else { full_path = rule; } // First attempt to load the file, in case it is saved (pre-compiled) // rules. Sadly there is no way to load multiple compiled rules in // succession. This means that: // // saved1, saved2 // results in saved2 being the only file used. // // Also, mixing source and saved rules results in the saved rules being // overridden by the combination of the source rules once compiled, e.g.: // // file1, saved1 // result in file1 being the only file used. // // If you want to use saved rule files you must have them all in a single // file. This is easy to accomplish with yarac(1). result = yr_rules_load(full_path.c_str(), &tmp_rules); if (result != ERROR_SUCCESS && result != ERROR_INVALID_FILE) { yr_compiler_destroy(compiler); return Status(1, "Error loading YARA rules: " + std::to_string(result)); } else if (result == ERROR_SUCCESS) { // If there are already rules there, destroy them and put new ones in. if (rules->count(category) > 0) { yr_rules_destroy((*rules)[category]); } (*rules)[category] = tmp_rules; } else { compiled = true; // Try to compile the rules. FILE *rule_file = fopen(full_path.c_str(), "r"); if (rule_file == nullptr) { yr_compiler_destroy(compiler); return Status(1, "Could not open file: " + full_path); } int errors = yr_compiler_add_file(compiler, rule_file, nullptr, full_path.c_str()); fclose(rule_file); rule_file = nullptr; if (errors > 0) { yr_compiler_destroy(compiler); // Errors printed via callback. return Status(1, "Compilation errors"); } } } if (compiled) { // All the rules for this category have been compiled, save them in the map. result = yr_compiler_get_rules(compiler, &((*rules)[category])); if (result != ERROR_SUCCESS) { yr_compiler_destroy(compiler); return Status(1, "Insufficient memory to get YARA rules"); } } if (compiler != nullptr) { yr_compiler_destroy(compiler); compiler = nullptr; } return Status(0, "OK"); }
int main( int argc, const char** argv) { COMPILER_RESULTS cr; YR_COMPILER* compiler = NULL; YR_RULES* rules = NULL; int result; argc = args_parse(options, argc, argv); if (show_version) { printf("%s\n", YR_VERSION); return EXIT_SUCCESS; } if (show_help) { printf("%s\n\n", USAGE_STRING); args_print_usage(options, 35); printf("\nSend bug reports and suggestions to: [email protected]\n"); return EXIT_SUCCESS; } if (argc < 2) { fprintf(stderr, "yarac: wrong number of arguments\n"); fprintf(stderr, "%s\n\n", USAGE_STRING); fprintf(stderr, "Try `--help` for more options\n"); exit_with_code(EXIT_FAILURE); } result = yr_initialize(); if (result != ERROR_SUCCESS) exit_with_code(EXIT_FAILURE); if (yr_compiler_create(&compiler) != ERROR_SUCCESS) exit_with_code(EXIT_FAILURE); if (!define_external_variables(compiler)) exit_with_code(EXIT_FAILURE); cr.errors = 0; cr.warnings = 0; yr_set_configuration(YR_CONFIG_MAX_STRINGS_PER_RULE, &max_strings_per_rule); yr_compiler_set_callback(compiler, report_error, &cr); if (!compile_files(compiler, argc, argv)) exit_with_code(EXIT_FAILURE); if (cr.errors > 0) exit_with_code(EXIT_FAILURE); if (fail_on_warnings && cr.warnings > 0) exit_with_code(EXIT_FAILURE); result = yr_compiler_get_rules(compiler, &rules); if (result != ERROR_SUCCESS) { fprintf(stderr, "error: %d\n", result); exit_with_code(EXIT_FAILURE); } result = yr_rules_save(rules, argv[argc - 1]); if (result != ERROR_SUCCESS) { fprintf(stderr, "error: %d\n", result); exit_with_code(EXIT_FAILURE); } result = EXIT_SUCCESS; _exit: if (compiler != NULL) yr_compiler_destroy(compiler); if (rules != NULL) yr_rules_destroy(rules); yr_finalize(); return result; }
bool Yara::load_rules(const std::string& rule_filename) { if (_current_rules == rule_filename) { return true; } else { // The previous rules and compiler have to be freed manually. _clean_compiler_and_rules(); } bool res = false; int retval; // Look for a compiled version of the rule file first. if (boost::filesystem::exists(rule_filename + "c")) { // File extension is .yarac instead of .yara. retval = yr_rules_load((rule_filename + "c").c_str(), &_rules); } else { retval = yr_rules_load(rule_filename.c_str(), &_rules); } // Yara rules compiled with a previous Yara version. Delete and recompile. if (retval == ERROR_UNSUPPORTED_FILE_VERSION) { boost::filesystem::remove(rule_filename + "c"); } if (retval != ERROR_SUCCESS && retval != ERROR_INVALID_FILE && retval != ERROR_UNSUPPORTED_FILE_VERSION) { PRINT_ERROR << "Could not load yara rules (" << translate_error(retval) << ")." << std::endl; return false; } if (retval == ERROR_SUCCESS) { return true; } else if (retval == ERROR_INVALID_FILE || retval == ERROR_UNSUPPORTED_FILE_VERSION) // Uncompiled rules { if (yr_compiler_create(&_compiler) != ERROR_SUCCESS) { return false; } yr_compiler_set_callback(_compiler, compiler_callback, nullptr); FILE* rule_file = fopen(rule_filename.c_str(), "r"); if (rule_file == nullptr) { return false; } retval = yr_compiler_add_file(_compiler, rule_file, nullptr, rule_filename.c_str()); if (retval != 0) { PRINT_ERROR << "Could not compile yara rules (" << retval << " error(s))." << std::endl; goto END; } retval = yr_compiler_get_rules(_compiler, &_rules); if (retval != ERROR_SUCCESS) { goto END; } // Save the compiled rules to improve load times. // /!\ The compiled rules will have to be deleted if the original (readable) rule file is updated! // TODO: Compare timestamps and recompile automatically. retval = yr_rules_save(_rules, (rule_filename + "c").c_str()); if (retval != ERROR_SUCCESS) { goto END; } res = true; _current_rules = rule_filename; END: if (rule_file != nullptr) { fclose(rule_file); } } return res; }
int main( int argc, const char** argv) { YR_COMPILER* compiler = NULL; YR_RULES* rules = NULL; int result; argc = args_parse(options, argc, argv); if (show_version) { printf("%s\n", PACKAGE_STRING); printf("\nSend bug reports and suggestions to: %s.\n", PACKAGE_BUGREPORT); return EXIT_FAILURE; } if (show_help) { printf("%s\n\n", USAGE_STRING); args_print_usage(options, 25); printf("\nSend bug reports and suggestions to: %s.\n", PACKAGE_BUGREPORT); return EXIT_FAILURE; } if (argc < 2) { fprintf(stderr, "yarac: wrong number of arguments\n"); fprintf(stderr, "%s\n\n", USAGE_STRING); fprintf(stderr, "Try `--help` for more options\n"); exit_with_code(EXIT_FAILURE); } result = yr_initialize(); if (result != ERROR_SUCCESS) exit_with_code(EXIT_FAILURE); if (yr_compiler_create(&compiler) != ERROR_SUCCESS) exit_with_code(EXIT_FAILURE); if (!define_external_variables(compiler)) exit_with_code(EXIT_FAILURE); yr_compiler_set_callback(compiler, report_error, NULL); for (int i = 0; i < argc - 1; i++) { const char* ns; const char* file_name; char* colon = (char*) strchr(argv[i], ':'); if (colon) { file_name = colon + 1; *colon = '\0'; ns = argv[i]; } else { file_name = argv[i]; ns = NULL; } FILE* rule_file = fopen(file_name, "r"); if (rule_file != NULL) { int errors = yr_compiler_add_file( compiler, rule_file, ns, file_name); fclose(rule_file); if (errors) // errors during compilation exit_with_code(EXIT_FAILURE); } else { fprintf(stderr, "error: could not open file: %s\n", file_name); } } result = yr_compiler_get_rules(compiler, &rules); if (result != ERROR_SUCCESS) { fprintf(stderr, "error: %d\n", result); exit_with_code(EXIT_FAILURE); } result = yr_rules_save(rules, argv[argc - 1]); if (result != ERROR_SUCCESS) { fprintf(stderr, "error: %d\n", result); exit_with_code(EXIT_FAILURE); } result = EXIT_SUCCESS; _exit: if (compiler != NULL) yr_compiler_destroy(compiler); if (rules != NULL) yr_rules_destroy(rules); yr_finalize(); return result; }
int main( int argc, char const* argv[]) { YR_COMPILER* compiler; YR_RULES* rules; FILE* rule_file; EXTERNAL* external; int pid; int i; int errors; int result; THREAD thread[MAX_THREADS]; if (!process_cmd_line(argc, argv)) return EXIT_FAILURE; if (argc == 1 || optind == argc) { show_help(); cleanup(); return EXIT_FAILURE; } yr_initialize(); result = yr_rules_load(argv[optind], &rules); if (result != ERROR_SUCCESS && result != ERROR_INVALID_FILE) { print_scanner_error(result); yr_finalize(); cleanup(); return EXIT_FAILURE; } if (result == ERROR_SUCCESS) { external = externals_list; while (external != NULL) { switch (external->type) { case EXTERNAL_TYPE_INTEGER: yr_rules_define_integer_variable( rules, external->name, external->integer); break; case EXTERNAL_TYPE_BOOLEAN: yr_rules_define_boolean_variable( rules, external->name, external->boolean); break; case EXTERNAL_TYPE_STRING: yr_rules_define_string_variable( rules, external->name, external->string); break; } external = external->next; } } else { if (yr_compiler_create(&compiler) != ERROR_SUCCESS) { yr_finalize(); cleanup(); return EXIT_FAILURE; } external = externals_list; while (external != NULL) { switch (external->type) { case EXTERNAL_TYPE_INTEGER: yr_compiler_define_integer_variable( compiler, external->name, external->integer); break; case EXTERNAL_TYPE_BOOLEAN: yr_compiler_define_boolean_variable( compiler, external->name, external->boolean); break; case EXTERNAL_TYPE_STRING: yr_compiler_define_string_variable( compiler, external->name, external->string); break; } external = external->next; } yr_compiler_set_callback(compiler, print_compiler_error); rule_file = fopen(argv[optind], "r"); if (rule_file == NULL) { fprintf(stderr, "could not open file: %s\n", argv[optind]); yr_compiler_destroy(compiler); yr_finalize(); cleanup(); return EXIT_FAILURE; } errors = yr_compiler_add_file(compiler, rule_file, NULL, argv[optind]); fclose(rule_file); if (errors > 0) { yr_compiler_destroy(compiler); yr_finalize(); cleanup(); return EXIT_FAILURE; } result = yr_compiler_get_rules(compiler, &rules); yr_compiler_destroy(compiler); if (result != ERROR_SUCCESS) { yr_finalize(); cleanup(); return EXIT_FAILURE; } } mutex_init(&output_mutex); if (is_numeric(argv[argc - 1])) { pid = atoi(argv[argc - 1]); result = yr_rules_scan_proc( rules, pid, callback, (void*) argv[argc - 1], fast_scan, timeout); if (result != ERROR_SUCCESS) print_scanner_error(result); } else if (is_directory(argv[argc - 1])) { if (file_queue_init() != 0) print_scanner_error(ERROR_INTERNAL_FATAL_ERROR); for (i = 0; i < threads; i++) { if (create_thread(&thread[i], scanning_thread, (void*) rules) != 0) { print_scanner_error(ERROR_COULD_NOT_CREATE_THREAD); return EXIT_FAILURE; } } scan_dir( argv[argc - 1], recursive_search, rules, callback); file_queue_finish(); // Wait for scan threads to finish for (i = 0; i < threads; i++) thread_join(&thread[i]); file_queue_destroy(); } else { result = yr_rules_scan_file( rules, argv[argc - 1], callback, (void*) argv[argc - 1], fast_scan, timeout); if (result != ERROR_SUCCESS) { fprintf(stderr, "Error scanning %s: ", argv[argc - 1]); print_scanner_error(result); } } #ifdef PROFILING_ENABLED yr_rules_print_profiling_info(rules); #endif yr_rules_destroy(rules); yr_finalize(); mutex_destroy(&output_mutex); cleanup(); return EXIT_SUCCESS; }