Merge pull request #76 from ryantxu1/master

Removing zscript from master branch
This commit is contained in:
Ryan Xu
2022-12-06 11:21:32 -05:00
committed by GitHub
14 changed files with 1 additions and 1009 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ See ATT&CK: [Netwalker - Techniques Used](https://attack.mitre.org/software/S045
|---|---|
|[Execution::Command and Scripting Interpreter (E1049)](../execution/command-and-scripting-interpreter.md)|Netwalker is written and executed in Powershell [[1]](#1)|
|[Defense Evasion::Obfuscated Files or Information (E1027)](../defense-evasion/obfuscated-files-or-information.md)|Netwalker is obfuscated with several layers of encoding, obfuscation, and encryption techniques such as base64, hexademcimal, and XOR [[1]](#1)|
|[Defense Evasion::Process Injection::Dynamic-Link Library Injection (E1055.001)](../defense-evasion/process-injection.md)|Netwalker uses reflective DLL loading to inject from memory [[1]](#1)|
|[Defense Evasion::Process Injection::Dynamic-link Library Injection (E1055.001)](../defense-evasion/process-injection.md)|Netwalker uses reflective DLL loading to inject from memory [[1]](#1)|
|[Impact::Data Encrypted for Impact (E1486)](../impact/data-encrypted-for-impact.md)|Netwalker encrypts files for ransom [[1]](#1)|
-3
View File
@@ -1,3 +0,0 @@
- Update capa_analysis.py to make it look pretty and increase usability
- update autofill.py to make it look pretty and increase usability
- Move global variables such as objective_list into a config file to reduce editing if things are changed
Binary file not shown.
Binary file not shown.
-34
View File
@@ -1,34 +0,0 @@
import os
import re
# Converts all header format to atx (# ...)
def dir_walk(directory):
ignorelist = ["nursery", '.github', '.git', 'LICENSE.txt', 'README.md', '.gitattributes', 'ynewsletters', 'yfaq', 'zscript']
# Iterate recursively over all files in the repo
for root, dirs, files in os.walk(directory):
if not any(block in root for block in ignorelist):
for name in files:
f = open(os.path.join(root, name), "r")
lines = f.readlines() # Read contents of each capa rule
f.close()
for line in lines:
equals = re.search("={3,}\n", line) # Search capa rule for attack mapping, if found, add to attack counter
if equals:
print(os.path.join(root, name))
index = lines.index(equals.group(0))
lines.remove(equals.group(0))
lines[index-1] = "# {0}\n".format(lines[index-1])
with open(os.path.join(root, name), 'w') as f:
for line in lines:
f.write(line)
f.close()
dir_walk('..')
-277
View File
@@ -1,277 +0,0 @@
#!/usr/bin/python
import sys
import re
import glob
from fuzzywuzzy import fuzz # pip install fuzzywuzzy python-Levenshtein
MALWARE_EXAMPLES_HEADER = "\nMalware Examples\n----------------\n|Name|Date|Description|\n|---|---|---|\n"
REFERENCES_HEADER = "\nReferences\n----------"
ATTACK_TECHNIQUE_HEADER = "\nATT&CK Techniques\n-----------------\n|Name|Use|\n|---|---|\n"
BEHAVIORS_HEADER = "\nBehaviors\n---------\n|Name|Use|\n|---|---|\n"
def file_search(file_lines, string): # Searches file f for a string, returns the line number. If not found, return -1
count = 0
for x in file_lines:
if string in x:
return count
count += 1
return -1
def fuzzy_file_directory_search(files, string): # Searches file directories for a file using fuzzy matching
count = 0
f = ''
for file in files:
x = fuzz.partial_ratio(file, string)
# print(file + " " + str(x))
if x > count: # Returns highest fuzzy match score
count = x
f = file
if count == 0 or f is None:
raise Exception("Fuzzy file search did not find anything: ".format(string))
return f
def populate_behavior(name, date, reference, path, description, orig_file):
# if len(sys.argv) != 4:
# print("This script needs three command-and-scripting-interpreter parameters: the malware name, date, and reference link. Additionally, paste the markdown into the input file")
# return
# malware_name = sys.argv[1]
# malware_date = sys.argv[2]
# reference_link = sys.argv[3]
# input_regex = "\[[^]]*\]\(([^\)]*)\)\|(.*?) \["
# input_regex2 = "\[[^]]*\]\(([^\)]*)\)\|"
reference_regex = "<a name="
# lines = []
# with open("input") as f: # Reading input file
# lines = f.readlines()
# for line in lines: # Pulling path+description from input file
# x = re.search(input_regex, line)
# try:
# path = x.group(1)
# description = x.group(2)
# except AttributeError:
# x = re.search(input_regex2, line)
# path = x.group(1)
# description = ""
with open(path, "r+") as f: # Navigating to 'path', determining if behavior already has a 'Malware Example' section
mbcBehaviorLines = f.readlines()
f.seek(0)
mbcFile = f.read()
if file_search(mbcBehaviorLines, name) != -1: # If malware is already listed, skip this file
print("[+] Detecting that {} is already in {}\n".format(name, path))
return
malware_examples_line = file_search(mbcBehaviorLines, 'Malware Examples') # Determining if Malware Examples and Reference sections are present
references_line = file_search (mbcBehaviorLines, 'References')
if malware_examples_line == -1: # If there is no malware_examples line, build one
if references_line == -1: # If there is no reference section, we can write malware_examples to the end
mbcBehaviorLines.append(MALWARE_EXAMPLES_HEADER)
malware_examples_line = len(mbcBehaviorLines) - 1
else:
mbcBehaviorLines.insert(references_line - 1, MALWARE_EXAMPLES_HEADER)
malware_examples_line = references_line - 1
if references_line == -1: # If there is no reference section, write a reference header at the end of the file
mbcBehaviorLines.append(REFERENCES_HEADER)
references_line = len(mbcBehaviorLines)
# Count number of references present, then add one for the new entry
reference_num = len(re.findall(reference_regex, mbcFile)) + 1
# Building the text
malware_example_text = "|[**{}**]({})|{}|{} [[{}]](#{})|\n".format(name, orig_file, date, description, reference_num, reference_num)
reference_text = '\n<a name="{}">[{}]</a> {}\n'.format(reference_num, reference_num, reference)
# Insert malware notation in the line above the Reference line (which should be the bottom of malware examples)
# Insert new reference at the end
mbcBehaviorLines.insert(references_line - 1, malware_example_text)
mbcBehaviorLines.append(reference_text)
# Fix some spacing issues between sections if present
malware_examples_line = file_search(mbcBehaviorLines, 'Malware Examples')
if mbcBehaviorLines[malware_examples_line - 1] != '\n':
mbcBehaviorLines.insert(malware_examples_line, '\n')
references_line = file_search(mbcBehaviorLines, 'References')
if mbcBehaviorLines[references_line - 1] != '\n':
mbcBehaviorLines.insert(references_line, '\n')
with open(path, "w") as f:
f.writelines(mbcBehaviorLines)
print("[+] Inserting Malware Reference into {}\n".format(path))
return
# Receives an input file such as 'example_input', parses the file and inserts corresponding information into the markdown
# NOTE: Does require the example malware file to be created first
def populate_malware_example(input_file):
references = []
input_regex = "(.*?) (\(\S+)\s+\[(\d)\]\s(.*)"
input_regex2 = "(.*?) (\(\S+)\s+\[(\d)\]\s"
reference_regex = '<a name="\d+">\[\d+\]<\/a> (\S+)'
date_regex = "\|\*\*Year\*\*\|(.*?)\|"
mbc_file_map = glob.glob('../**/*.md', recursive=True) # Get list of all files in MBC
with open(input_file) as f: # Reading input file
# Read first line, which should be a name
line = f.readline()
if not re.search('X\d{4}', line): # Asserts that name line (Kraken X0010) is correctly formatted
raise Exception("Name syntax not correct")
name_line = line.split()
# Start iteratively reading the next lines
input_lines = f.readlines()
print("[+] Input File parsed, searching for {}".format(name_line[0]))
# Try to match malware name to the corresponding xample-malware using fuzzy string matching
malware_files = glob.glob("../xample-malware/*")
name = "../xample-malware/" + name_line[0].lower() + ".md"
modified_xample_file = fuzzy_file_directory_search(malware_files, name)
print("[+] Malware file found: {}\n".format(modified_xample_file))
# Reading the xample-malware file
with open(modified_xample_file) as f:
xample_file_lines = f.readlines()
f.seek(0)
xample_file_whole = f.read()
# Verify file id with xample_file
if name_line[1] not in xample_file_whole:
raise("Exception malware ID did not match file")
# Get date
date = re.findall(date_regex, xample_file_whole)[0]
# Searching xample-malware file to see what sections are present
attack_techniques_line = file_search(xample_file_lines, 'ATT&CK Techniques')
behaviors_line = file_search(xample_file_lines, 'Behaviors')
references_line = file_search(xample_file_lines, 'References')
# Fill in missing sections
if references_line == -1:
xample_file_lines.append(REFERENCES_HEADER)
# print(xample_file_lines)
if behaviors_line == -1:
references_line = file_search(xample_file_lines, 'References')
xample_file_lines.insert(references_line, BEHAVIORS_HEADER)
if attack_techniques_line == -1:
behaviors_line = file_search(xample_file_lines, 'Behaviors')
xample_file_lines.insert(behaviors_line, ATTACK_TECHNIQUE_HEADER)
# Count number of references present
existing_references = re.findall(reference_regex, xample_file_whole)
for ref in existing_references:
references.append(ref)
reference_diff = len(existing_references)
# Iterate through input file and populate xample-malware file
for line in input_lines:
if line.isspace():
continue
if "Reference" in line: # Determines if reference is already present, if not, add it
reference_link = line.split()[-1]
if reference_link not in xample_file_whole:
references.append(reference_link)
reference_num = len(references)
reference_text = '\n<a name="{}">[{}]</a> {}\n'.format(reference_num, reference_num, reference_link)
xample_file_lines.append(reference_text)
else: # Parse behavior/technique lines
print("[+] Parsing " + line.replace("\n", ''))
x = re.search(input_regex, line)
try:
technique_behavior = x.group(1)
id = x.group(2)
reference = x.group(3)
description = x.group(4)
except AttributeError: # In case description is absent
x = re.search(input_regex2, line)
technique_behavior = x.group(1)
id = x.group(2)
reference = x.group(3)
if reference_diff > 0:
reference_diff -= 1
reference = str(int(reference) + reference_diff)
reference_link = references[int(reference) - 1]
if id in xample_file_whole:
print("[+] Skipping {} because already present".format(id))
continue
if 'T' in id: # Determine if ATT&CK technique
attack_link = "https://attack.mitre.org/techniques/{}/".format(id.replace('(', '').replace(')', '').replace('.', '/'))
technique_text = "|[{} {}]({})|{} [[{}]](#{})|\n".format(technique_behavior, id, attack_link, description, reference, reference)
behaviors_line = file_search(xample_file_lines, 'Behaviors')
xample_file_lines.insert(behaviors_line, technique_text)
print("[+] Inserting ATT&CK technique: {}\n".format(technique_behavior))
else: # If it is an MBC behavior
# Try to fuzzy match the input behavior to a file
print("[+] Searching for {}".format(technique_behavior))
mbc_file = fuzzy_file_directory_search(mbc_file_map, technique_behavior)
print("[+] Behavior found: {}".format(mbc_file))
behavior_text = "|[{} {}]({})|{} [[{}]](#{})|\n".format(technique_behavior, id, mbc_file, description, reference, reference)
references_line = file_search(xample_file_lines, 'References')
xample_file_lines.insert(references_line, behavior_text)
# Add malware entry into the behavior file itself
populate_behavior(name_line[0], date, reference_link, mbc_file, description, modified_xample_file)
# Fix some spacing issues between sections if present
behaviors_line = file_search(xample_file_lines, 'Behaviors')
if xample_file_lines[behaviors_line - 1] != '\n':
xample_file_lines.insert(behaviors_line, '\n')
references_line = file_search(xample_file_lines, 'References')
if xample_file_lines[references_line - 1] != '\n':
xample_file_lines.insert(references_line, '\n')
with open(modified_xample_file, "w") as f:
f.writelines(xample_file_lines)
def main():
if len(sys.argv) != 2:
print("This script needs one command-and-scripting-interpreter parameters: the path to the input file")
return
input_file = sys.argv[1]
populate_malware_example(input_file)
return
if __name__=="__main__":
main()
-107
View File
@@ -1,107 +0,0 @@
#!/usr/bin/python3
import os
import re
import sys
from collections import Counter
import termplotlib as tpl
import yaml
# Walk through capa directory, ignoring files within the ignorelist folders
# Read each file and use regex to match mbc or attack mappings
# If found, insert them into the corresponding Counter
def dir_walk(directory):
attack_regex = "att&ck:\s*- ([^\n]*)"
mbc_regex = "mbc:\s*- ([^\n]*)"
ignorelist = ["nursery", '.github', 'LICENSE.txt', 'README.md', '.gitattributes', '.git']
attack_mappings = Counter()
mbc_mappings = Counter()
# Iterate recursively over all files in the repo
for root, dirs, files in os.walk(directory):
if not any(block in root for block in ignorelist):
for name in files:
f = open(os.path.join(root, name), "r")
capa_rule = f.read() # Read contents of each capa rule
attack = re.search(attack_regex, capa_rule) # Search capa rule for attack mapping, if found, add to attack counter
if attack:
attack_mappings.update(Counter([attack.group(1)]))
mbc = re.search(mbc_regex, capa_rule)
if mbc:
mbc_mappings.update(Counter([mbc.group(1)]))
return attack_mappings, mbc_mappings
def plot(dict):
keys = list(dict.keys())
nums = [dict[x]['num'] for x in keys]
fig = tpl.figure()
fig.barh(nums, keys, force_ascii=True)
fig.show()
# Takes a list of tactics/behaviors and converts them as keys in a dict
# Iterates over list of mappings and split the strings to separate tactics/techniques, behaviors/methods
# Insert into dictionary
# Print out results and create a histogram
def analysis(map, keys, mbc_micro_behaviors=None):
tactic_behavior_dict = {k: {'num':0, 'rule':[]} for k in keys}
if mbc_micro_behaviors:
micro_behavior_dict = {k: {'num':0, 'rule':[]} for k in mbc_micro_behaviors}
for mapping in map:
try:
split_map = mapping.split("::", 1)
tactic_behavior = split_map[0]
tactic_behavior_dict[tactic_behavior]['rule'].append(split_map[1])
tactic_behavior_dict[tactic_behavior]['num'] += 1
except KeyError:
if mbc_micro_behaviors:
try:
micro_behavior_dict[tactic_behavior]['rule'].append(split_map[1])
micro_behavior_dict[tactic_behavior]['num'] += 1
except KeyError:
print("The following MBC mapping could not be identified: " + str(mapping))
else:
print("The following ATT&CK mapping could not be identified: " + str(mapping))
if mbc_micro_behaviors is None:
print("---------ATT&CK MAPPINGS---------")
print(yaml.dump(tactic_behavior_dict, default_flow_style=False))
plot(tactic_behavior_dict)
else:
print("\n---------MBC MAPPINGS---------")
print(yaml.dump(tactic_behavior_dict, default_flow_style=False))
plot(tactic_behavior_dict)
print("\n---------MBC MICRO-BEHAVIOR MAPPINGS---------")
print(yaml.dump(micro_behavior_dict, default_flow_style=False))
plot(micro_behavior_dict)
def return_mbc_mapping(capa_dir):
attack_mapping, mbc_mapping = dir_walk(capa_dir)
return dict(mbc_mapping)
if __name__ == "__main__":
if sys.argv[1] == "-h":
print("This script analyzes the capa repo to determine the coverage wrt ATT&CK + MBC. \n Usage: python3 capa_analysis.py <directory>")
directory = sys.argv[1]
attack_tactics = ["Reconnaissance", "Resource Development", "Initial Access", "Execution", "Persistence", "Privilege Escalation", "Defense Evasion", "Credential Access", "Discovery", "Lateral Movement", "Collection", "Command and Control", "Exfiltration", "Impact"]
mbc_behaviors = ["Anti-Behavioral Analysis", "Anti-Static Analysis", "Collection", "Command and Control", "Credential Access", "Defense Evasion", "Discovery", "Execution", "Exfiltration", "Impact", "Lateral Movement","Persistence", "Privilege Escalation"]
mbc_micro_behaviors = ["Communication", "Cryptography", "Data", "File System", "Hardware", "Memory", "Operating System", "Process"]
attack_mapping, mbc_mapping = dir_walk(directory)
analysis(attack_mapping, attack_tactics)
analysis(mbc_mapping, mbc_behaviors, mbc_micro_behaviors=mbc_micro_behaviors)
print(dict(mbc_mapping))
-57
View File
@@ -1,57 +0,0 @@
"""
Analyze CAPEv2 community signature modules, extract information, and produce
CSV content.
"""
import argparse
import csv
import importlib
import inspect
import logging
import logging.config
import pathlib
import stix2
import stix2.utils
import sys
# From CAPEv2, or the stubs
import lib.cuckoo.common.abstracts
# From CAPEv2 community repo; successfully importing this module probably
# requires adding the appropriate path to $PYTHONPATH.
#
# See: https://github.com/kevoreilly/community
import modules.signatures
def parse_args():
"""
Parse commandline arguments.
"""
arg_parser = argparse.ArgumentParser(
description="Analyze CAPEv2 community signatures and create CSV"
" content."
)
arg_parser.add_argument(
"-o", "--out", required=True,
help="""
Directory path to the CAPE community repo.
"""
)
arg_parser.add_argument(
"-o", "--out", required=True
help="""
A filename to write content to. If not given, write to stdout.
"""
)
return arg_parser.parse_args()
def main():
if __name__ == "__main__":
main()
-10
View File
@@ -1,10 +0,0 @@
Kraken X0010
Date 2008
Reference [1] http://blog.threatexpert.com/2008/04/kraken-changes-tactics.html
Command and Control::Dynamic Resolution:Domain Generation Algorithms (T1568.002) [1] Uses a domain name generator. 
Command and Control::Application Layer Protocol::Web Protocols (T1568.002) [1] The malware uses HTTP to communicate with C2
Command and Control::Domain Name Generation (B0003) [1]
Anti-Behavioral Analysis::Memory Dump Evasion (B0006) [1] Dumping Kraken's c.dll module from the heap of its own process is tricky because its PE-header is wiped out.
-215
View File
@@ -1,215 +0,0 @@
#!/usr/bin/python
import argparse
import re
import subprocess
import yaml
from capa_analysis import return_mbc_mapping
objective_list = ['anti-behavioral-analysis', 'anti-static-analysis', 'collection', 'command-and-control', 'credential-access', 'defense-evasion', 'discovery', 'execution', 'exfiltration', 'impact', 'lateral-movement', 'micro-behaviors', 'persistence', 'privilege-escalation']
capa_rule_blacklist = ['README', 'format']
def yaml_find(d, tag):
if tag in d:
yield d[tag]
for k, v in d.items():
if isinstance(v, dict):
for i in yaml_find(v, tag):
yield i
# Fills file with the detection capa + CAPE headers. Returns new lines and indexes of capa and cape indicating where new entries should be placed
def fill_detection(behavior_lines, index):
behavior_lines.insert(index, "\n")
behavior_lines.insert(index+1, "## Detection\n")
behavior_lines.insert(index+2, "\n")
behavior_lines.insert(index+3, "|Tool: capa|Mapping|APIs|\n")
behavior_lines.insert(index+4, "|---|---|---|\n")
behavior_lines.insert(index+5, "\n")
behavior_lines.insert(index+6, "|Tool: CAPE|Mapping|APIs|\n")
behavior_lines.insert(index+7, "|---|---|---|\n")
behavior_lines.insert(index+8, "\n")
return behavior_lines, index+5, index+8
# Starting at 'index', parse each line for text in between '[]', which is the rule name. Ends when a blank line is reached. Returns array of rules
def detect_existing_rules(behavior_lines, index):
rules = []
rule_line = behavior_lines[index]
rule_re = "\[([^\]]+)]"
while capa_line != "\n":
rules.append(re.search(rule_re, rule_line).group(1))
index += 1
capa_line = behavior_lines[index]
return rules
# Searches capa-rules repo for mentions of id using subprocess + grep, returns list of capa files that have MBC rule
def search_capa_rules(id, capa_repo):
capa_rule_paths = []
grep_output = subprocess.run(["grep", "-r", id, capa_repo], capture_output=True)
grep_output = grep_output.stdout
rules = grep_output.decode().split('\n')
for rule in rules:
if rule == '':
continue
rule_path = rule.split(' ', 1)[0][:-1]
if not any(substring in rule_path for substring in capa_rule_blacklist):
capa_rule_paths.append(rule_path)
return capa_rule_paths
# Parses given capa rules and generates and inserts text into MBC file
def fill_capa_rules(capa_rules_path, behavior_lines):
for rule in capa_rules_path:
with open(rule) as f:
capa_yaml = yaml.safe_load(f)
f.close()
# print(capa_yaml)
rule_name = capa_yaml['rule']['meta']['name']
api = list(yaml_find(capa_yaml, 'api'))
if len(api) > 1:
raise Exception(">1 API FOUND")
api = api[0]
print(capa_yaml.keys())
print(rule_name)
print(api)
raise Exception
def test(file):
try:
with open(file) as f:
behavior_lines = f.readlines()
f.close()
except FileNotFoundError:
print("[X] FILE NOT FOUND: " + file)
return -1
# Determine if 'Detection' section already present
if "## Detection\n" not in behavior_lines:
if "## Code Snippets\n" in behavior_lines:
index = behavior_lines.index("## Code Snippets\n") - 1
elif "## References\n" in behavior_lines:
index = behavior_lines.index("## References\n") - 1
else:
print("[X] Code Snippet or Reference Section not found")
return -1
behavior_lines, capa_index, cape_index = fill_detection(behavior_lines, index)
else:
capa_index = behavior_lines.index("|Tool: capa|Mapping|APIs|\n") + 2
cape_index = behavior_lines.index("|Tool: CAPE|Mapping|APIs|\n") + 2
# If 'Detection' section present, detect existing rules
capa_rules = detect_existing_rules(behavior_lines, capa_index)
cape_rules = detect_existing_rules(behavior_lines, cape_index)
with open(file, 'w') as f:
for line in behavior_lines:
f.write(line)
f.close()
def main():
# Initialize parser
parser = argparse.ArgumentParser(description="Inserts a 'detection' section into behaviors. The section will contain info on capa and cape rules related to that behavior")
# Adding arguments
parser.add_argument("-i", "--id", help = "ID (B0001)")
parser.add_argument("-o", "--objective", nargs='+', help = "Objectives separated by spaces, replace spaces within the name with underscore (Anti-Behavioral_Analysis Anti-Static_Analysis)")
parser.add_argument("-a", "--attack", nargs='+', help = "Related ATT&CK Techniques grouped by name and ID (Debugger_Evasion,T1622 Virtualization/Standbox_Evasion_Checks,T1497.001,T1633.001)")
parser.add_argument("-t", "--type", help = "Anti-Analysis or Impact Types (Evasion, Detection, Integrity, Breach, Availability)")
parser.add_argument("-v", "--version", help="Version")
parser.add_argument("-m", "--last_modified", help="Last modified date (1_August_2019)")
parser.add_argument("-c", "--capa", help="capa-rules directory", required=True)
parser.add_argument("-f", "--file")
# Read arguments from command line
args = parser.parse_args()
if args.file:
test(args.file)
return
# Gets a dict of all behaviors that are mentioned in capa, along with count
capa_behaviors = return_mbc_mapping(args.capa)
for behavior, count in capa_behaviors.items():
# Splitting dict entry into behavior and id
# EX: communication/socket-communication/create-udp-socket, C0001.010
str_split = behavior.split(" [", 1)
behavior_path = str_split[0].lower().replace('::', '/').replace(' ', '-')
id = str_split[1][:-1]
# if method or sub-microbehavior, remove portion from path
if '.' in id:
str_split = behavior_path.split("/")[:-1]
behavior_path = '/'.join(str_split)
# If microbehavior, add 'micro-behaviors' to behavior path
objective = behavior_path.split('/')[0]
if objective not in objective_list:
behavior_path = 'micro-behaviors/' + behavior_path
behavior_path = '../' + behavior_path + '.md'
try:
with open(behavior_path) as f:
behavior_lines = f.readlines()
f.close()
except FileNotFoundError:
print("[X] FILE NOT FOUND: " + behavior_path)
return -1
if "## Code Snippets\n" in behavior_lines:
index = behavior_lines.index("## Code Snippets\n") - 1
elif "## References\n" in behavior_lines:
index = behavior_lines.index("## References\n") - 1
else: # If Code Snippet or Reference Section missing, return index of last line
index = len(behavior_lines) - 1
x = search_capa_rules(id, args.capa)
fill_capa_rules(x, behavior_lines)
# print(capa_behaviors.keys())
# print(yaml.dump(capa_behaviors, default_flow_style=False))
if __name__=="__main__":
main()
-176
View File
@@ -1,176 +0,0 @@
#!/usr/bin/python
import argparse
from fuzzywuzzy import fuzz # pip install fuzzywuzzy python-Levenshtein
objective_list = ['anti-behavioral-analysis', 'anti-static-analysis', 'collection', 'command-and-control', 'credential-access', 'defense-evasion', 'discovery', 'execution', 'exfiltration', 'impact', 'lateral-movement', 'micro-behaviors', 'persistence', 'privilege-escalation']
anti_analysis_types = ['Evasion', 'Detection']
impact_types = ['Integrity', 'Breach', 'Availability']
# Checks if 'string' in 'l' at index 'line_num'. If missing, insert 'string' into 'l' at index 'line_num'
# Return possibly modified 'l'
def insert_if_missing(l, line_num, string):
if l[line_num] != string:
l.insert(line_num, string)
return l
# Matches string to an entry in objective_list
def objective_search(string):
string = string.lower().replace('_', '-')
if string not in objective_list:
raise Exception("Objective {} did not match anything: ".format(string))
return "../" + string
def main():
# Initialize parser
parser = argparse.ArgumentParser(description="Inserts a formatted header for MBC. Only add parameters that are missing. In case of bugs, only run on a second copy")
# Adding arguments
parser.add_argument("-f", "--file", help = "File to modify", required=True)
parser.add_argument("-i", "--id", help = "ID (B0001)")
parser.add_argument("-o", "--objective", nargs='+', help = "Objectives separated by spaces, replace spaces within the name with underscore (Anti-Behavioral_Analysis Anti-Static_Analysis)")
parser.add_argument("-a", "--attack", nargs='+', help = "Related ATT&CK Techniques grouped by name and ID (Debugger_Evasion,T1622 Virtualization/Standbox_Evasion_Checks,T1497.001,T1633.001)")
parser.add_argument("-t", "--type", help = "Anti-Analysis or Impact Types (Evasion, Detection, Integrity, Breach, Availability)")
parser.add_argument("-v", "--version", help="Version")
parser.add_argument("-c", "--created", help="Method Creation Date (1_August_2019)")
parser.add_argument("-m", "--last_modified", help="Last modified date (1_August_2019)")
# Read arguments from command line
args = parser.parse_args()
# Read file
file = args.file
with open(file) as f:
lines = f.readlines()
f.close()
offset = 0 # Handles unique fields such as anti-analysis/impact type
# Some files have an empty line 1, delete that
if lines[0] == '\n':
lines.pop(0)
# Checking if first line is <table>, if not, that means this file does not have any appropriate header formatting
lines = insert_if_missing(lines, 0, "<table>\n")
lines = insert_if_missing(lines, 1, "<tr>\n")
# Adding ID field
if args.id:
lines = insert_if_missing(lines, 2, "<td><b>ID</b></td>\n")
lines.insert(3, "<td><b>{}</b></td>\n".format(args.id))
lines.insert(4, "</tr>\n")
# Adding Objective field
if args.objective:
lines = insert_if_missing(lines, 5, "<tr>\n")
lines = insert_if_missing(lines, 6, "<td><b>Objective(s)</b></td>\n")
# Build objectives if multiple
obj_str = "<td><b>"
for objective in args.objective:
obj_path = objective_search(objective)
objective = objective.replace('_', ' ')
obj_str = obj_str + "<a href=\"{}\">{}</a>, ".format(obj_path, objective)
# Chop off last ', '
obj_str = obj_str[:len(obj_str) - 2]
obj_str = obj_str + "</b></td>\n"
lines.insert(7, obj_str)
lines.insert(8, "</tr>\n")
# Adding Related ATT&CK Techniques Field
if args.attack:
lines = insert_if_missing(lines, 9, "<tr>\n")
lines = insert_if_missing(lines, 10, "<td><b>Related ATT&CK Techniques</b></td>\n")
# Build attack links if multiple
attack_str = "<td><b>"
for attack in args.attack:
attack = attack.split(",")
attack_name = attack[0].replace('_', ' ')
attack_str = attack_str + attack_name + " ("
# Looking at technique IDs now
for i in range(1, len(attack)):
attack_id = attack[i]
attack_id_dash = attack_id.replace('.', '/')
attack_str = attack_str + "<a href=\"https://attack.mitre.org/techniques/{}/\">{}</a>, ".format(attack_id_dash, attack_id)
# Chop off last ', '
attack_str = attack_str[:len(attack_str) - 2]
attack_str = attack_str + "), "
# Chop off last ', '
attack_str = attack_str[:len(attack_str) - 2]
attack_str = attack_str + "</b></td>\n"
lines.insert(11, attack_str)
lines.insert(12, "</tr>\n")
print(attack_str)
# Adding Anti-Analysis/Impact Type
if args.type:
if args.type in impact_types:
lines.insert(13, "<tr>\n")
lines = insert_if_missing(lines, 14, "<td><b>Impact Type</b></td>\n")
elif args.type in anti_analysis_types:
lines.insert(13, "<tr>\n")
lines = insert_if_missing(lines, 14, "<td><b>Anti-Analysis Type</b></td>\n")
else:
raise Exception("Anti-Analysis/Impact Type is not valid")
lines.insert(15, "<td><b>{}</b></td>\n".format(args.type))
lines.insert(16, "</tr>\n")
offset += 4
# Adding version field
if args.version:
lines = insert_if_missing(lines, 13+offset, "<tr>\n")
lines = insert_if_missing(lines, 14+offset, "<td><b>Version</b></td>\n")
lines.insert(15+offset, "<td><b>{}</b></td>\n".format(args.version))
lines.insert(16+offset, "</tr>\n")
# Adding Created field
if args.created:
lines = insert_if_missing(lines, 17+offset, "<tr>\n")
lines = insert_if_missing(lines, 18+offset, "<td><b>Created</b></td>\n")
created = args.created.replace('_', ' ')
lines.insert(19+offset, "<td><b>{}</b></td>\n".format(created))
lines.insert(20+offset, "</tr>\n")
# Adding Last Modified Field
if args.last_modified:
lines = insert_if_missing(lines, 21+offset, "<tr>\n")
lines = insert_if_missing(lines, 22+offset, "<td><b>Last Modified</b></td>\n")
last_modified = args.last_modified.replace('_', ' ')
lines.insert(23+offset, "<td><b>{}</b></td>\n".format(last_modified))
lines.insert(24+offset, "</tr>\n")
lines = insert_if_missing(lines, 25+offset, "</table>\n")
lines = insert_if_missing(lines, 26+offset, "\n")
# Now that modifications are complete, write to file
with open(file, "w") as f:
for line in lines:
f.write(line)
f.close()
return
if __name__=="__main__":
main()
View File
-69
View File
@@ -1,69 +0,0 @@
<table>
<tr>
<td><b>ID</b></td>
<td><b>E1113</b></td>
</tr>
<tr>
<td><b>Objective(s)</b></td>
<td><b><a href="../collection">Collection</a>, <a href="../credential-access">Credential Access</a></b></td>
</tr>
<tr>
<td><b>Related ATT&CK Techniques</b></td>
<td><b>Screen Capture (<a href="https://attack.mitre.org/techniques/T1113/">T1113</a>)</b></td>
</tr>
<tr>
<td><b>Version</b></td>
<td><b>2.0</b></td>
</tr>
<tr>
<td><b>Created</b></td>
<td><b>1 August 2019</b></td>
</tr>
<tr>
<td><b>Last Modified</b></td>
<td><b>31 October 2022</b></td>
</tr>
</table>
# Screen Capture
Malware takes screen captures of the desktop.
See ATT&CK: **Screen Capture ([T1113](https://attack.mitre.org/techniques/T1113/))**.
## Methods
|Name|ID|Description|
|---|---|---|
|**WinAPI**|E1113.m01|Screen is captured using WinAPI functions (e.g., user32.GetDesktopWindow).|
## Use in Malware
|Name|Date|Description|
|---|---|---|
|[**GotBotKR**](../xample-malware/gobotkr.md)|2019| GoBotKR is capable of capturing screenshots. [[1]](#1)|
|[**BlackEnergy**](../xample-malware/blackenergy.md)|2007|Screenshot plugin allows for collection of screenshots [[2]](#2)|
|[**DarkComet**](../xample-malware/dark-comet.md)|2008|Can take screenshots of victim's computer [[3]](#3)|
## Detection
|Tool: capa|Mapping|APIs|
|---|---|---|
|[check for microsoft office emulation](https://github.com/mandiant/capa-rules/blob/master/anti-analysis/anti-vm/vm-detection/check-for-microsoft-office-emulation.yml)|[Sandbox Detection::Product Key/ID Testing (B0007.005)|CreateFile|
|[check for sandbox and av modules](https://github.com/mandiant/capa-rules/blob/master/anti-analysis/anti-av/check-for-sandbox-and-av-modules.yml)|Sandbox Detection (B0007)|GetModuleHandle|
|Tool: CAPE|Mapping|APIs|
|---|---|---|
|[antisandbox_joe_anubis_files.py](https://github.com/kevoreilly/community/blob/master/modules/signatures/antisandbox_joe_anubis_files.py)|Sandbox Detection::Check Files (B0007.002)|--|
|[antisandbox_cuckoo_files](https://github.com/kevoreilly/community/blob/master/modules/signatures/antisandbox_cuckoo_files.py)|Sandbox Detection::Check Files (B0007.002)|--|
## References
<a name="1">[1]</a> https://www.welivesecurity.com/2019/07/08/south-korean-users-backdoor-torrents/
<a name="2">[2]</a> https://securelist.com/be2-custom-plugins-router-abuse-and-target-profiles/67353/
<a name="3">[3]</a> https://blog.malwarebytes.com/threat-analysis/2012/06/you-dirty-rat-part-1-darkcomet/
-60
View File
@@ -1,60 +0,0 @@
import os
import re
def dir_walk(directory):
ignorelist = ["nursery", '.github', '.git', 'LICENSE.txt', 'README.md', '.gitattributes', 'ynewsletters', 'yfaq', 'zscript']
# Iterate recursively over all files in the repo
for root, dirs, files in os.walk(directory):
if not any(block in root for block in ignorelist):
for name in files:
f = open(os.path.join(root, name), "r")
lines = f.readlines() # Read contents of each capa rule
f.close()
try:
index = lines.index('## Use in Malware\n')
except ValueError:
continue
# if lines[index+2] != "|Name|Date|Description|\n":
# print("{} has format issue".format(os.path.join(root,name)))
try:
index = lines.index('|Name|Date|Method|Description|\n')
except ValueError:
print("{} has format issue".format(os.path.join(root,name)))
break
index = lines.index("<td><b>Last Modified</b></td>\n")
lines[index+1] = "<td><b>21 November 2022</b></td>\n"
with open(os.path.join(root, name), 'w') as f:
for line in lines:
f.write(line)
f.close()
# for line in lines:
# equals = re.search("={3,}\n", line) # Search capa rule for attack mapping, if found, add to attack counter
# if equals:
# print(os.path.join(root, name))
# index = lines.index(equals.group(0))
# lines.remove(equals.group(0))
# lines[index-1] = "# {0}\n".format(lines[index-1])
# with open(os.path.join(root, name), 'w') as f:
# for line in lines:
# f.write(line)
# f.close()
dir_walk('..')