Skip to content

Commit

Permalink
Improve tests (#81)
Browse files Browse the repository at this point in the history
* Fix Codacity warning.
Best practice: https://docs.python.org/3.8/tutorial/modules.html#importing-from-a-package

* Fixes #70

* Revert last change

* Fixes #71

* Remove deprecated methods in preparation for major release.

* Fixes #72

* Fixes #74

* Fixes #75

* Fixes #76

* Fixes #77

* Fixes #78

* Test the actual command line not the script

* Remove unused import

* Add full coverage for generate_logic_hash

* Deprecate rule rebuilding. This function needs to be reworked.
This function does not work on many rulesets and rules.

* Fix docstyle problem

* Actually fix docstring problem.

* Separate parser to function in preparation for unit testing

* Improved path

* Refactor CLI unit test. Fixes #82

* Add unit test for no error

* Fix docstring problem

* Change to multiline assert

* Use hashlib to test CLI output

* Change hash to correct

* Add both possible hashes
This is a workaround for what appears to be a bug in unittest.

* Fixes #83

* Make example executable

* This works from command line.
  • Loading branch information
utkonos committed Jan 4, 2020
1 parent 45e5d2d commit 2e8bece
Show file tree
Hide file tree
Showing 8 changed files with 566 additions and 335 deletions.
164 changes: 61 additions & 103 deletions examples/corpus_stats.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,109 +1,67 @@
"""Example script that demonstrates using plyara."""
import argparse
import operator
import os
import sys
import codecs

sys.path.insert(0, os.getcwd())
import plyara


if __name__ == '__main__':
def example():
"""Execute the example code."""
parser = argparse.ArgumentParser()
parser.add_argument('file', metavar='FILE', help='File containing YARA rules to parse.')
args = parser.parse_args()

print('Parsing file...')
with open(args.file, 'r') as fh:
data = fh.read()

parser = plyara.Plyara()
rules_dict = parser.parse_string(data)
print('Analyzing dictionary...')

imps = {}
tags = {}
rule_count = 0

for rule in rules_dict:
rule_count += 1

# Imports
if 'imports' in rule:
for imp in rule['imports']:
imp = imp.replace('"', '')
if imp in imps:
imps[imp] += 1
else:
imps[imp] = 1

# Tags
if 'tags' in rule:
for tag in rule['tags']:
if tag in tags:
tags[tag] += 1
else:
tags[tag] = 1

file_to_analyze = sys.argv[1]

print("...parsing file...")
rulesDict = plyara.Plyara().parse_string(codecs.open(file_to_analyze, encoding='utf-8').read())
print("...analyzing dictionary...")

authors = {}
imps = {}
meta_keys = {}
max_strings = []
max_string_len = 0
tags = {}
rule_count = 0

for rule in rulesDict:
rule_count += 1

#Imports
if 'imports' in rule:
for imp in rule['imports']:
imp = imp.replace('"','')
if imp in imps:
imps[imp] += 1
else:
imps[imp] = 1

#Tags
if 'tags' in rule:
for tag in rule['tags']:
if tag in tags:
tags[tag] += 1
else:
tags[tag] = 1

#Metadata
if 'metadata' in rule:
for key in rule['metadata']:
if key in meta_keys:
meta_keys[key] += 1
else:
meta_keys[key] = 1
if key in ['Author', 'author']:
if rule['metadata'][key] in authors:
authors[rule['metadata'][key]] += 1
else:
authors[rule['metadata'][key]] = 1

#Strings
if 'strings' in rule:
for strr in rule['strings']:
if len(strr['value']) > max_string_len:
max_string_len = len(strr['value'])
max_strings = [(rule['rule_name'], strr['name'], strr['value'])]
elif len(strr['value']) == max_string_len:
max_strings.append((rule['rule_name'], strr['key'], strr['value']))



print("\nNumber of rules in file: " + str(rule_count))

ordered_meta_keys = sorted(meta_keys.items(),
key=operator.itemgetter(1), reverse=True)

ordered_authors = sorted(authors.items(),
key=operator.itemgetter(1), reverse=True)

ordered_imps = sorted(imps.items(),
key=operator.itemgetter(1), reverse=True)

ordered_tags = sorted(tags.items(),
key=operator.itemgetter(1), reverse=True)

print("\nTop 5 metadata keys:")
for i in range(5):
if i < len(ordered_meta_keys):
print(ordered_meta_keys[i])

print("\nTop 5 authors based on parsed metadata:")
for i in range(5):
if i < len(ordered_authors):
print(ordered_authors[i])

print('\nLongest string(s): ')
for s in max_strings:
print('string named "' + s[1] +'" in rule "'+ s[0]
+ '" with length ' + str(max_string_len) + '.')

print("\nTop imports: ")
for i in range(5):
if i < len(ordered_imps):
print(ordered_imps[i])

print("\nTop tags")
for i in range(5):
if i < len(ordered_tags):
print(ordered_tags[i])

print("\n")
print('\n======================\n')
print('Number of rules in file: {}'.format(rule_count))

ordered_imps = sorted(imps.items(), key=operator.itemgetter(1), reverse=True)

ordered_tags = sorted(tags.items(), key=operator.itemgetter(1), reverse=True)

print('\n======================\n')
print('Top imports:')
for i in range(5):
if i < len(ordered_imps):
print(ordered_imps[i])

print('\n======================\n')
print('Top tags:')
for i in range(5):
if i < len(ordered_tags):
print(ordered_tags[i])


if __name__ == '__main__':
example()
3 changes: 2 additions & 1 deletion plyara/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from plyara.core import Plyara
__all__ = ['Plyara']
from plyara.core import *
7 changes: 5 additions & 2 deletions plyara/command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
from plyara.core import Plyara


def main():
def main(arguments=None):
"""Run the command line process to parse a yara rule file and output pretty printed JSON."""
parser = argparse.ArgumentParser(description='Parse YARA rules into a dictionary representation.')
parser.add_argument('file', metavar='FILE', help='File containing YARA rules to parse.')
parser.add_argument('--log', help='Enable debug logging to the console.', action='store_true')
args = parser.parse_args()
if not arguments:
args = parser.parse_args()
else:
args = parser.parse_args(arguments)

with open(args.file, 'r', encoding='utf-8') as fh:
input_string = fh.read()
Expand Down
Loading

0 comments on commit 2e8bece

Please sign in to comment.