improving human readable documents by adding results of the attack

pull/12/head
Thorsten Sick 3 years ago
parent 10fa4a97d8
commit 7e6ff60e25

@ -5,9 +5,10 @@
import json import json
import datetime import datetime
from random import randint from random import randint
from typing import Optional
def __mitre_fix_ttp__(ttp): def __mitre_fix_ttp__(ttp: Optional[str]) -> str:
""" enforce some systematic naming scheme for MITRE TTPs """ """ enforce some systematic naming scheme for MITRE TTPs """
if ttp is None: if ttp is None:
@ -22,12 +23,12 @@ def __mitre_fix_ttp__(ttp):
class AttackLog(): class AttackLog():
""" A specific logger class to log the progress of the attack steps """ """ A specific logger class to log the progress of the attack steps """
def __init__(self, verbosity=0): def __init__(self, verbosity: int = 0):
""" """
@param verbosity: verbosity setting from 0 to 3 for stdout printing @param verbosity: verbosity setting from 0 to 3 for stdout printing
""" """
self.log = [] self.log: list[dict] = []
self.verbosity = verbosity self.verbosity = verbosity
# TODO. As soon as someone wants custom timestamps, make the format variable # TODO. As soon as someone wants custom timestamps, make the format variable
@ -41,12 +42,12 @@ class AttackLog():
self.log.append(item) self.log.append(item)
def __get_timestamp__(self): def __get_timestamp__(self) -> str:
""" Get the timestamp to add to the log entries. Currently not configurable """ """ Get the timestamp to add to the log entries. Currently not configurable """
return datetime.datetime.now().strftime(self.datetime_format) return datetime.datetime.now().strftime(self.datetime_format)
def get_caldera_default_name(self, ability_id): def get_caldera_default_name(self, ability_id: str):
""" Returns the default name for this ability based on a db """ """ Returns the default name for this ability based on a db """
data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": "whoami"} data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": "whoami"}
if ability_id not in data: if ability_id not in data:
@ -54,7 +55,7 @@ class AttackLog():
return data[ability_id] return data[ability_id]
def get_caldera_default_description(self, ability_id): def get_caldera_default_description(self, ability_id: str):
""" Returns the default description for this ability based on a db """ """ Returns the default description for this ability based on a db """
data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": "Obtain user from current session"} data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": "Obtain user from current session"}
@ -63,16 +64,16 @@ class AttackLog():
return data[ability_id] return data[ability_id]
def get_caldera_default_tactics(self, ability_id): def get_caldera_default_tactics(self, ability_id: str):
""" Returns the default tactics for this ability based on a db """ """ Returns the default tactics for this ability based on a db """
data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": " System Owner/User Discovery"} data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": "System Owner/User Discovery"}
if ability_id not in data: if ability_id not in data:
return None return None
return data[ability_id] return data[ability_id]
def get_caldera_default_tactics_id(self, ability_id): def get_caldera_default_tactics_id(self, ability_id: str):
""" Returns the default name for this ability based on a db """ """ Returns the default name for this ability based on a db """
data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": "T1033"} data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": "T1033"}
@ -81,7 +82,7 @@ class AttackLog():
return data[ability_id] return data[ability_id]
def get_caldera_default_situation_description(self, ability_id): def get_caldera_default_situation_description(self, ability_id: str):
""" Returns the default situation description for this ability based on a db """ """ Returns the default situation description for this ability based on a db """
data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": None} data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": None}
@ -90,7 +91,7 @@ class AttackLog():
return data[ability_id] return data[ability_id]
def get_caldera_default_countermeasure(self, ability_id): def get_caldera_default_countermeasure(self, ability_id: str):
""" Returns the default countermeasure for this ability based on a db """ """ Returns the default countermeasure for this ability based on a db """
data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": None} data = {"bd527b63-9f9e-46e0-9816-b8434d2b8989": None}
@ -99,7 +100,7 @@ class AttackLog():
return data[ability_id] return data[ability_id]
def start_caldera_attack(self, source, paw, group, ability_id, ttp=None, **kwargs): def start_caldera_attack(self, source: str, paw: str, group: str, ability_id: str, ttp: str = None, **kwargs):
""" Mark the start of a caldera attack """ Mark the start of a caldera attack
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -131,6 +132,7 @@ class AttackLog():
"countermeasure": kwargs.get("countermeasure", self.get_caldera_default_countermeasure(ability_id)), # Set by the attack "countermeasure": kwargs.get("countermeasure", self.get_caldera_default_countermeasure(ability_id)), # Set by the attack
"obfuscator": kwargs.get("obfuscator", "default"), "obfuscator": kwargs.get("obfuscator", "default"),
"jitter": kwargs.get("jitter", "default"), "jitter": kwargs.get("jitter", "default"),
"result": None,
} }
self.__add_to_log__(data) self.__add_to_log__(data)
@ -141,7 +143,7 @@ class AttackLog():
# TODO: Add config # TODO: Add config
# TODO: Add results # TODO: Add results
def stop_caldera_attack(self, source, paw, group, ability_id, ttp=None, **kwargs): def stop_caldera_attack(self, source: str, paw: str, group: str, ability_id: str, ttp: str = None, **kwargs):
""" Mark the end of a caldera attack """ Mark the end of a caldera attack
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -168,11 +170,12 @@ class AttackLog():
"description": kwargs.get("description", ""), "description": kwargs.get("description", ""),
"obfuscator": kwargs.get("obfuscator", "default"), "obfuscator": kwargs.get("obfuscator", "default"),
"jitter": kwargs.get("jitter", "default"), "jitter": kwargs.get("jitter", "default"),
"logid": kwargs.get("logid", None) "logid": kwargs.get("logid", None),
"result": kwargs.get("result", None),
} }
self.__add_to_log__(data) self.__add_to_log__(data)
def start_file_write(self, source, target, file_name): def start_file_write(self, source: str, target: str, file_name: str):
""" Mark the start of a file being written to the target (payload !) """ Mark the start of a file being written to the target (payload !)
@param source: source of the attack. Attack IP (empty if written from controller) @param source: source of the attack. Attack IP (empty if written from controller)
@ -196,7 +199,7 @@ class AttackLog():
self.__add_to_log__(data) self.__add_to_log__(data)
return logid return logid
def stop_file_write(self, source, target, file_name, **kwargs): def stop_file_write(self, source: str, target: str, file_name: str, **kwargs):
""" Mark the stop of a file being written to the target (payload !) """ Mark the stop of a file being written to the target (payload !)
@param source: source of the attack. Attack IP (empty if written from controller) @param source: source of the attack. Attack IP (empty if written from controller)
@ -220,12 +223,12 @@ class AttackLog():
self.__add_to_log__(data) self.__add_to_log__(data)
def start_execute_payload(self, source, target, command): def start_execute_payload(self, source: str, target: str, command: str):
""" Mark the start of a payload being executed """ Mark the start of a payload being executed
@param source: source of the attack. Attack IP (empty if written from controller) @param source: source of the attack. Attack IP (empty if written from controller)
@param target: Target machine of the attack @param target: Target machine of the attack
@param command: Name of the file being written @param command:
""" """
timestamp = self.__get_timestamp__() timestamp = self.__get_timestamp__()
@ -245,7 +248,7 @@ class AttackLog():
return logid return logid
def stop_execute_payload(self, source, target, command, **kwargs): def stop_execute_payload(self, source: str, target: str, command: str, **kwargs):
""" Mark the stop of a payload being executed """ Mark the stop of a payload being executed
@param source: source of the attack. Attack IP (empty if written from controller) @param source: source of the attack. Attack IP (empty if written from controller)
@ -266,7 +269,7 @@ class AttackLog():
} }
self.__add_to_log__(data) self.__add_to_log__(data)
def start_kali_attack(self, source, target, attack_name, ttp=None, **kwargs): def start_kali_attack(self, source: str, target: str, attack_name: str, ttp: str = None, **kwargs):
""" Mark the start of a Kali based attack """ Mark the start of a Kali based attack
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -295,6 +298,7 @@ class AttackLog():
"description": kwargs.get("description", None), # Generic description for this attack. Set by the attack "description": kwargs.get("description", None), # Generic description for this attack. Set by the attack
"situation_description": kwargs.get("situation_description", None), # Description for the situation this attack was run in. Set by the plugin or attacker emulation "situation_description": kwargs.get("situation_description", None), # Description for the situation this attack was run in. Set by the plugin or attacker emulation
"countermeasure": kwargs.get("countermeasure", None), # Set by the attack "countermeasure": kwargs.get("countermeasure", None), # Set by the attack
"result": None,
} }
self.__add_to_log__(data) self.__add_to_log__(data)
@ -304,7 +308,7 @@ class AttackLog():
# TODO: Add config # TODO: Add config
# TODO: Add results # TODO: Add results
def stop_kali_attack(self, source, target, attack_name, ttp=None, **kwargs): def stop_kali_attack(self, source: str, target: str, attack_name: str, ttp: str = None, **kwargs):
""" Mark the end of a Kali based attack """ Mark the end of a Kali based attack
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -321,11 +325,12 @@ class AttackLog():
"target": target, "target": target,
"kali_name": attack_name, "kali_name": attack_name,
"hunting_tag": __mitre_fix_ttp__(ttp), "hunting_tag": __mitre_fix_ttp__(ttp),
"logid": kwargs.get("logid", None) "logid": kwargs.get("logid", None),
"result": kwargs.get("result", None),
} }
self.__add_to_log__(data) self.__add_to_log__(data)
def start_narration(self, text): def start_narration(self, text: str):
""" Add some user defined narration. Can be used in plugins to describe the situation before and after the attack, ... """ Add some user defined narration. Can be used in plugins to describe the situation before and after the attack, ...
At the moment there is no stop narration command. I do not think we need one. But I want to stick to the structure At the moment there is no stop narration command. I do not think we need one. But I want to stick to the structure
@ -344,6 +349,42 @@ class AttackLog():
self.__add_to_log__(data) self.__add_to_log__(data)
return logid return logid
def start_attack_step(self, text: str):
""" Mark the start of an attack step (several attacks in a chunk)
@param text: description of the attack step being started
"""
timestamp = self.__get_timestamp__()
logid = timestamp + "_" + str(randint(1, 100000))
data = {"timestamp": timestamp,
"timestamp_end": None,
"event": "start",
"type": "attack_step",
"sub_type": "user defined attack step",
"text": text,
"logid": logid,
}
self.__add_to_log__(data)
return logid
def stop_attack_step(self, text: str, **kwargs):
""" Mark the end of an attack step (several attacks in a chunk)
@param text: description of the attack step being stopped
"""
data = {"timestamp": self.__get_timestamp__(),
"event": "stop",
"type": "attack_step",
"sub_type": "user defined attack step",
"text": text,
"logid": kwargs.get("logid", None)
}
self.__add_to_log__(data)
def start_build(self, **kwargs): def start_build(self, **kwargs):
""" Mark the start of a tool building/compilation process """ Mark the start of a tool building/compilation process
@ -401,7 +442,7 @@ class AttackLog():
} }
self.__add_to_log__(data) self.__add_to_log__(data)
def start_metasploit_attack(self, source, target, metasploit_command, ttp=None, **kwargs): def start_metasploit_attack(self, source: str, target: str, metasploit_command: str, ttp: str = None, **kwargs):
""" Mark the start of a Metasploit based attack """ Mark the start of a Metasploit based attack
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -429,12 +470,13 @@ class AttackLog():
"description": kwargs.get("description", None), # Generic description for this attack. Set by the attack "description": kwargs.get("description", None), # Generic description for this attack. Set by the attack
"situation_description": kwargs.get("situation_description", None), # Description for the situation this attack was run in. Set by the plugin or attacker emulation "situation_description": kwargs.get("situation_description", None), # Description for the situation this attack was run in. Set by the plugin or attacker emulation
"countermeasure": kwargs.get("countermeasure", None), # Set by the attack "countermeasure": kwargs.get("countermeasure", None), # Set by the attack
"result": None
} }
self.__add_to_log__(data) self.__add_to_log__(data)
return logid return logid
def stop_metasploit_attack(self, source, target, metasploit_command, ttp=None, **kwargs): def stop_metasploit_attack(self, source: str, target: str, metasploit_command: str, ttp: str = None, **kwargs):
""" Mark the start of a Metasploit based attack """ Mark the start of a Metasploit based attack
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -451,11 +493,12 @@ class AttackLog():
"target": target, "target": target,
"metasploit_command": metasploit_command, "metasploit_command": metasploit_command,
"hunting_tag": __mitre_fix_ttp__(ttp), "hunting_tag": __mitre_fix_ttp__(ttp),
"logid": kwargs.get("logid", None) "logid": kwargs.get("logid", None),
"result": kwargs.get("result", None)
} }
self.__add_to_log__(data) self.__add_to_log__(data)
def start_attack_plugin(self, source, target, plugin_name, ttp=None): def start_attack_plugin(self, source: str, target: str, plugin_name: str, ttp: str = None):
""" Mark the start of an attack plugin """ Mark the start of an attack plugin
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -485,7 +528,7 @@ class AttackLog():
# TODO: Add config # TODO: Add config
# TODO: Add results # TODO: Add results
def stop_attack_plugin(self, source, target, plugin_name, **kwargs): def stop_attack_plugin(self, source: str, target: str, plugin_name: str, **kwargs):
""" Mark the end of an attack plugin """ Mark the end of an attack plugin
@param source: source of the attack. Attack IP @param source: source of the attack. Attack IP
@ -507,7 +550,7 @@ class AttackLog():
} }
self.__add_to_log__(data) self.__add_to_log__(data)
def write_json(self, filename): def write_json(self, filename: str):
""" Write the json data for this log """ Write the json data for this log
@param filename: Name of the json file @param filename: Name of the json file
@ -526,6 +569,9 @@ class AttackLog():
if replace_entry["event"] == "start" and "logid" in replace_entry and replace_entry["logid"] == logid: if replace_entry["event"] == "start" and "logid" in replace_entry and replace_entry["logid"] == logid:
# Found matching start event. Updating it # Found matching start event. Updating it
replace_entry["timestamp_end"] = entry["timestamp"] replace_entry["timestamp_end"] = entry["timestamp"]
if "result" in entry:
replace_entry["result"] = entry["result"]
def get_dict(self): def get_dict(self):
""" Return logged data in dict format """ """ Return logged data in dict format """
@ -540,7 +586,7 @@ class AttackLog():
# TODO: Return full doc # TODO: Return full doc
def vprint(self, text, verbosity): def vprint(self, text: str, verbosity: int):
""" verbosity based stdout printing """ verbosity based stdout printing
0: Errors only 0: Errors only

