int handle_message(int message, YR_RULE* rule, void* data) { TAG* tag; IDENTIFIER* identifier; YR_STRING* string; YR_MATCH* match; YR_META* meta; char* tag_name; size_t tag_length; int is_matching; int string_found; int show = TRUE; if (show_specified_tags) { show = FALSE; tag = specified_tags_list; while (tag != NULL) { tag_name = rule->tags; tag_length = tag_name != NULL ? strlen(tag_name) : 0; while (tag_length > 0) { if (strcmp(tag_name, tag->identifier) == 0) { show = TRUE; break; } tag_name += tag_length + 1; tag_length = strlen(tag_name); } tag = tag->next; } } if (show_specified_rules) { show = FALSE; identifier = specified_rules_list; while (identifier != NULL) { if (strcmp(identifier->name, rule->identifier) == 0) { show = TRUE; break; } identifier = identifier->next; } } is_matching = (message == CALLBACK_MSG_RULE_MATCHING); show = show && ((!negate && is_matching) || (negate && !is_matching)); if (show) { mutex_lock(&output_mutex); printf("%s ", rule->identifier); if (show_tags) { printf("["); tag_name = rule->tags; tag_length = tag_name != NULL ? strlen(tag_name) : 0; while (tag_length > 0) { printf("%s", tag_name); tag_name += tag_length + 1; tag_length = strlen(tag_name); if (tag_length > 0) printf(","); } printf("] "); } // Show meta-data. if (show_meta) { meta = rule->metas; printf("["); while(!META_IS_NULL(meta)) { if (meta->type == META_TYPE_INTEGER) printf("%s=%d", meta->identifier, meta->integer); else if (meta->type == META_TYPE_BOOLEAN) printf("%s=%s", meta->identifier, meta->integer ? "true" : "false"); else printf("%s=\"%s\"", meta->identifier, meta->string); meta++; if (!META_IS_NULL(meta)) printf(","); } printf("] "); } printf("%s\n", (char*) data); // Show matched strings. if (show_strings) { string = rule->strings; while (!STRING_IS_NULL(string)) { string_found = STRING_FOUND(string); if (string_found) { match = STRING_MATCHES(string).head; while (match != NULL) { printf("0x%" PRIx64 ":%s: ", match->first_offset, string->identifier); if (STRING_IS_HEX(string)) { print_hex_string(match->data, match->length); } else { print_string(match->data, match->length); } match = match->next; } } string++; } } mutex_unlock(&output_mutex); } if (is_matching) count++; if (limit != 0 && count >= limit) return CALLBACK_ABORT; return CALLBACK_CONTINUE; }
int yara_callback( int message, YR_RULE* rule, void* data) { YR_STRING* string; YR_MATCH* m; YR_META* meta; char* tag_name; size_t tag_length; PyObject* tag_list = NULL; PyObject* string_list = NULL; PyObject* meta_list = NULL; PyObject* match; PyObject* callback_dict; PyObject* object; PyObject* tuple; PyObject* matches = ((CALLBACK_DATA*) data)->matches; PyObject* callback = ((CALLBACK_DATA*) data)->callback; PyObject* callback_result; PyGILState_STATE gil_state; int result = CALLBACK_CONTINUE; if (message == CALLBACK_MSG_SCAN_FINISHED) return CALLBACK_CONTINUE; if (message == CALLBACK_MSG_RULE_NOT_MATCHING && callback == NULL) return CALLBACK_CONTINUE; gil_state = PyGILState_Ensure(); tag_list = PyList_New(0); string_list = PyList_New(0); meta_list = PyDict_New(); if (tag_list == NULL || string_list == NULL || meta_list == NULL) { Py_XDECREF(tag_list); Py_XDECREF(string_list); Py_XDECREF(meta_list); PyGILState_Release(gil_state); return CALLBACK_ERROR; } tag_name = rule->tags; tag_length = tag_name != NULL ? strlen(tag_name) : 0; while (tag_length > 0) { object = PY_STRING(tag_name); PyList_Append(tag_list, object); Py_DECREF(object); tag_name += tag_length + 1; tag_length = strlen(tag_name); } meta = rule->metas; while(!META_IS_NULL(meta)) { if (meta->type == META_TYPE_INTEGER) object = Py_BuildValue("I", meta->integer); else if (meta->type == META_TYPE_BOOLEAN) object = PyBool_FromLong(meta->integer); else object = PY_STRING(meta->string); PyDict_SetItemString(meta_list, meta->identifier, object); Py_DECREF(object); meta++; } string = rule->strings; while (!STRING_IS_NULL(string)) { if (STRING_FOUND(string)) { m = STRING_MATCHES(string).head; while (m != NULL) { object = PyBytes_FromStringAndSize((char*) m->data, m->length); tuple = Py_BuildValue( "(L,s,O)", m->offset, string->identifier, object); PyList_Append(string_list, tuple); Py_DECREF(object); Py_DECREF(tuple); m = m->next; } } string++; } if (message == CALLBACK_MSG_RULE_MATCHING) { match = Match_NEW( rule->identifier, rule->ns->name, tag_list, meta_list, string_list); if (match != NULL) { PyList_Append(matches, match); Py_DECREF(match); } else { Py_DECREF(tag_list); Py_DECREF(string_list); Py_DECREF(meta_list); PyGILState_Release(gil_state); return CALLBACK_ERROR; } } if (callback != NULL) { Py_INCREF(callback); callback_dict = PyDict_New(); object = PyBool_FromLong(message == CALLBACK_MSG_RULE_MATCHING); PyDict_SetItemString(callback_dict, "matches", object); Py_DECREF(object); object = PY_STRING(rule->identifier); PyDict_SetItemString(callback_dict, "rule", object); Py_DECREF(object); object = PY_STRING(rule->ns->name); PyDict_SetItemString(callback_dict, "namespace", object); Py_DECREF(object); PyDict_SetItemString(callback_dict, "tags", tag_list); PyDict_SetItemString(callback_dict, "meta", meta_list); PyDict_SetItemString(callback_dict, "strings", string_list); callback_result = PyObject_CallFunctionObjArgs( callback, callback_dict, NULL); if (callback_result != NULL) { #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(callback_result)) #else if (PyLong_Check(callback_result) || PyInt_Check(callback_result)) #endif { result = (int) PyLong_AsLong(callback_result); } Py_DECREF(callback_result); } else { result = CALLBACK_ERROR; } Py_DECREF(callback_dict); Py_DECREF(callback); } Py_DECREF(tag_list); Py_DECREF(string_list); Py_DECREF(meta_list); PyGILState_Release(gil_state); return result; }
int get_match_data(int message, void* message_data, void* data) { matches target; YR_META* meta; YR_STRING* s; YR_RULE* rule; pMatch m; YR_MODULE_IMPORT* mi; // Used for the CALLBACK_MSG_IMPORT_MODULE message. pcallback_data* cb_data = (pcallback_data*) data; if (!cb_data) { PRINT_ERROR << "Yara wrapper callback called with no data!" << std::endl; return ERROR_CALLBACK_ERROR; } switch (message) { case CALLBACK_MSG_RULE_MATCHING: rule = (YR_RULE*) message_data; target = cb_data->get()->yara_matches; meta = rule->metas; s = rule->strings; m = boost::make_shared<Match>(); while (!META_IS_NULL(meta)) { m->add_metadata(std::string(meta->identifier), meta->string); ++meta; } while (!STRING_IS_NULL(s)) { if (STRING_FOUND(s)) { YR_MATCH* match = STRING_MATCHES(s).head; while (match != nullptr) { if (!STRING_IS_HEX(s)) { std::string found((char*) match->data, match->length); // Yara inserts null bytes when it matches unicode strings. Dirty fix to remove them all. found.erase(std::remove(found.begin(), found.end(), '\0'), found.end()); m->add_found_string(found); } else { std::stringstream ss; ss << std::hex; for (int i = 0; i < std::min(20, match->length); i++) { ss << static_cast<unsigned int>(match->data[i]) << " "; // Don't interpret as a char } if (match->length > 20) { ss << "..."; } m->add_found_string(ss.str()); } match = match->next; } } ++s; } target->push_back(m); return CALLBACK_CONTINUE; // Don't stop on the first matching rule. case CALLBACK_MSG_RULE_NOT_MATCHING: return CALLBACK_CONTINUE; // Detect when the ManaPE module is loaded case CALLBACK_MSG_IMPORT_MODULE: mi = (YR_MODULE_IMPORT*) message_data; if (std::string(mi->module_name) == "manape") { if (!cb_data || cb_data->get()->pe_info == nullptr) { PRINT_ERROR << "Yara rule imports the ManaPE module, but no ManaPE data was given!" << std::endl; return ERROR_CALLBACK_ERROR; } else if (!cb_data) { PRINT_ERROR << "No data given to the callback to store results!" << std::endl; return ERROR_CALLBACK_ERROR; } mi->module_data = &*(cb_data->get()->pe_info); } return ERROR_SUCCESS; case CALLBACK_MSG_SCAN_FINISHED: return ERROR_SUCCESS; default: PRINT_WARNING << "Yara callback received an unhandled message (" << message << ")." << std::endl; return ERROR_SUCCESS; } }