mirror of
https://github.com/ditekshen/detection
synced 2026-06-08 13:49:35 +00:00
127 lines
6.1 KiB
Python
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()
|