From 30c7b99e95ab7631f3f0777882bf90221b2f3da8 Mon Sep 17 00:00:00 2001
From: VakarisZ <vakarisz@yahoo.com>
Date: Mon, 15 Jul 2019 15:58:22 +0300
Subject: [PATCH] PR fixes

---
 monkey/common/utils/attack_utils.py           |  7 +++++
 monkey/infection_monkey/exploit/smbexec.py    |  8 +++---
 .../system_info/mimikatz_collector.py         | 11 ++++----
 .../telemetry/attack/t1035_telem.py           |  2 +-
 .../telemetry/attack/t1129_telem.py           |  2 +-
 .../telemetry/attack/usage_telem.py           |  4 +--
 .../attack/technique_reports/T1035.py         |  8 +++---
 .../attack/technique_reports/T1129.py         |  8 +++---
 .../attack/technique_reports/__init__.py      | 26 +++++++++++++++++--
 .../components/attack/techniques/Helpers.js   |  4 +--
 10 files changed, 57 insertions(+), 23 deletions(-)

diff --git a/monkey/common/utils/attack_utils.py b/monkey/common/utils/attack_utils.py
index cb3c8f029..3edb0dc28 100644
--- a/monkey/common/utils/attack_utils.py
+++ b/monkey/common/utils/attack_utils.py
@@ -10,6 +10,13 @@ class ScanStatus(Enum):
     USED = 2
 
 
