forked from p15670423/monkey
Fixed bugs and finished up pypykatz integration
This commit is contained in:
parent
192ac67159
commit
895db8b446
|
@ -39,9 +39,9 @@ class WmiExploiter(HostExploiter):
|
|||
for user, password, lm_hash, ntlm_hash in creds:
|
||||
password_hashed = self._config.hash_sensitive_data(password)
|
||||
lm_hash_hashed = self._config.hash_sensitive_data(lm_hash)
|
||||
mtlm_hash_hashed = self._config.hash_sensitive_data(ntlm_hash)
|
||||
ntlm_hash_hashed = self._config.hash_sensitive_data(ntlm_hash)
|
||||
creds_for_logging = "user, password (SHA-512), lm hash (SHA-512), ntlm hash (SHA-512): " \
|
||||
"({},{},{},{})".format(user, password_hashed, lm_hash_hashed, mtlm_hash_hashed)
|
||||
"({},{},{},{})".format(user, password_hashed, lm_hash_hashed, ntlm_hash_hashed)
|
||||
LOG.debug(("Attempting to connect %r using WMI with " % self.host) + creds_for_logging)
|
||||
|
||||
wmi_connection = WmiTools.WmiConnection()
|
||||
|
|
|
@ -105,6 +105,7 @@ class InfoCollector(object):
|
|||
# we might be losing passwords in case of multiple reset attempts on same username
|
||||
# or in case another collector already filled in a password for this user
|
||||
self.info["credentials"][username]['password'] = password
|
||||
self.info["credentials"][username]['username'] = username
|
||||
if len(azure_creds) != 0:
|
||||
self.info["Azure"] = {}
|
||||
self.info["Azure"]['usernames'] = [cred[0] for cred in azure_creds]
|
||||
|
|
|
@ -18,5 +18,8 @@ class WindowsCredentialCollector(object):
|
|||
def cred_list_to_cred_dict(creds: List[WindowsCredential]):
|
||||
cred_dict = {}
|
||||
for cred in creds:
|
||||
cred_dict.update({cred.username: cred.to_dict()})
|
||||
# Lets not use "." and "$" in keys, because it will confuse mongo.
|
||||
# Ideally we should refactor island not to use a dict and simply parse credential list.
|
||||
key = cred.username.replace(".", ",").replace("$", "")
|
||||
cred_dict.update({key: cred.to_dict()})
|
||||
return cred_dict
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
__author__ = 'maor.rayzin'
|
||||
|
||||
|
||||
class MimikatzSecrets(object):
|
||||
|
||||
def __init__(self):
|
||||
# Static class
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def extract_sam_secrets(mim_string, users_dict):
|
||||
users_secrets = mim_string.split("\n42.")[1].split("\nSAMKey :")[1].split("\n\n")[1:]
|
||||
|
||||
if mim_string.count("\n42.") != 2:
|
||||
return {}
|
||||
|
||||
for sam_user_txt in users_secrets:
|
||||
sam_user = dict([list(map(str.strip, line.split(":"))) for line in
|
||||
[l for l in sam_user_txt.splitlines() if l.count(":") == 1]])
|
||||
username = sam_user.get("User")
|
||||
users_dict[username] = {}
|
||||
|
||||
ntlm = sam_user.get("NTLM")
|
||||
if not ntlm or "[hashed secret]" not in ntlm:
|
||||
continue
|
||||
|
||||
users_dict[username]['SAM'] = ntlm.replace("[hashed secret]", "").strip()
|
||||
|
||||
@staticmethod
|
||||
def extract_ntlm_secrets(mim_string, users_dict):
|
||||
|
||||
if mim_string.count("\n42.") != 2:
|
||||
return {}
|
||||
|
||||
ntds_users = mim_string.split("\n42.")[2].split("\nRID :")[1:]
|
||||
|
||||
for ntds_user_txt in ntds_users:
|
||||
user = ntds_user_txt.split("User :")[1].splitlines()[0].replace("User :", "").strip()
|
||||
ntlm = ntds_user_txt.split("* Primary\n NTLM :")[1].splitlines()[0].replace("NTLM :", "").strip()
|
||||
ntlm = ntlm.replace("[hashed secret]", "").strip()
|
||||
users_dict[user] = {}
|
||||
if ntlm:
|
||||
users_dict[user]['ntlm'] = ntlm
|
||||
|
||||
@staticmethod
|
||||
def extract_secrets_from_mimikatz(mim_string):
|
||||
users_dict = {}
|
||||
MimikatzSecrets.extract_sam_secrets(mim_string, users_dict)
|
||||
MimikatzSecrets.extract_ntlm_secrets(mim_string, users_dict)
|
||||
|
||||
return users_dict
|
|
@ -184,10 +184,13 @@ class ReportService:
|
|||
continue
|
||||
origin = NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname']
|
||||
for user in monkey_creds:
|
||||
for pass_type in monkey_creds[user]:
|
||||
for pass_type in PASS_TYPE_DICT:
|
||||
if pass_type not in monkey_creds[user] or not monkey_creds[user][pass_type]:
|
||||
continue
|
||||
username = monkey_creds[user]['username'] if 'username' in monkey_creds[user] else user
|
||||
cred_row = \
|
||||
{
|
||||
'username': user.replace(',', '.'),
|
||||
'username': username,
|
||||
'type': PASS_TYPE_DICT[pass_type],
|
||||
'origin': origin
|
||||
}
|
||||
|
@ -729,8 +732,7 @@ class ReportService:
|
|||
'stolen_creds': ReportService.get_stolen_creds(),
|
||||
'azure_passwords': ReportService.get_azure_creds(),
|
||||
'ssh_keys': ReportService.get_ssh_keys(),
|
||||
'strong_users': PTHReportService.get_strong_users_on_crit_details(),
|
||||
'pth_map': PTHReportService.get_pth_map()
|
||||
'strong_users': PTHReportService.get_strong_users_on_crit_details()
|
||||
},
|
||||
'recommendations':
|
||||
{
|
||||
|
|
|
@ -69,7 +69,7 @@ class WMIHandler(object):
|
|||
base_entity = self.build_entity_document(user)
|
||||
else:
|
||||
base_entity = self.build_entity_document(user, self.monkey_id)
|
||||
base_entity['NTLM_secret'] = self.users_secrets.get(base_entity['name'], {}).get('ntlm')
|
||||
base_entity['NTLM_secret'] = self.users_secrets.get(base_entity['name'], {}).get('ntlm_hash')
|
||||
base_entity['SAM_secret'] = self.users_secrets.get(base_entity['name'], {}).get('sam')
|
||||
base_entity['secret_location'] = []
|
||||
|
||||
|
|
Loading…
Reference in New Issue