diff --git a/infection_monkey/requirements.txt b/infection_monkey/requirements.txt
index 60656280b..9e9adc97f 100644
--- a/infection_monkey/requirements.txt
+++ b/infection_monkey/requirements.txt
@@ -13,7 +13,6 @@ PyInstaller
six
ecdsa
netifaces
-mock
nos
ipaddress
wmi
diff --git a/infection_monkey/system_info/mimikatz_collector.py b/infection_monkey/system_info/mimikatz_collector.py
index 89222c2e2..4d994c6ab 100644
--- a/infection_monkey/system_info/mimikatz_collector.py
+++ b/infection_monkey/system_info/mimikatz_collector.py
@@ -21,10 +21,10 @@ class MimikatzCollector(object):
self._dll = ctypes.WinDLL(self._config.mimikatz_dll_name)
collect_proto = ctypes.WINFUNCTYPE(ctypes.c_int)
get_proto = ctypes.WINFUNCTYPE(MimikatzCollector.LogonData)
- getTextOutput = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
+ get_text_output_proto = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
self._collect = collect_proto(("collect", self._dll))
self._get = get_proto(("get", self._dll))
- self._getTextOutput = getTextOutput(("getTextOutput", self._dll))
+ self._get_text_output_proto = get_text_output_proto(("getTextOutput", self._dll))
self._isInit = True
except Exception:
LOG.exception("Error initializing mimikatz collector")
@@ -44,7 +44,7 @@ class MimikatzCollector(object):
logon_data_dictionary = {}
hostname = socket.gethostname()
- self.mimikatz_text = self._getTextOutput()
+ self.mimikatz_text = self._get_text_output_proto()
for i in range(entry_count):
entry = self._get()
diff --git a/infection_monkey/system_info/windows_info_collector.py b/infection_monkey/system_info/windows_info_collector.py
index 30685569b..d63553b8f 100644
--- a/infection_monkey/system_info/windows_info_collector.py
+++ b/infection_monkey/system_info/windows_info_collector.py
@@ -113,12 +113,11 @@ def fix_wmi_obj_for_mongo(o):
row[method_name[3:]] = value
except wmi.x_wmi:
- #LOG.error("Error running wmi method '%s'" % (method_name, ))
- #LOG.error(traceback.format_exc())
continue
return row
+
class WindowsInfoCollector(InfoCollector):
"""
System information collecting module for Windows operating systems
@@ -126,6 +125,7 @@ class WindowsInfoCollector(InfoCollector):
def __init__(self):
super(WindowsInfoCollector, self).__init__()
+ self.info['reg'] = {}
def get_info(self):
"""
@@ -162,9 +162,6 @@ class WindowsInfoCollector(InfoCollector):
for wmi_class_name in WMI_CLASSES:
self.info[wmi_class_name] = self.get_wmi_class(wmi_class_name)
- # for wmi_class_name, props in WMI_LDAP_CLASSES.iteritems():
- # self.info[wmi_class_name] = self.get_wmi_class(wmi_class_name, "//./root/directory/ldap", props)
-
def get_wmi_class(self, class_name, moniker="//./root/cimv2", properties=None):
_wmi = wmi.WMI(moniker=moniker)
@@ -175,8 +172,6 @@ class WindowsInfoCollector(InfoCollector):
wmi_class = getattr(_wmi, class_name)(properties)
except wmi.x_wmi:
- #LOG.error("Error getting wmi class '%s'" % (class_name, ))
- #LOG.error(traceback.format_exc())
return
return fix_obj_for_mongo(wmi_class)
@@ -188,7 +183,7 @@ class WindowsInfoCollector(InfoCollector):
d = dict([_winreg.EnumValue(subkey, i)[:2] for i in xrange(_winreg.QueryInfoKey(subkey)[0])])
d = fix_obj_for_mongo(d)
- self.info[subkey_path] = d
+ self.info['reg'][subkey_path] = d
subkey.Close()
- key.Close()
\ No newline at end of file
+ key.Close()
diff --git a/monkey_island/cc/app.py b/monkey_island/cc/app.py
index 0f0754ed3..6b9ac1154 100644
--- a/monkey_island/cc/app.py
+++ b/monkey_island/cc/app.py
@@ -19,8 +19,6 @@ from cc.resources.monkey import Monkey
from cc.resources.monkey_configuration import MonkeyConfiguration
from cc.resources.monkey_download import MonkeyDownload
from cc.resources.netmap import NetMap
-from cc.resources.pthmap import PthMap
-from cc.resources.pthreport import PTHReport
from cc.resources.node import Node
from cc.resources.report import Report
from cc.resources.root import Root
@@ -108,7 +106,5 @@ def init_app(mongo_url):
api.add_resource(TelemetryFeed, '/api/telemetry-feed', '/api/telemetry-feed/')
api.add_resource(Log, '/api/log', '/api/log/')
api.add_resource(IslandLog, '/api/log/island/download', '/api/log/island/download/')
- api.add_resource(PthMap, '/api/pthmap', '/api/pthmap/')
- api.add_resource(PTHReport, '/api/pthreport', '/api/pthreport/')
return app
diff --git a/monkey_island/cc/resources/pthmap.py b/monkey_island/cc/resources/pthmap.py
deleted file mode 100644
index d19afd56f..000000000
--- a/monkey_island/cc/resources/pthmap.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import copy
-import flask_restful
-
-
-from cc.auth import jwt_required
-from cc.services.pth_report_utils import PassTheHashReport, Machine
-
-
-class PthMap(flask_restful.Resource):
- @jwt_required()
- def get(self, **kw):
- pth = PassTheHashReport()
-
- v = copy.deepcopy(pth.vertices)
- e = copy.deepcopy(pth.edges)
-
- return \
- {
- "nodes": [{"id": x, "label": Machine(x).GetIp()} for x in v],
- "edges": [{"id": str(s) + str(t), "from": s, "to": t, "label": label} for s, t, label in e]
- }
diff --git a/monkey_island/cc/resources/pthreport.py b/monkey_island/cc/resources/pthreport.py
deleted file mode 100644
index 7c4046694..000000000
--- a/monkey_island/cc/resources/pthreport.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import flask_restful
-
-from cc.auth import jwt_required
-from cc.services.pth_report import PTHReportService
-
-__author__ = "maor.rayzin"
-
-
-class PTHReport(flask_restful.Resource):
-
- @jwt_required()
- def get(self):
- return PTHReportService.get_report()
diff --git a/monkey_island/cc/services/pth_report.py b/monkey_island/cc/services/pth_report.py
index 03167f81a..512a80a14 100644
--- a/monkey_island/cc/services/pth_report.py
+++ b/monkey_island/cc/services/pth_report.py
@@ -257,178 +257,4 @@ class PTHReportService(object):
'edges': pth.edges
}
}
- return report
-
- # print """
"""
- #
- # print "
Cached Passwords
"
- # print "
On how many machines each secret is cached (possible attacker count)?
"
- # cache_counts = dict(map(lambda x: (x, pth.GetAttackCountBySecret(x)), pth.GetAllSecrets()))
- #
- # print """
"""
- # print """Secret | Machine Count |
"""
- # for secret, count in sorted(cache_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True):
- # if count <= 0:
- # continue
- # print """{secret} | {count} | """.format(secret=secret, count=count)
- # print """
"""
- #
- # print "
User's Creds
"
- # print "
To how many machines each user is able to connect with admin rights
"
- # attackable_counts = dict(map(lambda x: (x, pth.GetVictimCountBySid(x)), pth.GetAllSids()))
- #
- # print """
"""
- # print """SID | Username | Machine Count |
"""
- # for sid, count in sorted(attackable_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True):
- # if count <= 1:
- # continue
- # print """{sid} | {username} | {count} | """.format(sid=sid, username=pth.GetUsernameBySid(sid), count=count)
- # print """
"""
- #
- # print "
Actual Possible Attacks By SID
"
- # print "
How many attacks possible using each SID (aka len(attacker->victim pairs))
"
- # possible_attacks_by_sid = dict(map(lambda x: (x, pth.GetPossibleAttackCountBySid(x)), pth.GetAllSids()))
- #
- # print """
"""
- # print """SID | Username | Machine Count |
"""
- # for sid, count in sorted(possible_attacks_by_sid.iteritems(), key=lambda (k,v): (v,k), reverse=True):
- # if count <= 1:
- # continue
- # print """{sid} | {username} | {count} | """.format(sid=sid, username=pth.GetUsernameBySid(sid), count=count)
- # print """
"""
- #
- # print "
Machine's Creds
"
- # print "
To how many machines each machine is able to directly connect with admin rights?
"
- # attackable_counts = dict(map(lambda m: (m, pth.GetVictimCountByMachine(m)), pth.machines))
- #
- # print """
"""
- # print """Attacker Ip | Attacker Hostname | Domain Name | Victim Machine Count |
"""
- # for m, count in sorted(attackable_counts.iteritems(), key=lambda (k,v): (v,k), reverse=True):
- # if count <= 1:
- # continue
- # print """{ip} | {hostname} | {domain} | {count} | """.format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName(), count=count)
- # print """
"""
- #
- # print "
Domain Controllers
"
- # print "
List of domain controllers (we count them as critical points, so they are listed here)
"
- # DCs = dict(map(lambda m: (m, pth.GetInPathCountByVictim(m)), pth.GetAllDomainControllers()))
- #
- # print """
"""
- # print """DC Ip | DC Hostname | Domain Name | In-Path Count |
"""
- # for m, path_count in sorted(DCs.iteritems(), key=lambda (k,v): (v,k), reverse=True):
- # print """{ip} | {hostname} | {domain} | {path_count} |
""".format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName(), path_count=path_count)
- # print """
"""
- #
- # print "
Most Vulnerable Machines
"
- # print "
List all machines in the network sorted by the potincial to attack them
"
- # all_machines = dict(map(lambda m: (m, pth.GetInPathCountByVictim(m)), pth.machines))
- #
- # print """
"""
- # print """Ip | Hostname | Domain Name | In-Path Count |
"""
- # for m, path_count in sorted(all_machines.iteritems(), key=lambda (k,v): (v,k), reverse=True):
- # if count <= 0:
- # continue
- # print """{ip} | {hostname} | {domain} | {path_count} |
""".format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName(), path_count=path_count)
- # print """
"""
- #
- # print "
Critical Servers
"
- # print "
List of all machines identified as critical servers
"
- # critical_servers = pth.GetCritialServers()
- #
- # print """
"""
- # print """Ip | Hostname | Domain Name |
"""
- # for m in critical_servers:
- # print """{ip} | {hostname} | {domain} |
""".format(ip=m.GetIp(), hostname=m.GetHostName(), domain=m.GetDomainName())
- # print """
"""
- #
- # print "
"
- #
- # for m in pth.machines:
- # print """
Machine '{ip}'
- #
Hostname '{hostname}'
""".format(ip=m.GetIp(), hostname=m.GetHostName())
- #
- # print """
Cached SIDs
"""
- # print """
SIDs cached on this machine
"""
- # print """
"""
- # for sid in pth.GetCachedSids(m):
- # print """- {username} ({sid})
""".format(username=pth.GetUsernameBySid(sid), sid=sid)
- # print """
"""
- #
- # print """
Possible Attackers
"""
- # print """
Machines that can attack this machine
"""
- # print """
"""
- # for attacker in pth.GetAttackersByVictim(m):
- # print """- {ip} ({hostname})
""".format(ip=attacker.GetIp(), hostname=attacker.GetHostName())
- # print """
"""
- #
- #
- # print """
Admins
"""
- # print """
Users that have admin rights on this machine
"""
- # print """
"""
- # for sid in m.GetAdmins():
- # print """- {username} ({sid})
""".format(username=m.GetUsernameBySid(sid), sid=sid)
- # print """
"""
- #
- # print """
Installed Critical Services
"""
- # print """
List of crtical services found installed on machine
"""
- # print """
"""
- # for service_name in m.GetCriticalServicesInstalled():
- # print """- {service_name}
""".format(service_name=service_name)
- # print """
"""
- #
- #
- # print "
"
- #
- # for username in pth.GetAllUsernames():
- # print """
User '{username}'
""".format(username=username)
- #
- # print """
Matching SIDs
"""
- # print """
"""
- # for sid in pth.GetSidsByUsername(username):
- # print """- {username} ({sid})
""".format(username=pth.GetUsernameBySid(sid),
- # sid=sid)
- # print """
"""
- #
- # print "
"
- #
- # for sid in pth.GetAllSids():
- # print """
SID '{sid}'
- #
- #
Domain: {domain}
- #
- # """.format(username=pth.GetUsernameBySid(sid), sid=sid, secret=pth.GetSecretBySid(sid),
- # domain=pth.GetSidInfo(sid)["Domain"])
- #
- # print """
Machines the sid is local admin on
"""
- # print """
"""
- # for m in pth.GetVictimsBySid(sid):
- # print """- {ip} ({hostname})
""".format(ip=m.GetIp(), hostname=m.GetHostName())
- # print """
"""
- #
- # print """
Machines the sid is in thier cache
"""
- # print """
"""
- # for m in pth.GetAttackersBySid(sid):
- # print """- {ip} ({hostname})
""".format(ip=m.GetIp(), hostname=m.GetHostName())
- # print """
"""
- #
- # for secret in pth.GetAllSecrets():
- # print """
Secret '{secret}'
""".format(secret=secret)
- #
- # print """
SIDs that use that secret
"""
- # print """
"""
- # for sid in pth.GetSidsBySecret(secret):
- # print """- {username} ({sid})
""".format(username=pth.GetUsernameBySid(sid),
- # sid=sid)
- # print """
"""
- #
- # print """
Attackable Machines with that secret
"""
- # print """
"""
- # for m in pth.GetVictimsBySecret(secret):
- # print """- {hostname}
""".format(ip=m.GetIp(), hostname=m.GetHostName())
- # print """
"""
- #
- # print """
Machines that have this secret cached and can use it to attack other machines
"""
- # print """
"""
- # for m in pth.GetAttackersBySecret(secret):
- # print """- {hostname}
""".format(ip=m.GetIp(), hostname=m.GetHostName())
- # print """
"""
+ return report
\ No newline at end of file
diff --git a/monkey_island/cc/services/pth_report_utils.py b/monkey_island/cc/services/pth_report_utils.py
index 9e9baa6b3..5797a6909 100644
--- a/monkey_island/cc/services/pth_report_utils.py
+++ b/monkey_island/cc/services/pth_report_utils.py
@@ -329,7 +329,6 @@ class Machine(object):
if "cimv2:Win32_UserAccount" not in wmi_id:
continue
- # u'\\\\WIN-BFA01FFQFLS\\root\\cimv2:Win32_UserAccount.Domain="MYDOMAIN",Name="WIN-BFA01FFQFLS$"'
username = wmi_id.split('cimv2:Win32_UserAccount.Domain="')[1].split('",Name="')[0]
domain = wmi_id.split('cimv2:Win32_UserAccount.Domain="')[1].split('",Name="')[1][:-1]
@@ -556,12 +555,6 @@ class Machine(object):
class PassTheHashReport(object):
- # _instance = None
- # def __new__(class_, *args, **kwargs):
- # if not class_._instance:
- # class_._instance = object.__new__(class_, *args, **kwargs)
- #
- # return class_._instance
def __init__(self):
self.vertices = self.GetAllMachines()
@@ -582,15 +575,12 @@ class PassTheHashReport(object):
return GUIDs
@cache
- def ReprSidList(self, sid_list, attacker, victim):
+ def ReprSidList(self, sid_list, victim):
users_list = []
for sid in sid_list:
username = Machine(victim).GetUsernameBySid(sid)
- # if not username:
- # username = Machine(attacker).GetUsernameBySid(sid)
-
if username:
users_list.append(username)
@@ -631,7 +621,7 @@ class PassTheHashReport(object):
cached_admins = [i for i in cached if i in admins]
if cached_admins:
- relevant_users_list = self.ReprSidList(cached_admins, attacker, victim)
+ relevant_users_list = self.ReprSidList(cached_admins, victim)
edges_list.append(
{
'from': attacker,
@@ -680,11 +670,6 @@ class PassTheHashReport(object):
return edges
- @cache
- def Print(self):
- print map(lambda x: Machine(x).GetIp(), self.vertices)
- print map(lambda x: (Machine(x[0]).GetIp(), Machine(x[1]).GetIp()), self.edges)
-
@cache
def GetPossibleAttackCountBySid(self, sid):
return len(self.GetPossibleAttacksBySid(sid))
@@ -970,5 +955,6 @@ class PassTheHashReport(object):
#shared_admins |= (m.GetLocalAdminSids() & other.GetLocalAdminSids())
- #shared_admins -= m.GetDomainAdminsOfMachine()
- return shared_admins
\ No newline at end of file
+ shared_admins = [admin for admin in shared_admins if admin not in list(m.GetDomainAdminsOfMachine())]
+
+ return shared_admins
diff --git a/monkey_island/mymap.py b/monkey_island/mymap.py
deleted file mode 100644
index a9854468d..000000000
--- a/monkey_island/mymap.py
+++ /dev/null
@@ -1,330 +0,0 @@
-import hashlib
-import binascii
-from pymongo import MongoClient
-db = MongoClient().monkeyisland
-
-DsRole_RoleStandaloneWorkstation = 0
-DsRole_RoleMemberWorkstation = 1
-DsRole_RoleStandaloneServer = 2
-DsRole_RoleMemberServer = 3
-DsRole_RoleBackupDomainController = 4
-DsRole_RolePrimaryDomainController = 5
-
-def myntlm(x):
- hash = hashlib.new('md4', x.encode('utf-16le')).digest()
- return str(binascii.hexlify(hash))
-
-class Machine(object):
- def __init__(self, monkey_guid):
- self.monkey_guid = str(monkey_guid)
-
- def GetMimikatzOutput(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- output = set()
-
- for doc in cur:
- output.add(doc["data"]["mimikatz"])
-
- if len(output) == 1:
- return output.pop()
-
- return None
-
- def GetHostName(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- names = set()
-
- for doc in cur:
- for comp in doc["data"]["Win32_ComputerSystem"]:
- names.add(eval(comp["Name"]))
-
- if len(names) == 1:
- return names.pop()
-
- return None
-
- def GetIp(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- names = set()
-
- for doc in cur:
- for addr in doc["data"]["network_info"]["networks"]:
- return str(addr["addr"])
-
- return None
-
- def GetDomainName(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- names = set()
-
- for doc in cur:
- for comp in doc["data"]["Win32_ComputerSystem"]:
- names.add(eval(comp["Domain"]))
-
- if len(names) == 1:
- return names.pop()
-
- return None
-
- def GetDomainRole(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- roles = set()
-
- for doc in cur:
- for comp in doc["data"]["Win32_ComputerSystem"]:
- roles.add(comp["DomainRole"])
-
- if len(roles) == 1:
- return roles.pop()
-
- return None
-
- def GetSidByUsername(self, username):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid, "data.Win32_UserAccount.Name":"u'%s'" % (username,)})
-
- SIDs = set()
-
- for doc in cur:
- for user in doc["data"]["Win32_UserAccount"]:
- if eval(user["Name"]) != username:
- continue
-
- SIDs.add(eval(user["SID"]))
-
- if len(SIDs) == 1:
- return SIDs.pop()
-
- return None
-
- def GetUsernameBySid(self, sid):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid, "data.Win32_UserAccount.SID":"u'%s'" % (sid,)})
-
- names = set()
-
- for doc in cur:
- for user in doc["data"]["Win32_UserAccount"]:
- if eval(user["SID"]) != sid:
- continue
-
- names.add(eval(user["Name"]))
-
- if len(names) == 1:
- return names.pop()
-
- return None
-
- def GetGroupSidByGroupName(self, group_name):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid, "data.Win32_Group.Name":"u'%s'" % (group_name,)})
- SIDs = set()
-
- for doc in cur:
- for group in doc["data"]["Win32_Group"]:
- if eval(group["Name"]) != group_name:
- continue
-
- SIDs.add(eval(group["SID"]))
-
- if len(SIDs) == 1:
- return SIDs.pop()
-
- return None
-
- def GetUsersByGroupSid(self, sid):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid, "data.Win32_GroupUser.GroupComponent.SID":"u'%s'" % (sid,)})
-
- users = dict()
-
- for doc in cur:
- for group_user in doc["data"]["Win32_GroupUser"]:
- if eval(group_user["GroupComponent"]["SID"]) != sid:
- continue
-
- if "PartComponent" not in group_user.keys():
- continue
-
- users[eval(group_user["PartComponent"]["SID"])] = eval(group_user["PartComponent"]["Name"])
-
- return users
-
- def GetDomainControllersMonkeyGuidByDomainName(self, domain_name):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "data.Win32_ComputerSystem.Domain":"u'%s'" % (domain_name,)})
-
- GUIDs = set()
-
- for doc in cur:
- for comp in doc["data"]["Win32_ComputerSystem"]:
- if ((comp["DomainRole"] != DsRole_RolePrimaryDomainController) and
- (comp["DomainRole"] != DsRole_RoleBackupDomainController)):
- continue
-
- GUIDs.add(doc["monkey_guid"])
-
- return GUIDs
-
- def GetLocalAdmins(self):
- return set(self.GetUsersByGroupSid(self.GetGroupSidByGroupName("Administrators")).keys())
-
- def GetLocalAdminNames(self):
- return set(self.GetUsersByGroupSid(self.GetGroupSidByGroupName("Administrators")).values())
-
- def GetLocalAdminSecrets(self):
- admin_names = self.GetLocalAdminNames()
- sam_users = str(self.GetMimikatzOutput()).split("\nSAMKey :")[1].split("\n\n")[1:]
-
- admin_secrets = set()
-
- for sam_user_txt in sam_users:
- sam_user = dict([map(str.strip, line.split(":")) for line in filter(lambda l: l.count(":") == 1, sam_user_txt.splitlines())])
-
- if sam_user["User"] not in admin_names:
- continue
-
- admin_secrets.add(sam_user["NTLM"].replace("[hashed secret]", "").strip())
-
- return admin_secrets
-
- def GetCachedSecrets(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- secrets = set()
-
- for doc in cur:
- for username in doc["data"]["credentials"]:
- user = doc["data"]["credentials"][username]
-
- if "password" in user.keys():
- ntlm = myntlm(str(user["password"]))
- elif "ntlm_hash" in user.keys():
- ntlm = str(user["ntlm_hash"])
- else:
- continue
-
- secret = hashlib.md5(ntlm.decode("hex")).hexdigest()
- secrets.add(secret)
-
- return secrets
-
- def GetDomainAdminsOfMachine(self):
- domain_name = self.GetDomainName()
- DCs = self.GetDomainControllersMonkeyGuidByDomainName(domain_name)
-
- domain_admins = set()
-
- for dc_monkey_guid in DCs:
- domain_admins |= Machine(dc_monkey_guid).GetLocalAdmins()
-
- return domain_admins
-
- def GetAdmins(self):
- return self.GetLocalAdmins() | self.GetDomainAdminsOfMachine()
-
- def GetAdminNames(self):
- return set(map(lambda x: self.GetUsernameBySid(x), self.GetAdmins()))
-
- def GetCachedSids(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- SIDs = set()
-
- for doc in cur:
- for username in doc["data"]["credentials"]:
- SIDs.add(self.GetSidByUsername(username))
-
- return SIDs
-
- def GetCachedUsernames(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection", "monkey_guid": self.monkey_guid})
-
- SIDs = set()
-
- for doc in cur:
- for username in doc["data"]["credentials"]:
- SIDs.add(username)
-
- return SIDs
-
-class PassTheHashMap(object):
- def __init__(self):
- self.vertices = self.GetAllMachines()
- self.edges = set()
-
- self.GenerateEdgesBySid() # Useful for non-cached domain users
- self.GenerateEdgesBySamHash() # This will add edges based only on password hash without caring about username
-
- def GetAllMachines(self):
- cur = db.telemetry.find({"telem_type":"system_info_collection"})
-
- GUIDs = set()
-
- for doc in cur:
- GUIDs.add(doc["monkey_guid"])
-
- return GUIDs
-
- def GenerateEdgesBySid(self):
- for attacker in self.vertices:
- cached = Machine(attacker).GetCachedSids()
-
- for victim in self.vertices:
- if attacker == victim:
- continue
-
- admins = Machine(victim).GetAdmins()
-
- if len(cached & admins) > 0:
- self.edges.add((attacker, victim))
-
- def GenerateEdgesBySamHash(self):
- for attacker in self.vertices:
- cached = Machine(attacker).GetCachedSecrets()
-
- for victim in self.vertices:
- if attacker == victim:
- continue
-
- admins = Machine(victim).GetLocalAdminSecrets()
-
- if len(cached & admins) > 0:
- self.edges.add((attacker, victim))
-
- def GenerateEdgesByUsername(self):
- for attacker in self.vertices:
- cached = Machine(attacker).GetCachedUsernames()
-
- for victim in self.vertices:
- if attacker == victim:
- continue
-
- admins = Machine(victim).GetAdminNames()
-
- if len(cached & admins) > 0:
- self.edges.add((attacker, victim))
-
- def Print(self):
- print map(lambda x: Machine(x).GetIp(), self.vertices)
- print map(lambda x: (Machine(x[0]).GetIp(), Machine(x[1]).GetIp()), self.edges)
-
-PassTheHashMap().Print()
-
-#monkey_guid_island = 345051728334
-#monkey_guid_c = 345051740363
-#monkey_guid_d = 345051735830
-#
-#island = Machine(monkey_guid_island)
-#c = Machine(monkey_guid_c)
-#d = Machine(monkey_guid_d)
-#
-#assert str(island.GetIp()).endswith(".5")
-#assert str(c.GetIp()).endswith(".203")
-#assert str(d.GetIp()).endswith(".204")
-
-#print "sam", island.GetLocalAdminSecrets()
-#print "lsa", island.GetCachedSecrets()
-
-#print "cached", c.GetCachedSids()
-#print "admins", d.GetAdmins()