+class UsageEnum(Enum):
+    SMB = {ScanStatus.USED.value: "SMB exploiter ran the monkey by creating a service via MS-SCMR.",
+           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."}
+
+
 # Dict that describes what BITS job was used for
 BITS_UPLOAD_STRING = "BITS job was used to upload monkey to a remote system."
 
diff --git a/monkey/infection_monkey/exploit/smbexec.py b/monkey/infection_monkey/exploit/smbexec.py
index 6f1667c64..74354108e 100644
--- a/monkey/infection_monkey/exploit/smbexec.py
+++ b/monkey/infection_monkey/exploit/smbexec.py
@@ -11,7 +11,7 @@ from infection_monkey.network.tools import check_tcp_port
 from infection_monkey.exploit.tools import build_monkey_commandline
 from common.utils.exploit_enum import ExploitType
 from infection_monkey.telemetry.attack.t1035_telem import T1035Telem
-from common.utils.attack_utils import ScanStatus
+from common.utils.attack_utils import ScanStatus, UsageEnum
 
 LOG = getLogger(__name__)
 
@@ -133,11 +133,11 @@ class SmbExploiter(HostExploiter):
         service = resp['lpServiceHandle']
         try:
             scmr.hRStartServiceW(scmr_rpc, service)
-            T1035Telem(ScanStatus.USED, "SMB exploiter ran the monkey by creating a service via MS-SCMR.").send()
+            status = ScanStatus.USED
         except:
-            T1035Telem(ScanStatus.SCANNED,
-                       "SMB exploiter failed to run the monkey by creating a service via MS-SCMR.").send()
+            status = ScanStatus.SCANNED
             pass
+        T1035Telem(status, UsageEnum.SMB.name).send()
         scmr.hRDeleteService(scmr_rpc, service)
         scmr.hRCloseServiceHandle(scmr_rpc, service)
 
diff --git a/monkey/infection_monkey/system_info/mimikatz_collector.py b/monkey/infection_monkey/system_info/mimikatz_collector.py
index 4f2348531..47fa0d431 100644
--- a/monkey/infection_monkey/system_info/mimikatz_collector.py
+++ b/monkey/infection_monkey/system_info/mimikatz_collector.py
@@ -5,7 +5,7 @@ import socket
 import zipfile
 
 import infection_monkey.config
-from common.utils.attack_utils import ScanStatus
+from common.utils.attack_utils import ScanStatus, UsageEnum
 from infection_monkey.telemetry.attack.t1129_telem import T1129Telem
 from infection_monkey.pyinstaller_utils import get_binary_file_path, get_binaries_dir_path
 
@@ -50,10 +50,11 @@ class MimikatzCollector(object):
             self._get = get_proto(("get", self._dll))
             self._get_text_output_proto = get_text_output_proto(("getTextOutput", self._dll))
             self._isInit = True
-            T1129Telem(ScanStatus.USED, "Windows module loader was used to load Mimikatz DLL.").send()
+            status = ScanStatus.USED
         except Exception:
             LOG.exception("Error initializing mimikatz collector")
-            T1129Telem(ScanStatus.SCANNED, "Monkey tried to load Mimikatz DLL, but failed.").send()
+            status = ScanStatus.SCANNED
+        T1129Telem(status, UsageEnum.MIMIKATZ.name).send()
 
     def get_logon_info(self):
         """
@@ -70,7 +71,7 @@ class MimikatzCollector(object):
 
             logon_data_dictionary = {}
             hostname = socket.gethostname()
-            
+
             self.mimikatz_text = self._get_text_output_proto()
 
             for i in range(entry_count):
@@ -105,7 +106,7 @@ class MimikatzCollector(object):
         except Exception:
             LOG.exception("Error getting logon info")
             return {}
-    
+
     def get_mimikatz_text(self):
         return self.mimikatz_text
 
diff --git a/monkey/infection_monkey/telemetry/attack/t1035_telem.py b/monkey/infection_monkey/telemetry/attack/t1035_telem.py
index b3d7c90de..13d0bcc59 100644
--- a/monkey/infection_monkey/telemetry/attack/t1035_telem.py
+++ b/monkey/infection_monkey/telemetry/attack/t1035_telem.py
@@ -6,6 +6,6 @@ class T1035Telem(UsageTelem):
         """
         T1035 telemetry.
         :param status: ScanStatus of technique
-        :param usage: Usage string
+        :param usage: Enum name of UsageEnum
         """
         super(T1035Telem, self).__init__('T1035', status, usage)
diff --git a/monkey/infection_monkey/telemetry/attack/t1129_telem.py b/monkey/infection_monkey/telemetry/attack/t1129_telem.py
index fb7d776c6..a04834959 100644
--- a/monkey/infection_monkey/telemetry/attack/t1129_telem.py
+++ b/monkey/infection_monkey/telemetry/attack/t1129_telem.py
@@ -6,6 +6,6 @@ class T1129Telem(UsageTelem):
         """
         T1129 telemetry.
         :param status: ScanStatus of technique
-        :param usage: Usage string
+        :param usage: Enum name of UsageEnum
         """
         super(T1129Telem, self).__init__("T1129", status, usage)
diff --git a/monkey/infection_monkey/telemetry/attack/usage_telem.py b/monkey/infection_monkey/telemetry/attack/usage_telem.py
index 48ff5431c..d493c64d8 100644
--- a/monkey/infection_monkey/telemetry/attack/usage_telem.py
+++ b/monkey/infection_monkey/telemetry/attack/usage_telem.py
@@ -5,9 +5,9 @@ class UsageTelem(AttackTelem):
 
     def __init__(self, technique, status, usage):
         """
-        T1035 telemetry.
+        :param technique: Id of technique
         :param status: ScanStatus of technique
-        :param usage: Usage string
+        :param usage: Enum name of UsageEnum
         """
         super(UsageTelem, self).__init__(technique, status)
         self.usage = 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 a651a8288..4651f3c25 100644
--- a/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py
+++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1035.py
@@ -1,10 +1,10 @@
 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 T1035(AttackTechnique):
+class T1035(UsageTechnique):
     tech_id = "T1035"
     unscanned_msg = "Monkey didn't try to interact with Windows services."
     scanned_msg = "Monkey tried to interact with Windows services, but failed."
@@ -13,5 +13,7 @@ class T1035(AttackTechnique):
     @staticmethod
     def get_report_data():
         data = T1035.get_tech_base_data()
-        data.update({'services': list(mongo.db.telemetry.aggregate(T1035.get_usage_query()))})
+        services = list(mongo.db.telemetry.aggregate(T1035.get_usage_query()))
+        services = list(map(T1035.parse_usages, services))
+        data.update({'services': services})
         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 7d9fa9dd0..17abd4dd3 100644
--- a/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py
+++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1129.py
@@ -1,10 +1,10 @@
 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 T1129(AttackTechnique):
+class T1129(UsageTechnique):
     tech_id = "T1129"
     unscanned_msg = "Monkey didn't try to load any DLL's."
     scanned_msg = "Monkey tried to load DLL's, but failed."
@@ -13,5 +13,7 @@ class T1129(AttackTechnique):
     @staticmethod
     def get_report_data():
         data = T1129.get_tech_base_data()
-        data.update({'dlls': list(mongo.db.telemetry.aggregate(T1129.get_usage_query()))})
+        dlls = list(mongo.db.telemetry.aggregate(T1129.get_usage_query()))
+        dlls = list(map(T1129.parse_usages, dlls))
+        data.update({'dlls': dlls})
         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 de55cd08c..9b0c23d50 100644
--- a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py
+++ b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py
@@ -1,10 +1,13 @@
 import abc
+import logging
 
 from monkey_island.cc.database import mongo
-from common.utils.attack_utils import ScanStatus
+from common.utils.attack_utils import ScanStatus, UsageEnum
 from monkey_island.cc.services.attack.attack_config import AttackConfig
 from common.utils.code_utils import abstractstatic
 
+logger = logging.getLogger(__name__)
+
 
 class AttackTechnique(object):
     """ Abstract class for ATT&CK report components """
@@ -113,6 +116,24 @@ class AttackTechnique(object):
         data.update({'title': cls.technique_title()})
         return data
 
+
+class UsageTechnique(AttackTechnique):
+    __metaclass__ = abc.ABCMeta
+
+    @staticmethod
+    def parse_usages(usage):
+        """
+        Parses data from database and translates usage enums into strings
+        :param usage:
+        :return:
+        """
+        try:
+            usage['usage'] = UsageEnum[usage['usage']].value[usage['status']]
+        except KeyError:
+            logger.error("Error translating usage enum. into string. "
+                         "Check if usage enum field exists and covers all telem. statuses.")
+        return usage
+
     @classmethod
     def get_usage_query(cls):
         """
@@ -131,4 +152,5 @@ class AttackTechnique(object):
                 {'$addFields': {'_id': 0,
                                 'machine': {'hostname': '$monkey.hostname', 'ips': '$monkey.ip_addresses'},
                                 'monkey': 0}},
-                {'$group': {'_id': {'machine': '$machine', 'status': '$status', 'usage': '$usage'}}}]
+                {'$group': {'_id': {'machine': '$machine', 'status': '$status', 'usage': '$usage'}}},
+                {"$replaceRoot": {"newRoot": "$_id"}}]
diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js
index 775d453da..9cb0de635 100644
--- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js
+++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js
@@ -27,12 +27,12 @@ export function getUsageColumns() {
       columns: [
         {Header: 'Machine',
           id: 'machine',
-          accessor: x => renderMachineFromSystemData(x._id.machine),
+          accessor: x => renderMachineFromSystemData(x.machine),
           style: { 'whiteSpace': 'unset' },
           width: 300},
         {Header: 'Usage',
           id: 'usage',
-          accessor: x => x._id.usage,
+          accessor: x => x.usage,
           style: { 'whiteSpace': 'unset' }}]
     }])}