@ -625,7 +625,7 @@ class CalderaControl():
self.add_adversary(adversary_name, ability_id) self.add_adversary(adversary_name, ability_id)
adid = self.get_adversary(adversary_name)["adversary_id"] adid = self.get_adversary(adversary_name)["adversary_id"]
self.attack_logger.start_caldera_attack(source=self.url, logid = self.attack_logger.start_caldera_attack(source=self.url,
paw=paw, paw=paw,
group=group, group=group,
ability_id=ability_id, ability_id=ability_id,
@ -682,9 +682,11 @@ class CalderaControl():
except CalderaError: except CalderaError:
pass pass
outp=""
if output is None: if output is None:
output = str(self.get_operation_by_id(opid)) outp = str(self.get_operation_by_id(opid))
self.attack_logger.vprint(f"{CommandlineColors.FAIL}Failed getting operation data. We just have: {output} from get_operation_by_id{CommandlineColors.ENDC}", 0) self.attack_logger.vprint(f"{CommandlineColors.FAIL}Failed getting operation data. We just have: {outp} from get_operation_by_id{CommandlineColors.ENDC}", 0)
else: else:
outp = str(output) outp = str(output)
self.attack_logger.vprint(f"{CommandlineColors.BACKGROUND_GREEN} Output: {outp} {CommandlineColors.ENDC}", 2) self.attack_logger.vprint(f"{CommandlineColors.BACKGROUND_GREEN} Output: {outp} {CommandlineColors.ENDC}", 2)
@ -704,7 +706,9 @@ class CalderaControl():
name=self.get_ability(ability_id)[0]["name"], name=self.get_ability(ability_id)[0]["name"],
description=self.get_ability(ability_id)[0]["description"], description=self.get_ability(ability_id)[0]["description"],
obfuscator=obfuscator, obfuscator=obfuscator,
jitter=jitter jitter=jitter,
logid=logid,
result=[outp]
) )
return True return True

