Skip to content

Commit 96ce0cc

Browse files
committed
plugin compat: updated for new yara version + added test
1 parent dcbf802 commit 96ce0cc

File tree

2 files changed

+60
-10
lines changed

2 files changed

+60
-10
lines changed

src/analysis/plugin/compat.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,17 @@ def shutdown(self):
5858

5959
def yara_match_to_dict(match: yara.Match) -> dict:
6060
"""Converts a ``yara.Match`` to the format that :py:class:`analysis.YaraPluginBase` would return."""
61-
# FIXME (yara): Use this when we upgrade to yara-python 4.3.0
62-
# for string_match in match.strings:
63-
# for string_instance in string_match.instances:
64-
65-
strings = [(offset, identifier, data.hex()) for offset, identifier, data in match.strings]
61+
# see YARA docs: https://yara.readthedocs.io/en/latest/yarapython.html#yara.StringMatchInstance
62+
strings = [
63+
(string_instance.offset, string_match.identifier, string_instance.matched_data.decode(errors='replace'))
64+
for string_match in match.strings # type: yara.StringMatch
65+
for string_instance in string_match.instances # type: yara.StringMatchInstance
66+
]
6667

6768
return {
6869
'meta': {
69-
# Optional
70-
'date': match.meta.get('date'),
71-
# Optional
72-
'author': match.meta.get('author'),
73-
'description': match.meta['description'],
70+
key: match.meta.get(key)
71+
for key in ('open_source', 'software_name', 'website', 'date', 'author', 'description')
7472
},
7573
'rule': match.rule,
7674
'strings': strings,
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from io import FileIO
2+
from pathlib import Path
3+
4+
import yara
5+
6+
from analysis.YaraPluginBase import YaraBasePlugin
7+
from analysis.plugin.addons import Yara
8+
from analysis.plugin.compat import yara_match_to_dict
9+
from helperFunctions.fileSystem import get_src_dir
10+
from test.common_helper import create_test_file_object
11+
12+
signature_file = str(Path(get_src_dir()) / 'test/unit/analysis/test.yara')
13+
test_target = str(Path(get_src_dir()) / 'test/data/files/get_files_test/testfile1')
14+
15+
EXPECTED_RESULT = {
16+
'matches': True,
17+
'meta': {
18+
'description': 'Generic Software',
19+
'open_source': False,
20+
'software_name': 'Test Software',
21+
'website': 'http://www.fkie.fraunhofer.de',
22+
},
23+
'rule': 'testRule',
24+
'strings': [(0, '$a', 'test'), (22, '$a', 'Test')],
25+
}
26+
27+
28+
class MockYaraPlugin(YaraBasePlugin):
29+
def __init__(self):
30+
self.signature_path = signature_file
31+
self.NAME = 'test_plugin'
32+
33+
34+
class MockYaraAddonPlugin(Yara):
35+
def __init__(self):
36+
self._rules = yara.compile(signature_file)
37+
38+
39+
def test_output_is_compatible():
40+
fo = create_test_file_object(test_target)
41+
plugin = MockYaraPlugin()
42+
plugin.process_object(fo)
43+
assert fo.processed_analysis['test_plugin']['testRule'] == EXPECTED_RESULT
44+
45+
yara_addon_plugin = MockYaraAddonPlugin()
46+
file = FileIO(test_target)
47+
yara_matches = yara_addon_plugin.match(file)
48+
assert all(isinstance(m, yara.Match) for m in yara_matches)
49+
converted_match = yara_match_to_dict(yara_matches[0])
50+
assert converted_match['strings'] == EXPECTED_RESULT['strings']
51+
for key, value in EXPECTED_RESULT['meta'].items():
52+
assert converted_match['meta'][key] == value

0 commit comments

Comments
 (0)