#!/usr/bin/env python3 """ Logger for the attack side. Output must be flexible, because we want to be able to feed it into many different processes. From ML to analysts """ import json import datetime def __get_timestamp__(): return datetime.datetime.now().strftime("%H:%M:%S.%f") def __mitre_fix_ttp__(ttp): """ enforce some systematic naming scheme for MITRE TTPs """ if ttp is None: return "" if ttp.startswith("MITRE_"): return ttp else: return "MITRE_" + ttp class AttackLog(): """ A specific logger class to log the progress of the attack steps """ def __init__(self, verbosity=0): """ @param verbosity: verbosity setting from 0 to 3 for stdout printing """ self.log = [] self.verbosity = verbosity def start_caldera_attack(self, source, paw, group, ability_id, ttp=None, name=None, description=None, obfuscator="default", jitter="default"): # pylint: disable=too-many-arguments """ Mark the start of a caldera attack @param source: source of the attack. Attack IP @param paw: Caldera paw of the targets being attacked @param group: Caldera group of the targets being attacked @param ability_id: Caldera ability id of the attack @param ttp: TTP of the attack (as stated by Caldera internal settings) @param name: Name of the attack. Data source is Caldera internal settings @param description: Descirption of the attack. Caldera is the source @param obfuscator: C&C obfuscator being used @param jitter: Jitter being used """ data = {"timestamp": __get_timestamp__(), "event": "start", "type": "attack", "sub-type": "caldera", "source": source, "target_paw": paw, "target_group": group, "ability_id": ability_id, "hunting_tag": __mitre_fix_ttp__(ttp), "name": name or "", "description": description or "", "obfuscator": obfuscator, "jitter": jitter } self.log.append(data) # TODO: Add parameter # TODO: Add config # TODO: Add results def stop_caldera_attack(self, source, paw, group, ability_id, ttp=None, name=None, description=None, obfuscator="default", jitter="default"): # pylint: disable=too-many-arguments """ Mark the end of a caldera attack @param source: source of the attack. Attack IP @param paw: Caldera oaw of the targets being attacked @param group: Caldera group of the targets being attacked @param ability_id: Caldera ability id of the attack @param ttp: TTP of the attack (as stated by Caldera internal settings) @param name: Name of the attack. Data source is Caldera internal settings @param description: Descirption of the attack. Caldera is the source @param obfuscator: C&C obfuscator being used @param jitter: Jitter being used """ data = {"timestamp": __get_timestamp__(), "event": "stop", "type": "attack", "sub-type": "caldera", "source": source, "target_paw": paw, "target_group": group, "ability_id": ability_id, "hunting_tag": __mitre_fix_ttp__(ttp), "name": name or "", "description": description or "", "obfuscator": obfuscator, "jitter": jitter } self.log.append(data) def start_kali_attack(self, source, target, attack_name, ttp=None): """ Mark the start of a Kali based attack @param source: source of the attack. Attack IP @param target: Target machine of the attack @param attack_name: Name of the attack. From plugin @param ttp: TTP of the attack. From plugin """ data = {"timestamp": __get_timestamp__(), "event": "start", "type": "attack", "sub-type": "kali", "source": source, "target": target, "kali_name": attack_name, "hunting_tag": __mitre_fix_ttp__(ttp), } self.log.append(data) # TODO: Add parameter # TODO: Add config # TODO: Add results def stop_kali_attack(self, source, target, attack_name, ttp=None): """ Mark the end of a Kali based attack @param source: source of the attack. Attack IP @param target: Target machine of the attack @param attack_name: Name of the attack. From plugin @param ttp: TTP of the attack. From plugin """ data = {"timestamp": __get_timestamp__(), "event": "stop", "type": "attack", "sub-type": "kali", "source": source, "target": target, "kali_name": attack_name, "hunting_tag": __mitre_fix_ttp__(ttp), } self.log.append(data) def write_json(self, filename): """ Write the json data for this log @param filename: Name of the json file """ with open(filename, "wt") as fh: json.dump(self.get_dict(), fh) def get_dict(self): """ Return logged data in dict format """ return self.log def vprint(self, text, verbosity): """ verbosity based stdout printing 0: Errors only 1: Main colored information 2: Detailed progress information 3: Debug logs, data dumps, everything @param text: The text to print @param verbosity: the verbosity level the text has. """ if verbosity <= self.verbosity: print(text)