@ -438,7 +438,8 @@ class MetasploitInstant(Metasploit):
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp, ttp=ttp,
logid=logid) logid=logid,
result=res)
return res return res
def migrate(self, target, user=None, name=None, arch=None): def migrate(self, target, user=None, name=None, arch=None):
@ -472,7 +473,8 @@ class MetasploitInstant(Metasploit):
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(), self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp) ttp=ttp,
result=res)
return res return res
def arp_network_discovery(self, target, **kwargs): def arp_network_discovery(self, target, **kwargs):
@ -505,7 +507,8 @@ class MetasploitInstant(Metasploit):
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp, ttp=ttp,
logid=logid) logid=logid,
result=res)
return res return res
def nslookup(self, target, target2, **kwargs): def nslookup(self, target, target2, **kwargs):
@ -542,7 +545,8 @@ class MetasploitInstant(Metasploit):
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp, ttp=ttp,
logid=logid) logid=logid,
result=res)
return res return res
def getsystem(self, target, **kwargs): def getsystem(self, target, **kwargs):
@ -580,7 +584,8 @@ Elevate privileges from local administrator to SYSTEM. Three ways to do that wil
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp, ttp=ttp,
logid=logid) logid=logid,
result=res)
return res return res
def clearev(self, target): def clearev(self, target):
@ -601,7 +606,8 @@ Elevate privileges from local administrator to SYSTEM. Three ways to do that wil
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(), self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp) ttp=ttp,
result=res)
return res return res
def screengrab(self, target): def screengrab(self, target):
@ -628,7 +634,8 @@ Elevate privileges from local administrator to SYSTEM. Three ways to do that wil
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(), self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp) ttp=ttp,
result=res)
return res return res
def keylogging(self, target, monitoring_time): def keylogging(self, target, monitoring_time):
@ -660,7 +667,8 @@ Elevate privileges from local administrator to SYSTEM. Three ways to do that wil
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(), self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp) ttp=ttp,
result=res)
return res return res
def getuid(self, target): def getuid(self, target):
@ -683,7 +691,8 @@ Elevate privileges from local administrator to SYSTEM. Three ways to do that wil
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(), self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp) ttp=ttp,
result=res)
return res[0] return res[0]
def sysinfo(self, target): def sysinfo(self, target):
@ -706,7 +715,8 @@ Elevate privileges from local administrator to SYSTEM. Three ways to do that wil
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(), self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp) ttp=ttp,
result=res)
return res[0] return res[0]
def upload(self, target, src, dst, **kwargs): def upload(self, target, src, dst, **kwargs):
@ -745,5 +755,6 @@ Uploading new files to the target. Can be config files, tools, implants, ...
target=target.get_ip(), target=target.get_ip(),
metasploit_command=command, metasploit_command=command,
ttp=ttp, ttp=ttp,
logid=logid) logid=logid,
result=res)
return res return res

