Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
	}
}