Skip to content

Commit

Permalink
plugin compat: updated for new yara version + added test
Browse files Browse the repository at this point in the history
  • Loading branch information
jstucke committed Dec 20, 2023
1 parent dcbf802 commit 96ce0cc
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 10 deletions.
18 changes: 8 additions & 10 deletions src/analysis/plugin/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,17 @@ def shutdown(self):

def yara_match_to_dict(match: yara.Match) -> dict:
"""Converts a ``yara.Match`` to the format that :py:class:`analysis.YaraPluginBase` would return."""
# FIXME (yara): Use this when we upgrade to yara-python 4.3.0
# for string_match in match.strings:
# for string_instance in string_match.instances:

strings = [(offset, identifier, data.hex()) for offset, identifier, data in match.strings]
# see YARA docs: https://yara.readthedocs.io/en/latest/yarapython.html#yara.StringMatchInstance
strings = [
(string_instance.offset, string_match.identifier, string_instance.matched_data.decode(errors='replace'))
for string_match in match.strings # type: yara.StringMatch
for string_instance in string_match.instances # type: yara.StringMatchInstance
]

return {
'meta': {
# Optional
'date': match.meta.get('date'),
# Optional
'author': match.meta.get('author'),
'description': match.meta['description'],
key: match.meta.get(key)
for key in ('open_source', 'software_name', 'website', 'date', 'author', 'description')
},
'rule': match.rule,
'strings': strings,
Expand Down
52 changes: 52 additions & 0 deletions src/test/unit/analysis/test_addons_yara.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from io import FileIO
from pathlib import Path

import yara

from analysis.YaraPluginBase import YaraBasePlugin
from analysis.plugin.addons import Yara
from analysis.plugin.compat import yara_match_to_dict
from helperFunctions.fileSystem import get_src_dir
from test.common_helper import create_test_file_object

signature_file = str(Path(get_src_dir()) / 'test/unit/analysis/test.yara')
test_target = str(Path(get_src_dir()) / 'test/data/files/get_files_test/testfile1')

EXPECTED_RESULT = {
'matches': True,
'meta': {
'description': 'Generic Software',
'open_source': False,
'software_name': 'Test Software',
'website': 'http://www.fkie.fraunhofer.de',
},
'rule': 'testRule',
'strings': [(0, '$a', 'test'), (22, '$a', 'Test')],
}


class MockYaraPlugin(YaraBasePlugin):
def __init__(self):
self.signature_path = signature_file
self.NAME = 'test_plugin'


class MockYaraAddonPlugin(Yara):
def __init__(self):
self._rules = yara.compile(signature_file)


def test_output_is_compatible():
fo = create_test_file_object(test_target)
plugin = MockYaraPlugin()
plugin.process_object(fo)
assert fo.processed_analysis['test_plugin']['testRule'] == EXPECTED_RESULT

yara_addon_plugin = MockYaraAddonPlugin()
file = FileIO(test_target)
yara_matches = yara_addon_plugin.match(file)
assert all(isinstance(m, yara.Match) for m in yara_matches)
converted_match = yara_match_to_dict(yara_matches[0])
assert converted_match['strings'] == EXPECTED_RESULT['strings']
for key, value in EXPECTED_RESULT['meta'].items():
assert converted_match['meta'][key] == value

0 comments on commit 96ce0cc

Please sign in to comment.