@ -12,19 +12,18 @@ def generate(jfile, outfile):
loader=FileSystemLoader("templates", encoding='utf-8', followlinks=False), loader=FileSystemLoader("templates", encoding='utf-8', followlinks=False),
autoescape=select_autoescape(), autoescape=select_autoescape(),
trim_blocks=True, trim_blocks=True,
lstrip_blocks=True # lstrip_blocks=True
) )
template = env.get_template("attack_description.rst") template = env.get_template("attack_description.rst")
with open(jfile) as fh: with open(jfile) as fh:
events = json.load(fh) events = json.load(fh)
print(template.render(events=events)) rendered = template.render(events=events)
# pprint(events) print(rendered)
# dest = os.path.join(self.get_plugin_path(), "filebeat.conf")
# with open(dest, "wt") as fh: with open(outfile, "wt") as fh:
# res = template.render({"playground": self.get_playground()}) fh.write(rendered)
# fh.write(res)
if __name__ == "__main__": if __name__ == "__main__":
@ -34,8 +33,13 @@ if __name__ == "__main__":
# generate("loot/2021_07_28___12_09_00/attack.json", # generate("loot/2021_07_28___12_09_00/attack.json",
# "tools/human_readable_documentation/contents.rst") # FIN 7 The last minute locally generated thing # "tools/human_readable_documentation/contents.rst") # FIN 7 The last minute locally generated thing
generate("loot/2021_08_30___14_40_23/attack.json", # generate("loot/2021_08_30___14_40_23/attack.json",
"tools/human_readable_documentation/contents.rst") # FIN 7 With genereated files added # "tools/human_readable_documentation/contents.rst") # FIN 7 With genereated files added
# generate("removeme/loot/2021_09_07___08_59_42/attack.json",
# "tools/human_readable_documentation/source/contents.rst") # FIN 7 first run on environment
generate("loot/2021_09_07___16_20_48/attack.json",
"tools/human_readable_documentation/source/contents.rst") # FIN 7 locally with extended data (older: loot/2021_09_07___14_38_14)
# generate("loot/2021_07_19___15_10_45/attack.json", "tools/human_readable_documentation/contents.rst") # generate("loot/2021_07_19___15_10_45/attack.json", "tools/human_readable_documentation/contents.rst")
# generate("removeme.json", "tools/human_readable_documentation/contents.rst") # generate("removeme.json", "tools/human_readable_documentation/contents.rst")

