From d880c19910c3ce497f7f4e8c7fe66def2f377a7f Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 16 Jul 2019 10:47:16 +0300 Subject: [PATCH 1/2] PR fixes for t1106 --- monkey/common/utils/attack_utils.py | 3 +++ monkey/infection_monkey/control.py | 1 + monkey/infection_monkey/dropper.py | 5 ++--- monkey/infection_monkey/system_info/mimikatz_collector.py | 3 +-- monkey/infection_monkey/system_singleton.py | 7 ------- monkey/infection_monkey/telemetry/attack/t1106_telem.py | 4 ++-- .../cc/services/attack/technique_reports/T1035.py | 4 +--- .../cc/services/attack/technique_reports/T1106.py | 7 +++---- .../cc/services/attack/technique_reports/T1129.py | 4 +--- .../cc/services/attack/technique_reports/__init__.py | 5 +++++ 10 files changed, 19 insertions(+), 24 deletions(-) diff --git a/monkey/common/utils/attack_utils.py b/monkey/common/utils/attack_utils.py index 3edb0dc28..77d813351 100644 --- a/monkey/common/utils/attack_utils.py +++ b/monkey/common/utils/attack_utils.py @@ -15,6 +15,9 @@ class UsageEnum(Enum): ScanStatus.SCANNED.value: "SMB exploiter failed to run the monkey by creating a service via MS-SCMR."} MIMIKATZ = {ScanStatus.USED.value: "Windows module loader was used to load Mimikatz DLL.", ScanStatus.SCANNED.value: "Monkey tried to load Mimikatz DLL, but failed."} + MIMIKATZ_WINAPI = {ScanStatus.USED.value: "WinAPI was called to load mimikatz.", + ScanStatus.SCANNED.value: "Monkey tried to call WinAPI to load mimikatz."} + DROPPER = {ScanStatus.USED.value: "WinAPI was used to mark monkey files for deletion on next boot."} # Dict that describes what BITS job was used for diff --git a/monkey/infection_monkey/control.py b/monkey/infection_monkey/control.py index f34784041..ba30bf515 100644 --- a/monkey/infection_monkey/control.py +++ b/monkey/infection_monkey/control.py @@ -125,6 +125,7 @@ class ControlClient(object): @staticmethod def send_telemetry(telem_category, data): if not WormConfiguration.current_server: + LOG.error("Trying to send %s telemetry before current server is established, aborting." % telem_category) return try: telemetry = {'monkey_guid': GUID, 'telem_category': telem_category, 'data': data} diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index e39860d50..230ebc567 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -15,7 +15,7 @@ from infection_monkey.exploit.tools import build_monkey_commandline_explicitly from infection_monkey.model import MONKEY_CMDLINE_WINDOWS, MONKEY_CMDLINE_LINUX, GENERAL_CMDLINE_LINUX from infection_monkey.system_info import SystemInfoCollector, OperatingSystem from infection_monkey.telemetry.attack.t1106_telem import T1106Telem -from common.utils.attack_utils import ScanStatus +from common.utils.attack_utils import ScanStatus, UsageEnum if "win32" == sys.platform: from win32process import DETACHED_PROCESS @@ -158,7 +158,6 @@ class MonkeyDrops(object): else: LOG.debug("Dropper source file '%s' is marked for deletion on next boot", self._config['source_path']) - T1106Telem(ScanStatus.USED, "WinAPI was used to mark monkey files" - " for deletion on next boot.").send() + T1106Telem(ScanStatus.USED, UsageEnum.DROPPER.name).send() except AttributeError: LOG.error("Invalid configuration options. Failing") diff --git a/monkey/infection_monkey/system_info/mimikatz_collector.py b/monkey/infection_monkey/system_info/mimikatz_collector.py index 61d3a1c56..0e6a913c9 100644 --- a/monkey/infection_monkey/system_info/mimikatz_collector.py +++ b/monkey/infection_monkey/system_info/mimikatz_collector.py @@ -47,7 +47,6 @@ class MimikatzCollector(object): collect_proto = ctypes.WINFUNCTYPE(ctypes.c_int) get_proto = ctypes.WINFUNCTYPE(MimikatzCollector.LogonData) get_text_output_proto = ctypes.WINFUNCTYPE(ctypes.c_wchar_p) - T1106Telem(ScanStatus.USED, "WinAPI was called to load mimikatz.").send() self._collect = collect_proto(("collect", self._dll)) self._get = get_proto(("get", self._dll)) self._get_text_output_proto = get_text_output_proto(("getTextOutput", self._dll)) @@ -56,7 +55,7 @@ class MimikatzCollector(object): except Exception: LOG.exception("Error initializing mimikatz collector") status = ScanStatus.SCANNED - T1106Telem(ScanStatus.SCANNED, "Monkey tried to call WinAPI to load mimikatz.").send() + T1106Telem(status, UsageEnum.MIMIKATZ_WINAPI.name).send() T1129Telem(status, UsageEnum.MIMIKATZ.name).send() diff --git a/monkey/infection_monkey/system_singleton.py b/monkey/infection_monkey/system_singleton.py index 06a2ea689..d8c3ec51c 100644 --- a/monkey/infection_monkey/system_singleton.py +++ b/monkey/infection_monkey/system_singleton.py @@ -4,8 +4,6 @@ import sys from abc import ABCMeta, abstractmethod from infection_monkey.config import WormConfiguration -from infection_monkey.telemetry.attack.t1106_telem import T1106Telem -from common.utils.attack_utils import ScanStatus __author__ = 'itamar' @@ -48,19 +46,14 @@ class WindowsSystemSingleton(_SystemSingleton): if not handle: LOG.error("Cannot acquire system singleton %r, unknown error %d", self._mutex_name, last_error) - T1106Telem(ScanStatus.SCANNED, "WinAPI call to acquire system singleton " - "for monkey process wasn't successful.").send() - return False if winerror.ERROR_ALREADY_EXISTS == last_error: LOG.debug("Cannot acquire system singleton %r, mutex already exist", self._mutex_name) - return False self._mutex_handle = handle - T1106Telem(ScanStatus.USED, "WinAPI was called to acquire system singleton for monkey's process.").send() LOG.debug("Global singleton mutex %r acquired", self._mutex_name) diff --git a/monkey/infection_monkey/telemetry/attack/t1106_telem.py b/monkey/infection_monkey/telemetry/attack/t1106_telem.py index 30cad6072..422313540 100644 --- a/monkey/infection_monkey/telemetry/attack/t1106_telem.py +++ b/monkey/infection_monkey/telemetry/attack/t1106_telem.py @@ -4,8 +4,8 @@ from infection_monkey.telemetry.attack.usage_telem import UsageTelem class T1106Telem(UsageTelem): def __init__(self, status, usage): """ - T1129 telemetry. + T1106 telemetry. :param status: ScanStatus of technique - :param usage: Usage string + :param usage: Enum name of UsageEnum """ super(T1106Telem, self).__init__("T1106", status, usage) diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py index 4651f3c25..fcc230be5 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py @@ -13,7 +13,5 @@ class T1035(UsageTechnique): @staticmethod def get_report_data(): data = T1035.get_tech_base_data() - services = list(mongo.db.telemetry.aggregate(T1035.get_usage_query())) - services = list(map(T1035.parse_usages, services)) - data.update({'services': services}) + data.update({'services': T1035.get_usage_data()}) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py index b24d10bd9..b50b19883 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1106.py @@ -1,10 +1,9 @@ -from monkey_island.cc.database import mongo -from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.services.attack.technique_reports import UsageTechnique __author__ = "VakarisZ" -class T1106(AttackTechnique): +class T1106(UsageTechnique): tech_id = "T1106" unscanned_msg = "Monkey didn't try to directly use WinAPI." scanned_msg = "Monkey tried to use WinAPI, but failed." @@ -13,5 +12,5 @@ class T1106(AttackTechnique): @staticmethod def get_report_data(): data = T1106.get_tech_base_data() - data.update({'api_uses': list(mongo.db.telemetry.aggregate(T1106.get_usage_query()))}) + data.update({'api_uses': T1106.get_usage_data()}) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py index 17abd4dd3..f1a4d1b83 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py @@ -13,7 +13,5 @@ class T1129(UsageTechnique): @staticmethod def get_report_data(): data = T1129.get_tech_base_data() - dlls = list(mongo.db.telemetry.aggregate(T1129.get_usage_query())) - dlls = list(map(T1129.parse_usages, dlls)) - data.update({'dlls': dlls}) + data.update({'dlls': T1129.get_usage_data()}) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py index 9b0c23d50..cc702de62 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py @@ -134,6 +134,11 @@ class UsageTechnique(AttackTechnique): "Check if usage enum field exists and covers all telem. statuses.") return usage + @classmethod + def get_usage_data(cls): + data = list(mongo.db.telemetry.aggregate(cls.get_usage_query())) + return list(map(cls.parse_usages, data)) + @classmethod def get_usage_query(cls): """ From 7eab8687c1d5d926d757696f5cd127991d2d867b Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Mon, 19 Aug 2019 09:16:14 +0300 Subject: [PATCH 2/2] Fixed bug created during merge, fixed typos in attack telemetries for usage. --- monkey/common/utils/attack_utils.py | 10 ++++------ monkey/infection_monkey/dropper.py | 2 +- .../infection_monkey/system_info/mimikatz_collector.py | 2 +- monkey/infection_monkey/system_singleton.py | 2 +- .../infection_monkey/telemetry/attack/usage_telem.py | 4 ++-- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/monkey/common/utils/attack_utils.py b/monkey/common/utils/attack_utils.py index ac3f2f66b..708bc8f3c 100644 --- a/monkey/common/utils/attack_utils.py +++ b/monkey/common/utils/attack_utils.py @@ -18,12 +18,10 @@ class UsageEnum(Enum): MIMIKATZ_WINAPI = {ScanStatus.USED.value: "WinAPI was called to load mimikatz.", ScanStatus.SCANNED.value: "Monkey tried to call WinAPI to load mimikatz."} DROPPER = {ScanStatus.USED.value: "WinAPI was used to mark monkey files for deletion on next boot."} - MIMIKATZ_FILE_COPY = {ScanStatus.USED.value: "WinAPI was called to load mimikatz.", - ScanStatus.SCANNED.value: "Monkey tried to call WinAPI to load mimikatz, but failed."} - SINGLETON_FILE_COPY = {ScanStatus.USED.value: "WinAPI was called to acquire system singleton for monkey's process.", - ScanStatus.SCANNED.value: "WinAPI call to acquire system singleton" - " for monkey process wasn't successful."} - DROPPER_FILE_COPY = {ScanStatus.USED.value: "WinAPI was used to mark monkey files for deletion on next boot."} + SINGLETON_WINAPI = {ScanStatus.USED.value: "WinAPI was called to acquire system singleton for monkey's process.", + ScanStatus.SCANNED.value: "WinAPI call to acquire system singleton" + " for monkey process wasn't successful."} + DROPPER_WINAPI = {ScanStatus.USED.value: "WinAPI was used to mark monkey files for deletion on next boot."} # Dict that describes what BITS job was used for diff --git a/monkey/infection_monkey/dropper.py b/monkey/infection_monkey/dropper.py index 6b8e969c0..7c576fc30 100644 --- a/monkey/infection_monkey/dropper.py +++ b/monkey/infection_monkey/dropper.py @@ -158,6 +158,6 @@ class MonkeyDrops(object): else: LOG.debug("Dropper source file '%s' is marked for deletion on next boot", self._config['source_path']) - T1106Telem(ScanStatus.USED, UsageEnum.DROPPER_FILE_COPY).send() + T1106Telem(ScanStatus.USED, UsageEnum.DROPPER_WINAPI).send() except AttributeError: LOG.error("Invalid configuration options. Failing") diff --git a/monkey/infection_monkey/system_info/mimikatz_collector.py b/monkey/infection_monkey/system_info/mimikatz_collector.py index c0632a09e..2951b7ebc 100644 --- a/monkey/infection_monkey/system_info/mimikatz_collector.py +++ b/monkey/infection_monkey/system_info/mimikatz_collector.py @@ -55,8 +55,8 @@ class MimikatzCollector(object): except Exception: LOG.exception("Error initializing mimikatz collector") status = ScanStatus.SCANNED + T1106Telem(status, UsageEnum.MIMIKATZ_WINAPI).send() T1129Telem(status, UsageEnum.MIMIKATZ).send() - T1106Telem(status, UsageEnum.MIMIKATZ_FILE_COPY).send() def get_logon_info(self): """ diff --git a/monkey/infection_monkey/system_singleton.py b/monkey/infection_monkey/system_singleton.py index a1c8762cd..50fa6363b 100644 --- a/monkey/infection_monkey/system_singleton.py +++ b/monkey/infection_monkey/system_singleton.py @@ -59,7 +59,7 @@ class WindowsSystemSingleton(_SystemSingleton): if not status: status = ScanStatus.USED - T1106Telem(status, UsageEnum.SINGLETON_FILE_COPY).send() + T1106Telem(status, UsageEnum.SINGLETON_WINAPI).send() if status == ScanStatus.SCANNED: return False diff --git a/monkey/infection_monkey/telemetry/attack/usage_telem.py b/monkey/infection_monkey/telemetry/attack/usage_telem.py index 4b47d8be3..2d7cb548e 100644 --- a/monkey/infection_monkey/telemetry/attack/usage_telem.py +++ b/monkey/infection_monkey/telemetry/attack/usage_telem.py @@ -7,10 +7,10 @@ class UsageTelem(AttackTelem): """ :param technique: Id of technique :param status: ScanStatus of technique - :param usage: Enum of UsageEnum type + :param usage: Usage string """ super(UsageTelem, self).__init__(technique, status) - self.usage = usage.name + self.usage = usage def get_data(self): data = super(UsageTelem, self).get_data()