Files
ditekshen-detection/scripts/mbfyar.py
T

127 lines
6.1 KiB
Python

#!/usr/bin/env python3
import os
import csv
import argparse
__author__ = "ditekSHen"
__copyright__ = "Copyright 2020, ditekShen"
__version__ = "1.0"
__reference__ = "https://github.com/ditekshen"
def parse_csv(infile=None,hashtype='md5'):
samples = list()
if infile:
infile = os.path.join(os.path.dirname(__file__), infile)
try:
with open(infile, 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile, delimiter=',', quotechar='"', skipinitialspace=True)
try:
for row in reader:
if not row[0].startswith('#'):
sample = dict()
if ("dosexec" or "executable" or "exe") in row[7] and ("exe" or "dll" or "elf") in row[6]:
sample["first_seen"] = row[0]
sample["md5"] = row[2]
sample["sha1"] = row[3]
sample["sha2"] = row[1]
sample["filetype"] = row[6]
sample["mimetype"] = row[7]
sample["signature"] = row[8]
sample["imphash"] = row[11]
sample["ssdeep"] = row[12]
samples.append(sample)
except IndexError as err:
print("Input file is potentially not a CSV file")
raise SystemExit(err)
except IOError as err:
raise SystemExit(err)
return samples
else:
return None
def write_yara(samples, hashtype, minsize, maxsize, outfile):
rules = str()
try:
fw = open(outfile, 'w')
except IOError:
print("Could not open file for writting output Yara rules file")
file_header = "/*\n"
file_header += " Auto-generated hash-based Yara rules for executables (exe, dll, elf) from Abuse.ch MalwareBazar\n"
file_header += " Author: Automatically generated by MBYar (ditekSHen)\n"
file_header += " Reference: https://bazaar.abuse.ch/faq/\n"
file_header += " Reference: https://github.com/ditekshen\n"
file_header += "*/\n\n"
fw.write(file_header)
fw.write('import "hash"\n\n')
rule_name_prefix = "rule INDICATOR_MB_Hash_"
for sample in samples:
if hashtype == "md5":
rule_name = "rule INDICATOR_MB_Hash_%s {\n" % sample["md5"].lower()
elif hashtype == "sha1":
rule_name = "rule INDICATOR_MB_Hash_%s {\n" % sample["sha1"].lower()
elif hashtype == "sha2":
rule_name = "rule INDICATOR_MB_Hash_%s {\n" % sample["sha2"].lower()
rule_meta = " meta:\n"
rule_meta += " author = \"ditekSHen\"\n"
rule_meta += " description = \"Detects malicious sample based on known hash from Abuse.ch MalwareBazar\"\n"
rule_meta += " first_seen = \"%s\"\n" % sample["first_seen"].lower()
rule_meta += " signature = \"%s\"\n" % sample["signature"]
rule_meta += " md5 = \"%s\"\n" % sample["md5"].lower()
rule_meta += " sha1 = \"%s\"\n" % sample["sha1"].lower()
rule_meta += " sha2 = \"%s\"\n" % sample["sha2"].lower()
if len(sample["imphash"]) == 32:
rule_meta += " imphash = \"%s\"\n" % sample["imphash"].lower()
rule_meta += " ssdeep = \"%s\"\n" % sample["ssdeep"]
rule_condition = " condition:\n"
if ("exe" or "dll") in sample["filetype"]:
rule_condition += " uint16(0) == 0x5a4d and\n"
elif ("elf") in sample["filetype"]:
rule_condition += " uint16(0) == 0x457f and\n"
rule_condition += " filesize > {0}KB and filesize < {1}KB and\n".format(minsize, maxsize)
if hashtype == "md5":
rule_condition += " hash.md5(0,filesize) == \"%s\"\n" % sample["md5"]
elif hashtype == "sha1":
rule_condition += " hash.sha1(0,filesize) == \"%s\"\n" % sample["sha1"]
elif hashtype == "sha2":
rule_condition += " hash.sha256(0,filesize) == \"%s\"\n" % sample["sha2"]
rule_end = "}\n\n"
rules += rule_name + rule_meta + rule_condition + rule_end
fw.write(rules)
try:
fw.close()
except IOError:
print("Could not close output Yara rules file")
def main():
usage_text = '''Example Usage:
mbfyar.py -i full.csv - Generate Yara rules from MalwareBazar CSV file (defaults - hash: md5, minsize:100, maxsize:2000)
mbfyar.py -H sha1 -i full.csv - Generate SHA1-based Yara rules from MalwareBazar CSV file
mbyar.py -n 500 -x 5000 -i full.csv -o output.yar - Generate MD5-based Yara rules limiting matches to file size range to custom output file name'''
parser = argparse.ArgumentParser(description='Generate Yara hash rules for executables (exe, dll, elf) from Absue.ch MalwareBazar', epilog=usage_text, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-H', '--hash', help='Hash type to generate Yara rules against', type=str, metavar="HASH", required=False, default="md5", choices=['md5', 'sha1', 'sha2'])
parser.add_argument('-n', '--minsize', type=int, metavar='SIZE', required=False, action='store', default=100, help='Minimum file size in kilobytes (KB)')
parser.add_argument('-x', '--maxsize', type=int, metavar='SIZE', required=False, action='store', default=2000, help='Maximum file size in kilobytes (KB)')
parser.add_argument('-i', '--input', type=str, metavar='INPUT', required=True, action='store', help='Input full dump from Absue.ch MalwareBazar')
parser.add_argument('-o', '--output', type=str, metavar='OUTPUT', required=False, default='hashes.yar', help='Output Yara rules file name')
args = parser.parse_args()
data = parse_csv(args.input)
if data and len(data) > 0:
write_yara(data, args.hash, args.minsize, args.maxsize, args.output)
else:
print("No hash IOCs found, or something went wrong!")
if __name__ == "__main__":
main()