def handle(self, *args, **options): corpus = YaraRule.objects.all() rule_count = corpus.count() message = 'Updating logic hashes for {} rules'.format(rule_count) logging.info(message) rule_index = 0 for rule in corpus.iterator(): rule_index += 1 logic_data = {'strings': rule.strings, 'condition_terms': rule.condition} logic_hash = Plyara.generate_logic_hash(logic_data) rule.logic_hash = logic_hash rule.save() logging.info('Rule Logic Update: {} of {}'.format(rule_index, rule_count))
def generate_kwargs_from_parsed_rule(parsed_rule): # Generate parsed rule kwargs for saving a rule name = parsed_rule['rule_name'] tags = parsed_rule.get('tags', []) scopes = parsed_rule.get('scopes', []) # TODO : Update when Plyara moves to clean Python types metadata = parsed_rule.get('metadata', {}) for key, value in metadata.items(): if value not in ('true', 'false'): try: value = int(value) except ValueError: metadata[key] = '"' + value + '"' strings = parsed_rule.get('strings', []) condition = parsed_rule['condition_terms'] # TODO : Update when Plyara moves to stripping quotes from detect_imports module imports = [imp.strip('"') for imp in Plyara.detect_imports(parsed_rule)] comments = parsed_rule.get('comments', []) dependencies = Plyara.detect_dependencies(parsed_rule) # Calculate hash value of rule strings and condition logic_hash = Plyara.generate_logic_hash(parsed_rule) # TEMP FIX - Use only a single instance of a metakey # until YaraGuardian models and functions can be updated for key, value in metadata.items(): if isinstance(value, list): metadata[key] = value[0] return { 'name': name, 'tags': list(set(tags)), 'scopes': list(set(scopes)), 'imports': list(set(imports)), 'comments': list(set(comments)), 'metadata': metadata, 'strings': strings, 'condition': condition, 'dependencies': dependencies, 'logic_hash': logic_hash }
def test_logic_hash_generator(self): with open('tests/data/logic_collision_ruleset.yar', 'r') as f: inputString = f.read() result = Plyara().parse_string(inputString) rule_mapping = {} for entry in result: rulename = entry['rule_name'] setname, _ = rulename.split('_') rulehash = Plyara.generate_logic_hash(entry) if setname not in rule_mapping: rule_mapping[setname] = [rulehash] else: rule_mapping[setname].append(rulehash) for setname, hashvalues in rule_mapping.items(): if not len(set(hashvalues)) == 1: raise AssertionError("Collision detection failure for {}".format(setname))
def test_logic_hash_generator(self): with data_dir.joinpath('logic_collision_ruleset.yar').open('r') as fh: inputString = fh.read() result = Plyara().parse_string(inputString) rule_mapping = {} for entry in result: rulename = entry['rule_name'] setname, _ = rulename.split('_') with self.assertWarns(DeprecationWarning): rulehash = Plyara.generate_logic_hash(entry) if setname not in rule_mapping: rule_mapping[setname] = [rulehash] else: rule_mapping[setname].append(rulehash) for setname, hashvalues in rule_mapping.items(): if not len(set(hashvalues)) == 1: raise AssertionError( 'Collision detection failure for {}'.format(setname))