@ -44,9 +44,7 @@ class FIN7Plugin(AttackPlugin):
def step1(self): def step1(self):
self.attack_logger.vprint(f"{CommandlineColors.OKBLUE}Step 1 (target hotelmanager): Initial Breach{CommandlineColors.ENDC}", 1) self.attack_logger.vprint(f"{CommandlineColors.OKBLUE}Step 1 (target hotelmanager): Initial Breach{CommandlineColors.ENDC}", 1)
self.attack_logger.start_attack_step("Step 1 (target hotelmanager): Initial Breach")
self.attack_logger.start_narration(
"Step 1 (target hotelmanager): Initial Breach\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
NOT IMPLEMENTED YET NOT IMPLEMENTED YET
@ -73,8 +71,7 @@ This is the initial attack step that requires user interaction. Maybe it is bett
def step2(self): def step2(self):
self.attack_logger.vprint(f"{CommandlineColors.OKBLUE}Step 2 (target hotelmanager): Delayed Malware Execution{CommandlineColors.ENDC}", 1) self.attack_logger.vprint(f"{CommandlineColors.OKBLUE}Step 2 (target hotelmanager): Delayed Malware Execution{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 2 (target hotelmanager): Delayed Malware Execution")
"Step 2 (target hotelmanager): Delayed Malware Execution\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
NOT IMPLEMENTED YET NOT IMPLEMENTED YET
@ -97,7 +94,7 @@ In this simulation sql-rat.js communication will be replaced by Caldera communic
def step3(self): def step3(self):
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 3 (target hotelmanager): Target Assessment{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 3 (target hotelmanager): Target Assessment{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration("Step 3 (target hotelmanager): Target Assessment\n----------------------------") self.attack_logger.start_attack_step("Step 3 (target hotelmanager): Target Assessment")
# TODO: Make sure logging is nice and complete # TODO: Make sure logging is nice and complete
@ -254,8 +251,7 @@ In this simulation sql-rat.js communication will be replaced by Caldera communic
""" """
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 4 (target hotelmanager): Staging Interactive Toolkit{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 4 (target hotelmanager): Staging Interactive Toolkit{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 4 (target hotelmanager): Staging Interactive Toolkit")
"Step 4 (target hotelmanager): Staging Interactive Toolkit\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
In the original attack Babymetal payload is a dll. Currently we are using a simplification here (directly calling a exe). The original steps are: In the original attack Babymetal payload is a dll. Currently we are using a simplification here (directly calling a exe). The original steps are:
* Target already runs adb156.exe. This one gets the shellcode over the network connection and decodes it. * Target already runs adb156.exe. This one gets the shellcode over the network connection and decodes it.
@ -305,8 +301,7 @@ In the original attack Babymetal payload is a dll. Currently we are using a simp
def step5(self): def step5(self):
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 5 (target hotelmanager): Escalate Privileges{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 5 (target hotelmanager): Escalate Privileges{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 5 (target hotelmanager): Escalate Privileges")
"Step 5 (target hotelmanager): Escalate Privileges\n----------------------------")
hotelmanager = self.get_target_by_name("hotelmanager") hotelmanager = self.get_target_by_name("hotelmanager")
@ -388,12 +383,14 @@ In the original attack Babymetal payload is a dll. Currently we are using a simp
situation_description="Executing Mimikatz through UAC bypassing powershell", situation_description="Executing Mimikatz through UAC bypassing powershell",
countermeasure="Behaviour detection" countermeasure="Behaviour detection"
) )
print(metasploit.meterpreter_execute_on([execute_samcats], hotelmanager, delay=20)) result = metasploit.meterpreter_execute_on([execute_samcats], hotelmanager, delay=20)
print(result)
self.attack_logger.stop_metasploit_attack(source=self.attacker_machine_plugin.get_ip(), self.attack_logger.stop_metasploit_attack(source=self.attacker_machine_plugin.get_ip(),
target=hotelmanager.get_ip(), target=hotelmanager.get_ip(),
metasploit_command=execute_samcats, metasploit_command=execute_samcats,
ttp="T1003", ttp="T1003",
logid=logid) logid=logid,
result=result)
# samcat.exe: reads local credentials https://attack.mitre.org/techniques/T1003/001/ # samcat.exe: reads local credentials https://attack.mitre.org/techniques/T1003/001/
@ -481,8 +478,7 @@ In the original attack Babymetal payload is a dll. Currently we are using a simp
def step6(self): def step6(self):
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 6 (target hotelmanager -> itadmin): Expand Access{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 6 (target hotelmanager -> itadmin): Expand Access{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 6 (target hotelmanager and itadmin): Expand Access")
"Step 6 (target hotelmanager and itadmin): Expand Access\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
NOT IMPLEMENTED YET. NEEDS A SECOND MACHINE FOR LATERAL MOVEMENT NOT IMPLEMENTED YET. NEEDS A SECOND MACHINE FOR LATERAL MOVEMENT
* powershell download: paexec.exe and hollow.exe https://attack.mitre.org/techniques/T1105/ * powershell download: paexec.exe and hollow.exe https://attack.mitre.org/techniques/T1105/
@ -543,8 +539,7 @@ NOT IMPLEMENTED YET. NEEDS A SECOND MACHINE FOR LATERAL MOVEMENT
def step7(self): def step7(self):
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 7 on itadmin: Setup User Monitoring{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 7 on itadmin: Setup User Monitoring{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 7 (target itadmin): Setup User Monitoring")
"Step 7 (target itadmin): Setup User Monitoring\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
NOT IMPLEMENTED YET. A REPLACEMENT FOR THE ALOHA COMMAND CENTER IS NEEDED NOT IMPLEMENTED YET. A REPLACEMENT FOR THE ALOHA COMMAND CENTER IS NEEDED
@ -579,8 +574,7 @@ NOT IMPLEMENTED YET. A REPLACEMENT FOR THE ALOHA COMMAND CENTER IS NEEDED
def step8(self): def step8(self):
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 8 (target: itadmin as domain_admin): User Monitoring{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 8 (target: itadmin as domain_admin): User Monitoring{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 8 (target itadmin): User Monitoring")
"Step 8 (target itadmin): User Monitoring\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
NOT IMPLEMENTED YET. MAYBE DO THIS PARTIAL. KEYLOGGING NEEDS USER INTERACTION. NOT IMPLEMENTED YET. MAYBE DO THIS PARTIAL. KEYLOGGING NEEDS USER INTERACTION.
(Screen spying and keylogging are already implemented as standalone metasploit attacks. Use them) (Screen spying and keylogging are already implemented as standalone metasploit attacks. Use them)
@ -700,8 +694,7 @@ NOT IMPLEMENTED YET. MAYBE DO THIS PARTIAL. KEYLOGGING NEEDS USER INTERACTION.
def step9(self): def step9(self):
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 9 (target: accounting): Setup Shim Persistence{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 9 (target: accounting): Setup Shim Persistence{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 9 (target accounting): Setup Shim Persistence")
"Step 9 (target accounting): Setup Shim Persistence\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
NOT IMPLEMENTED YET NOT IMPLEMENTED YET
@ -791,8 +784,7 @@ NOT IMPLEMENTED YET
self.attack_logger.vprint( self.attack_logger.vprint(
f"{CommandlineColors.OKBLUE}Step 10 (target: accounting): Steal Payment Data{CommandlineColors.ENDC}", 1) f"{CommandlineColors.OKBLUE}Step 10 (target: accounting): Steal Payment Data{CommandlineColors.ENDC}", 1)
self.attack_logger.start_narration( self.attack_logger.start_attack_step("Step 10 (target accounting): Steal Payment Data")
"Step 10 (target accounting): Steal Payment Data\n----------------------------")
self.attack_logger.start_narration(""" self.attack_logger.start_narration("""
NOT IMPLEMENTED YET. NEEDS TARGET REBOOTING: NO IDEA IF ATTACKX CAN SUPPORT THAT NOT IMPLEMENTED YET. NEEDS TARGET REBOOTING: NO IDEA IF ATTACKX CAN SUPPORT THAT

@ -7,114 +7,161 @@ Target systems
Attack steps Attack steps
------------ ------------
{% for e in events %} {% for e in events %}
{% if e.event is eq("start") %} {% if e.event is eq("start") %}
{% if e.type is eq("dropping_file") %} {% if e.type is eq("attack_step") %}
Dropping file to target
~~~~~~~~~~~~~~~~~~~~~~~
At {{ e.timestamp }} {{ e.text }}
The file {{ e.file_name }} is dropped to the target {{ e.target }}. ~~~~~~~~~~~~
{% endif %} {% endif %} {# end attack_step #}
{% if e.type is eq("execute_payload") %} {% if e.type is eq("dropping_file") %}
Executing payload on target
~~~~~~~~~~~~~~~~~~~~~~~~~~~ Dropping file to target
At {{ e.timestamp }} _______________________
The command {{ e.command }} is used to start a file on the target {{ e.target }}. At {{ e.timestamp }}
{% endif %} The file {{ e.file_name }} is dropped to the target {{ e.target }}.
{% if e.type is eq("narration") %} {% endif %}
{{ e.text }} {% if e.type is eq("execute_payload") %}
{% endif %}
{% if e.sub_type is eq("metasploit") %} Executing payload on target
Metasploit attack {{ e.name }} ___________________________
~~~~~~~~~~~~~~~~~~~~~~~~~~ At {{ e.timestamp }}
Tactics: {{ e.tactics }} The command {{ e.command }} is used to start a file on the target {{ e.target }}.
Tactics ID: {{ e.tactics_id }} {% endif %}
Hunting Tag: {{ e.hunting_tag}} {% if e.type is eq("narration") %}
At {{ e.timestamp }} a Metasploit command {{ e.name }} was used to attack {{ e.target }} from {{ e.source }}. {{ e.text }}
{{ e.description }} {% endif %}
{% if e.metasploit_command is string() %} {% if e.sub_type is eq("metasploit") %}
Metasploit command: {{ e.metasploit_command }}
{% endif %} Metasploit attack {{ e.name }}
{% if e.situation_description is string() %} ______________________________
Situation: {{ e.situation_description }} + Tactics: {{ e.tactics }}
{% endif %} + Tactics ID: {{ e.tactics_id }}
{% if e.countermeasure is string() %} + Hunting Tag: {{ e.hunting_tag}}
Countermeasure: {{ e.countermeasure }} + At {{ e.timestamp }} a Metasploit command {{ e.name }} was used to attack {{ e.target }} from {{ e.source }}.
{% endif %} + Description: {{ e.description }}
{% endif %} {% if e.metasploit_command is string() %}
{% if e.sub_type is eq("kali") %} + Metasploit command: {{ e.metasploit_command }}
Kali attack {{ e.name }} {% endif %}
~~~~~~~~~~~~~~~~~~~~~~~~~~ {% if e.situation_description is string() %}
Tactics: {{ e.tactics }} + Situation: {{ e.situation_description }}
Tactics ID: {{ e.tactics_id }} {% endif %}
Hunting Tag: {{ e.hunting_tag}} {% if e.countermeasure is string() %}
At {{ e.timestamp }} a Kali command {{ e.kali_name }} was used to attack {{ e.target }} from {{ e.source }}. + Countermeasure: {{ e.countermeasure }}
{{ e.description }} {% endif %}
{% if e.kali_command is string() %} {% if e.result is string() %}
Kali command: {{ e.kali_command }} Attack result::
{% endif %}
{% if e.situation_description is string() %} {{ e.result }}
Situation: {{ e.situation_description }} {% endif %}
{% endif %} {% if e.result is iterable() %}
{% if e.countermeasure is string() %} Attack result::
Countermeasure: {{ e.countermeasure }}
{% endif %} {% for item in e.result %}
{% endif %} {{ item|trim()|indent(4) }}
{% if e.sub_type is eq("caldera") %} {% endfor %}
Caldera attack {{ e.name }} {% endif %}
~~~~~~~~~~~~~~~~~~~~~~~~~~ {% endif %}
Tactics: {{ e.tactics }} {% if e.sub_type is eq("kali") %}
Tactics ID: {{ e.tactics_id }}
Hunting Tag: {{ e.hunting_tag}} Kali attack {{ e.name }}
At {{ e.timestamp }} a Caldera ability {{ e.ability_id }}/"{{ e.name }}" was used to attack the group {{ e.target_group }} from {{ e.source }}. ________________________
{{ e.description }} + Tactics: {{ e.tactics }}
{% if e.situation_description is string() %} + Tactics ID: {{ e.tactics_id }}
Situation: {{ e.situation_description }} + Hunting Tag: {{ e.hunting_tag}}
{% endif %} + At {{ e.timestamp }} a Kali command {{ e.kali_name }} was used to attack {{ e.target }} from {{ e.source }}.
{% if e.countermeasure is string() %} + Description: {{ e.description }}
Countermeasure: {{ e.countermeasure }} {% if e.kali_command is string() %}
{% endif %} + Kali command: {{ e.kali_command }}
{% endif %} {% endif %}
{% endif %} {# event equal start #} {% if e.situation_description is string() %}
+ Situation: {{ e.situation_description }}
{% endif %}
{% if e.countermeasure is string() %}
+ Countermeasure: {{ e.countermeasure }}
{% endif %}
{% if e.result is string() %}
Attack result::
{{ e.result }}
{% endif %}
{% if e.result is iterable() %}
Attack result::
{% for item in e.result %}
{{ item|trim()|indent(4) }}
{% endfor %}
{% endif %}
{% endif %}
{% if e.sub_type is eq("caldera") %}
Caldera attack {{ e.name }}
___________________________
+ Tactics: {{ e.tactics }}
+ Tactics ID: {{ e.tactics_id }}
+ Hunting Tag: {{ e.hunting_tag}}
+ At {{ e.timestamp }} a Caldera ability {{ e.ability_id }}/"{{ e.name }}" was used to attack the group {{ e.target_group }} from {{ e.source }}.
+ Description: {{ e.description }}
{% if e.situation_description is string() %}
+ Situation: {{ e.situation_description }}
{% endif %}
{% if e.countermeasure is string() %}
+ Countermeasure: {{ e.countermeasure }}
{% endif %}
{% if e.result is string() %}
Attack result::
{{ e.result }}
{% endif %}
{% if e.result is iterable() %}
Attack result::
{% for item in e.result %}
{{ item|trim()|indent(4) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %} {# event equal start #}
{% endfor %} {% endfor %}
Tools Tools
----- -----
{% for e in events %} {% for e in events %}
{% if e.event is eq("start") %} {% if e.event is eq("start") %}
{% if e.type is eq("build") %} {% if e.type is eq("build") %}
Building tool {{ e.filename }} Building tool {{ e.filename }}
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The file {{ e.filename }} is built The file {{ e.filename }} is built
{% if e.for_step %} {% if e.for_step %}
It will be used in Step {{ e.for_step }} It will be used in Step {{ e.for_step }}
{% endif %} {% endif %}
Build time is between {{ e.timestamp }} and {{ e.timestamp_end }} Build time is between {{ e.timestamp }} and {{ e.timestamp_end }}
{% if e.dl_uri is string() %} {% if e.dl_uri is string() %}
Built from source downloaded from {{ e.dl_uri }} Built from source downloaded from {{ e.dl_uri }}
{% endif %} {% endif %}
{% if e.dl_uris %} {% if e.dl_uris %}
Built from sources downloaded from Built from sources downloaded from
{% for i in e.dl_uris %} {% for i in e.dl_uris %}
* {{ i }} * {{ i }}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if e.payload is string() %} {% if e.payload is string() %}
The attack tool uses a Meterpreter payload. The payload is {{ e.payload }}. The payload is built for the {{ e.platform }} platform and the {{ e.architecture }} architecture. The attack tool uses a Meterpreter payload. The payload is {{ e.payload }}. The payload is built for the {{ e.platform }} platform and the {{ e.architecture }} architecture.
The settings for lhost and lport are {{ e.lhost }}/{{ e.lport }}. The settings for lhost and lport are {{ e.lhost }}/{{ e.lport }}.
{% endif %} {% endif %}
{% if e.encoding is string() %} {% if e.encoding is string() %}
The file was encoded using {{ e.encoding }} after compilation. The file was encoded using {{ e.encoding }} after compilation.
{% endif %} {% endif %}
{% if e.encoded_filename is string() %} {% if e.encoded_filename is string() %}
The encoded version is named {{ e.encoded_filename }}. The encoded version is named {{ e.encoded_filename }}.
{% endif %} {% endif %}
{% if e.SRDI_conversion %} {% if e.SRDI_conversion %}
The attack tool was converted to position independent shellcode. See: https://github.com/monoxgas/sRDI The attack tool was converted to position independent shellcode. See: https://github.com/monoxgas/sRDI
{% endif %} {% endif %}
{{ e.comment }} {{ e.comment }}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}

@ -0,0 +1,23 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= python3 -m sphinx
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile all
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
all: html epub latexpdf text man

@ -13,6 +13,7 @@
# import os # import os
# import sys # import sys
master_doc = 'contents'
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
Loading…
Cancel
Save