-
Notifications
You must be signed in to change notification settings - Fork 385
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
5 changed files
with
190 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "Malpedia", | ||
"author": "Davide Arcuri, Andrea Garavaglia - LDO-CERT", | ||
"license": "AGPL-V3", | ||
"url": "https://github.com/LDO-CERT/cortex-analyzers", | ||
"version": "1.0", | ||
"baseConfig": "Malpedia", | ||
"config": {}, | ||
"description": "Check files against Malpedia YARA rules.", | ||
"dataTypeList": ["file"], | ||
"command": "Malpedia/malpedia_analyzer.py" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#!/usr/bin/env python3 | ||
import os | ||
import io | ||
import sys | ||
import json | ||
import yara | ||
import requests | ||
import datetime | ||
|
||
from cortexutils.analyzer import Analyzer | ||
from requests.auth import HTTPBasicAuth | ||
from stat import ST_MTIME | ||
|
||
|
||
class MalpediaAnalyzer(Analyzer): | ||
"""Checking binaries through yara rules. This analyzer requires a list of yara rule paths in the cortex | ||
configuration. If a path is given, an index file is expected.""" | ||
|
||
def __init__(self): | ||
Analyzer.__init__(self) | ||
|
||
self.baseurl = "https://malpedia.caad.fkie.fraunhofer.de/api/get" | ||
self.rulepaths = self.get_param('config.path', None, 'No rulepath provided.') | ||
self.user = self.get_param('config.username', None, 'No username provided.') | ||
self.pwd = self.get_param('config.password', None, 'No password provided.') | ||
self.update_hours = int(self.get_param('config.update_hours', 10)) | ||
|
||
if not os.path.exists(self.rulepaths): | ||
os.makedirs(self.rulepaths) | ||
|
||
timestamps = [] | ||
try: | ||
for fn in os.listdir(self.rulepaths): | ||
for path in os.path.join(self.rulepaths, fn): | ||
if os.path.isfile(path) and path.endswith('.yar'): | ||
timestamps.append(datetime.datetime.fromtimestamp(os.stat(path)[ST_MTIME])) | ||
newest = max(timestamps) | ||
hours = (datetime.datetime.now() - newest).seconds / 3600 | ||
except ValueError: | ||
hours = self.update_hours + 1 | ||
|
||
if hours > self.update_hours or len(timestamps) == 0: | ||
try: | ||
req = requests.get('{}/yara/after/2010-01-01?format=json'.format(self.baseurl), | ||
auth=HTTPBasicAuth(self.user, self.pwd)) | ||
if req.status_code == requests.codes.ok: | ||
rules_json = json.loads(req.text) | ||
for color, color_data in rules_json.items(): | ||
for rule_name, rule_text in color_data.items(): | ||
with io.open(os.path.join(self.rulepaths, rule_name), 'w', encoding='utf-8') as f: | ||
f.write(rule_text) | ||
else: | ||
self.error('Could not download new rules due tue HTTP {}: {}'.format(req.status_code, req.text)) | ||
except Exception as e: | ||
with io.open('%s' % os.path.join(self.rulepaths, "error.txt"), 'w') as f: | ||
f.write('Error: {}\n'.format(e)) | ||
|
||
def check(self, file): | ||
""" | ||
Checks a given file against all available yara rules | ||
:param file: Path to file | ||
:type file:str | ||
:returns: Python list with matched rules info | ||
:rtype: list | ||
""" | ||
result = [] | ||
all_matches = [] | ||
for filerules in os.listdir(self.rulepaths): | ||
try: | ||
rule = yara.compile(os.path.join(self.rulepaths, filerules)) | ||
except yara.SyntaxError: | ||
continue | ||
matches = rule.match(file) | ||
if len(matches) > 0: | ||
for rulem in matches: | ||
rule_family = "_".join([x for x in rulem.rule.replace("_", ".", 1).split("_")[:-1]]) | ||
if rule_family not in all_matches: | ||
all_matches.append(rule_family) | ||
for rule_family in all_matches: | ||
rules_info_txt = requests.get('{}/family/{}'.format(self.baseurl, rule_family), | ||
auth=HTTPBasicAuth(self.user, self.pwd)) | ||
rules_info_json = json.loads(rules_info_txt.text) | ||
result.append({ | ||
'family': rule_family, | ||
'common_name': rules_info_json['common_name'], | ||
'description': rules_info_json['description'], | ||
'attribution': rules_info_json['attribution'], | ||
'alt_names': rules_info_json['alt_names'], | ||
'urls': rules_info_json['urls'] | ||
}) | ||
|
||
return result | ||
|
||
def summary(self, raw): | ||
taxonomies = [] | ||
namespace = "Malpedia" | ||
predicate = "Match" | ||
|
||
value = "\"{} rule(s)\"".format(len(raw["results"])) | ||
if len(raw["results"]) == 0: | ||
level = "safe" | ||
else: | ||
level = "malicious" | ||
|
||
taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) | ||
return {"taxonomies": taxonomies} | ||
|
||
def run(self): | ||
if self.data_type == 'file': | ||
self.report({'results': self.check(self.get_param('file', None, 'No file given.'))}) | ||
else: | ||
self.error('Wrong data type.') | ||
|
||
|
||
if __name__ == '__main__': | ||
MalpediaAnalyzer().run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
yara-python | ||
cortexutils | ||
requests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<div class="panel panel-danger" ng-if="success && content.results.length > 0"> | ||
<div class="panel-heading"> | ||
Malpedia Report | ||
</div> | ||
<div class="panel-body"> | ||
<div ng-repeat="m in content.results"> | ||
<h4>{{m.common_name}} <span style="font-size: small">[{{m.family}}]</span></h4> | ||
<dl class="dl-horizontal"> | ||
<dt>Description</dt> | ||
<dd>{{m.description || "No description given."}}</dd> | ||
<dt>Attributions</dt> | ||
<dd> | ||
<span ng-if="m.attribution.length == 0">No attributions given.</span> | ||
<ul ng-if="m.attribution.length > 0"> | ||
<li ng-repeat="x in m.attribution">{{x}}</li> | ||
</ul> | ||
</dd> | ||
<dt>Alternative Names</dt> | ||
<dd> | ||
<span ng-if="m.alt_names.length == 0">No alternative names given.</span> | ||
<ul ng-if="m.alt_names.length > 0"> | ||
<li ng-repeat="x in m.alt_names">{{x}}</li> | ||
</ul> | ||
</dd> | ||
<dt>Urls</dt> | ||
<dd> | ||
<span ng-if="m.urls.length == 0">No Urls given.</span> | ||
<ul ng-if="m.urls.length > 0"> | ||
<li ng-repeat="x in m.urls"><a href="{{x}}" target="_blank">{{x}}</a></li> | ||
</ul> | ||
</dd> | ||
</dl> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="panel panel-success" ng-if="success && content.results.length == 0"> | ||
<div class="panel-heading"> | ||
Malpedia Report | ||
</div> | ||
<div class="panel-body"> | ||
<span>No matches.</span> | ||
</div> | ||
</div> | ||
|
||
<!-- General error --> | ||
<div class="panel panel-danger" ng-if="!success"> | ||
<div class="panel-heading"> | ||
<strong>{{(artifact.data || artifact.attachment.name) | fang}}</strong> | ||
</div> | ||
<div class="panel-body"> | ||
<dl class="dl-horizontal" ng-if="content.errorMessage"> | ||
<dt><i class="fa fa-warning"></i> Yara: </dt> | ||
<dd class="wrap">{{content.errorMessage}}</dd> | ||
</dl> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<span class="label" ng-repeat="t in content.taxonomies" ng-class="{'info': 'label-info', 'safe': 'label-success', 'suspicious': 'label-warning', 'malicious':'label-danger'}[t.level]"> | ||
{{t.namespace}}:{{t.predicate}}={{t.value}} | ||
</span> |