Add scripts, update README, minor addition to Yara/ClamAV rule

This commit is contained in:
ditekshen
2020-12-30 13:24:19 +00:00
parent 13759322e0
commit 3e79b91d54
5 changed files with 261 additions and 4 deletions
+5 -1
View File
@@ -4,4 +4,8 @@ A set of interrelated network and host detection rules with the aim of improving
## Supported Rules
Currently, Snort, Yara and ClamAV rules are supported. Additional singatures and formats are work in progress.
Currently, Snort, Yara and ClamAV rules are supported. Additional singatures and formats are work in progress.
## Scripts
Currently, only scripts available are used to aid in auto-generation of hash-based and certificate-based Yara rules.
+2 -2
View File
@@ -2,7 +2,7 @@ ditekSHen.INDICATOR.RTF.AncalogExploitBuilderDocument;Engine:51-255,Target:0;0&1
ditekSHen.INDICATOR.RTF.EquationBITSAdminDownloader;Engine:81-255,Container:CL_TYPE_RTF,Target:2;0&1&(2|3);6269747361646d696e::i;6571756174696f6e::iaw;2f7472616e73666572;2f646f776e6c6f6164
ditekSHen.INDICATOR.RTF.EquationPowerShellDownloader;Engine:81-255,Container:CL_TYPE_RTF,Target:2;0&1;706f7765727368656c6c::i;6571756174696f6e::iaw
ditekSHen.INDICATOR.RTF.EquationCertUtilDownloader;Engine:81-255,Container:CL_TYPE_RTF,Target:2;0&1;636572747574696c::i;6571756174696f6e::iaw
ditekSHen.INDICATOR.OOXML.Excel4MacrosEXEC;Engine:79-255,Container:CL_TYPE_OOXML_XL,Target:0;0&(1|2|3)>1;3c786d3a6d6163726f7368656574;3e464f524d554c412e46494c4c28;3e524547495354455228;3e4558454328
ditekSHen.INDICATOR.OOXML.Excel4MacrosEXEC;Engine:79-255,Container:CL_TYPE_OOXML_XL,Target:0;0&(1|2|3|4)>1;3c786d3a6d6163726f7368656574;3e464f524d554c412e46494c4c28;3e524547495354455228;3e4558454328;3e52554e28
ditekSHen.INDICATOR.Packed.NyanXCAT-CSharpLoader;Engine:51-255,Target:1;0;0050726f6772616d004c6f61646572004e79616e00
ditekSHen.MALWARE.Win.Trojan.Firebird-HiveRAT;Engine:51-255,Target:1;(0|1|2|3)|(4&5&6&7&8&9&10&11&12)>5;46697265626972642052656d6f74652041646d696e697374726174696f6e20546f6f6c::w;57656c636f6d6520746f2046697265626972642120596f75722073797374656d2069732063757272656e746c79206265696e67206d6f6e69746f726564::w;486976652052656d6f74652041646d696e697374726174696f6e20546f6f6c::w;57656c636f6d6520746f20486976652120596f75722073797374656d2069732063757272656e746c79206265696e67206d6f6e69746f726564::w;5245504c41434554484553454b45595354524f4b4553::w;5f454e41424c455f50524f46494c494e47::w;4b65796c6f675375626a656374::w;77656263616d656e61626c6564;73637265656e6c6f6773;6d6f6e69746f726f6e;5443505f5441424c455f4f574e45525f5049445f414c4c;73637265656e47726162;656e63727970746564636f6e6e656374696f6e
ditekSHen.MALWARE.Win.Trojan.AcridRain;Engine:51-255,Target:1;0&1&2&3&4&5&6&7&8&9;2f4c6962732e7a6970;2f55706c6f61642f;74656d706c6f67696d;74656d706c6f67696b;74656d70505368;74656d70505768;436f6f6b696573;53454c454354202a2046524f4d20;54656c656772616d2e657865;633a5c75736572735c69676f72315c::w
@@ -114,4 +114,4 @@ ditekSHen.MALWARE.Linux.Trojan.HiddenWasp-ELF;Engine:51-255,Target:6;(0&1&2&3&4)
ditekSHen.MALWARE.Linux.Trojan.WellMess_Golang;Engine:51-255,Target:6;0&1&2&3&4&5;3c3b686561643b3e3c3b7469746c653b3e;3c3b7469746c653b3e3c3b736572766963653b3e;5f2f686f6d652f7562756e74752f476f50726f6a6563742f7372632f626f742f626f746c6962;6e65742f687474702e282a70657273697374436f6e6e292e72656164526573706f6e7365;6e65742f687474702f636f6f6b69656a61722e282a4a6172292e536574436f6f6b696573;687474703a2f2f696e76616c69646c6f6f6b7570
ditekSHen.MALWARE.Linux.Trojan.PLEAD;Engine:51-255,Target:6;0&1&2&3&4&5;4346696c655472616e73666572;4346696c654d616e61676572;43506f7274466f7277617264;43506f7274466f72776172644d616e61676572;4352656d6f74655368656c6c;43536f636b436c69656e74
ditekSHen.MALWARE.Aix.Trojan.FastcachInjector;Engine:51-255,Target:0;0&1&2&3&4&5&6&7&8;0:01f7;73746f72655f636f6e666967;6c6f61645f636f6e666967;66696c655f64756d70;2f746d702f2e4943452d756e69782f636f6e6669675f2564;2f746d702f2e4943452d756e69782f44554d5025582e646174;496e6a6563742053746172740a;2e6f75745f6c6f67;2e6f75745f72656773
ditekSHen.MALWARE.Aix.Trojan.FastcachDLL;Engine:51-255,Target:0;0&1&2&3&4&5&6&7&8;0:01f7;2f746d702f2e4943452d756e69782f746d7025645f25642e6c6f67;2f746d702f2e4943452d756e69782f746d70777425645f25642e6c6f67;2f746d702f2e4943452d756e69782f746d70726425645f25642e6c6f;6f75745f64756d705f6c6f67;4d53472044554d50;686f6f6b5f66756e635f6164647228257829;6f72675f66756e6328257029;636f70795f66756e6328257829
ditekSHen.MALWARE.Aix.Trojan.FastcachDLL;Engine:51-255,Target:0;0&1&2&3&4&5&6&7&8;0:01f7;2f746d702f2e4943452d756e69782f746d7025645f25642e6c6f67;2f746d702f2e4943452d756e69782f746d70777425645f25642e6c6f67;2f746d702f2e4943452d756e69782f746d70726425645f25642e6c6f;6f75745f64756d705f6c6f67;4d53472044554d50;686f6f6b5f66756e635f6164647228257829;6f72675f66756e6328257029;636f70795f66756e6328257829
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
import os
import csv
import codecs
import requests
import argparse
from contextlib import closing
__author__ = "ditekSHen"
__copyright__ = "Copyright 2020, ditekShen"
__version__ = "1.0"
__reference__ = "https://github.com/ditekshen"
FILE_URL = "https://bazaar.abuse.ch/export/csv/cscb/"
def parse_csv(infile=None):
cert_data = 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('#'):
cert = dict()
cert["serial_number"] = row[1]
cert["thumbprint"] = row[2]
cert["subject_cn"] = row[4]
cert["reason"] = row[8]
cert_data.append(cert)
except IndexError as err:
print("Input file is potentially not a CSV file")
raise SystemExit(err)
except IOError as err:
raise SystemExit(err)
return cert_data
else:
try:
with closing(requests.get(FILE_URL, stream=True)) as response:
if response.status_code == 200:
reader = csv.reader(codecs.iterdecode(response.iter_lines(),'utf-8'), delimiter=',', quotechar='"', skipinitialspace=True)
try:
for row in reader:
if not row[0].startswith('#'):
cert = dict()
cert["serial_number"] = row[1]
cert["thumbprint"] = row[2]
cert["subject_cn"] = row[4]
cert["reason"] = row[8]
cert_data.append(cert)
except IndexError as err:
print("Response data is potentially not CSV formatted")
raise SystemExit(err)
except requests.exceptions.RequestException as err:
raise SystemExit(err)
return cert_data
def write_yara(iocs, 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 certificate-based Yara rules from Abuse.ch MalwareBazar Code Signing Certificate Blocklist\n"
file_header += " Author: Automatically generated by MBCSCBYar (ditekSHen)\n"
file_header += " Reference: https://bazaar.abuse.ch/faq/#cscb\n"
file_header += " Reference: https://github.com/ditekshen\n"
file_header += "*/\n\n"
fw.write(file_header)
fw.write('import "pe"\n\n')
for cert in iocs:
rule_name = "rule INDICATOR_KB_CERT_%s {\n" % cert["serial_number"].lower()
rule_meta = " meta:\n"
rule_meta += " author = \"ditekSHen\"\n"
rule_meta += " description = \"Detects executables signed with stolen, revoked or invalid certificates\"\n"
rule_meta += " thumbprint = \"%s\"\n" % cert["thumbprint"].lower()
rule_meta += " reason = \"%s\"\n" % cert["reason"]
rule_meta += " reference = \"https://bazaar.abuse.ch/faq/#cscb\"\n"
rule_condition = " condition:\n"
rule_condition += " uint16(0) == 0x5a4d and\n"
rule_condition += " for any i in (0..pe.number_of_signatures): (\n"
rule_condition += " pe.signatures[i].subject contains \"%s\" and\n" % cert["subject_cn"]
rule_condition += " pe.signatures[i].serial == \"%s\"\n" % ':'.join(cert["serial_number"][i:i + 2] for i in range(0, len(cert["serial_number"]), 2)).lower()
rule_condition += " )\n"
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:
mbcscb_to_yara.py - Download CSCB CSV file from URL and write Yara rules file using default file name (defaults)
mbcscb_to_yara.py -o name.yar - Download CSCB CSV file from URL and save generated Yara rules file using custom name
mbcscb_to_yara.py -i cscb.csv - Read local CSCB CSV file and write Yara rules file using default file name
mbcscb_to_yara.py -i cscb.csv -o name.yar - Read local CSCB CSV file and and save generated Yara rules file using custom name'''
parser = argparse.ArgumentParser(description='Generate Yara rules from Abuse.ch MalwareBazar Code Signing Certificate Blocklist (CSCB)',
epilog=usage_text, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-i', '--input', type=str, metavar='INPUT', required=False, action='store', help='Input CSCB CSV local file',)
parser.add_argument('-o', '--output', type=str, metavar='OUTPUT', required=False, default='certificates.yar', help='Output Yara rules file name')
args = parser.parse_args()
cert_data = parse_csv(args.input)
if len(cert_data) > 0:
write_yara(cert_data, args.output)
else:
print("No certificate IOCs found, or something went wrong!")
if __name__ == "__main__":
main()
+126
View File
@@ -0,0 +1,126 @@
#!/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()
+2 -1
View File
@@ -855,6 +855,7 @@ rule INDICATOR_OOXML_Excel4Macros_EXEC {
$s1 = ">FORMULA.FILL(" ascii nocase
$s2 = ">REGISTER(" ascii nocase
$s3 = ">EXEC(" ascii nocase
$s4 = ">RUN(" ascii nocase
condition:
uint32(0) == 0x6d783f3c and $ms and 2 of ($s*)
}
}