public void LMv1ResponseTest() { byte[] challenge = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; byte[] response = NtlmCryptography.ComputeLMv1Response(challenge, "Password"); byte[] expected = { 0x98, 0xde, 0xf7, 0xb8, 0x7f, 0x88, 0xaa, 0x5d, 0xaf, 0xe2, 0xdf, 0x77, 0x96, 0x88, 0xa1, 0x72, 0xde, 0xf1, 0x1c, 0x7d, 0x5c, 0xcd, 0xef, 0x13 }; Assert.True(ByteUtils.AreByteArraysEqual(response, expected)); }
public static byte[]? GetAuthenticateMessage(byte[] securityBlob, string domainName, string userName, string password, AuthenticationMethod authenticationMethod, out byte[]?sessionKey) { sessionKey = null; bool useGssApi = false; SimpleProtectedNegotiationTokenResponse?inputToken = null; try { inputToken = SimpleProtectedNegotiationToken.ReadToken(securityBlob, 0, false) as SimpleProtectedNegotiationTokenResponse; } catch { // ignored } ChallengeMessage?challengeMessage; if (inputToken != null) { challengeMessage = GetChallengeMessage(inputToken.ResponseToken); useGssApi = true; } else { challengeMessage = GetChallengeMessage(securityBlob); } if (challengeMessage == null) { return(null); } DateTime time = DateTime.UtcNow; byte[] clientChallenge = new byte[8]; new Random().NextBytes(clientChallenge); AuthenticateMessage authenticateMessage = new AuthenticateMessage { // https://msdn.microsoft.com/en-us/library/cc236676.aspx NegotiateFlags = NegotiateFlags.Sign | NegotiateFlags.NTLMSessionSecurity | NegotiateFlags.AlwaysSign | NegotiateFlags.Version | NegotiateFlags.Use128BitEncryption | NegotiateFlags.Use56BitEncryption }; if ((challengeMessage.NegotiateFlags & NegotiateFlags.UnicodeEncoding) > 0) { authenticateMessage.NegotiateFlags |= NegotiateFlags.UnicodeEncoding; } else { authenticateMessage.NegotiateFlags |= NegotiateFlags.OEMEncoding; } if ((challengeMessage.NegotiateFlags & NegotiateFlags.KeyExchange) > 0) { authenticateMessage.NegotiateFlags |= NegotiateFlags.KeyExchange; } if (authenticationMethod == AuthenticationMethod.NtlmV1) { authenticateMessage.NegotiateFlags |= NegotiateFlags.LanManagerSessionKey; } else { authenticateMessage.NegotiateFlags |= NegotiateFlags.ExtendedSessionSecurity; } authenticateMessage.UserName = userName; authenticateMessage.DomainName = domainName; authenticateMessage.WorkStation = Environment.MachineName; byte[] sessionBaseKey; byte[] keyExchangeKey; if (authenticationMethod == AuthenticationMethod.NtlmV1 || authenticationMethod == AuthenticationMethod.NtlmV1ExtendedSessionSecurity) { if (authenticationMethod == AuthenticationMethod.NtlmV1) { authenticateMessage.LmChallengeResponse = NtlmCryptography.ComputeLMv1Response(challengeMessage.ServerChallenge, password); authenticateMessage.NtChallengeResponse = NtlmCryptography.ComputeNTLMv1Response(challengeMessage.ServerChallenge, password); } else // NtlmV1ExtendedSessionSecurity { authenticateMessage.LmChallengeResponse = ByteUtils.Concatenate(clientChallenge, new byte[16]); authenticateMessage.NtChallengeResponse = NtlmCryptography.ComputeNTLMv1ExtendedSessionSecurityResponse(challengeMessage.ServerChallenge, clientChallenge, password); } // https://msdn.microsoft.com/en-us/library/cc236699.aspx sessionBaseKey = new MD4().GetByteHashFromBytes(NtlmCryptography.NTOWFv1(password)); byte[] lmowf = NtlmCryptography.LMOWFv1(password); keyExchangeKey = NtlmCryptography.KXKey(sessionBaseKey, authenticateMessage.NegotiateFlags, authenticateMessage.LmChallengeResponse, challengeMessage.ServerChallenge, lmowf); } else // NtlmV2 { NTLMv2ClientChallenge clientChallengeStructure = new NTLMv2ClientChallenge(time, clientChallenge, challengeMessage.TargetInfo); byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded(); byte[] ntProofStr = NtlmCryptography.ComputeNTLMv2Proof(challengeMessage.ServerChallenge, clientChallengeStructurePadded, password, userName, domainName); authenticateMessage.LmChallengeResponse = NtlmCryptography.ComputeLMv2Response(challengeMessage.ServerChallenge, clientChallenge, password, userName, challengeMessage.TargetName); authenticateMessage.NtChallengeResponse = ByteUtils.Concatenate(ntProofStr, clientChallengeStructurePadded); // https://msdn.microsoft.com/en-us/library/cc236700.aspx byte[] responseKeyNT = NtlmCryptography.NTOWFv2(password, userName, domainName); using HMACMD5 md5 = new HMACMD5(responseKeyNT); sessionBaseKey = md5.ComputeHash(ntProofStr); keyExchangeKey = sessionBaseKey; } authenticateMessage.Version = NtlmVersion.Server2003; // https://msdn.microsoft.com/en-us/library/cc236676.aspx if ((challengeMessage.NegotiateFlags & NegotiateFlags.KeyExchange) > 0) { sessionKey = new byte[16]; new Random().NextBytes(sessionKey); authenticateMessage.EncryptedRandomSessionKey = RC4.Encrypt(keyExchangeKey, sessionKey); } else { sessionKey = keyExchangeKey; } if (!useGssApi) { return(authenticateMessage.GetBytes()); } SimpleProtectedNegotiationTokenResponse outputToken = new SimpleProtectedNegotiationTokenResponse { ResponseToken = authenticateMessage.GetBytes() }; return(outputToken.GetBytes()); }
public void Login(string domainName, string userName, string password, AuthenticationMethod authenticationMethod) { if (!IsConnected) { throw new InvalidOperationException("A connection must be successfully established before attempting login"); } Capabilities clientCapabilities = Capabilities.NTSMB | Capabilities.RpcRemoteApi | Capabilities.NTStatusCode | Capabilities.NTFind; if (m_unicode) { clientCapabilities |= Capabilities.Unicode; } if (m_largeFiles) { clientCapabilities |= Capabilities.LargeFiles; } if (m_largeRead) { clientCapabilities |= Capabilities.LargeRead; } if (m_serverChallenge != null) { SessionSetupAndXRequest request = new SessionSetupAndXRequest { MaxBufferSize = ClientMaxBufferSize, MaxMpxCount = m_maxMpxCount, Capabilities = clientCapabilities, AccountName = userName, PrimaryDomain = domainName }; byte[] clientChallenge = new byte[8]; new Random().NextBytes(clientChallenge); if (authenticationMethod == AuthenticationMethod.NtlmV1) { request.OEMPassword = NtlmCryptography.ComputeLMv1Response(m_serverChallenge, password); request.UnicodePassword = NtlmCryptography.ComputeNTLMv1Response(m_serverChallenge, password); } else if (authenticationMethod == AuthenticationMethod.NtlmV1ExtendedSessionSecurity) { // [MS-CIFS] CIFS does not support Extended Session Security because there is no mechanism in CIFS to negotiate Extended Session Security throw new ArgumentException("SMB Extended Security must be negotiated in order for NtlmV1 Extended Session Security to be used"); } else // NtlmV2 { // Note: NtlmV2 over non-extended security session setup is not supported under Windows Vista and later which will return STATUS_INVALID_PARAMETER. // https://msdn.microsoft.com/en-us/library/ee441701.aspx // https://msdn.microsoft.com/en-us/library/cc236700.aspx request.OEMPassword = NtlmCryptography.ComputeLMv2Response(m_serverChallenge, clientChallenge, password, userName, domainName); NTLMv2ClientChallenge clientChallengeStructure = new NTLMv2ClientChallenge(DateTime.UtcNow, clientChallenge, AVPairUtils.GetAVPairSequence(domainName, Environment.MachineName)); byte[] temp = clientChallengeStructure.GetBytesPadded(); byte[] proofStr = NtlmCryptography.ComputeNTLMv2Proof(m_serverChallenge, temp, password, userName, domainName); request.UnicodePassword = ByteUtils.Concatenate(proofStr, temp); } SendMessage(request); SMB1Message reply = WaitForMessage(CommandName.SMB_COM_SESSION_SETUP_ANDX); m_isLoggedIn = (reply.Header.Status == NTStatus.STATUS_SUCCESS); reply.IsSuccessElseThrow(); } else // m_securityBlob != null { byte[] negotiateMessage = NtlmAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod); SessionSetupAndXRequestExtended request = new SessionSetupAndXRequestExtended { MaxBufferSize = ClientMaxBufferSize, MaxMpxCount = m_maxMpxCount, Capabilities = clientCapabilities, SecurityBlob = negotiateMessage }; SendMessage(request); SMB1Message reply = WaitForMessage(CommandName.SMB_COM_SESSION_SETUP_ANDX); if (reply.Header.Status != NTStatus.STATUS_MORE_PROCESSING_REQUIRED || !(reply.Commands[0] is SessionSetupAndXResponseExtended)) { throw new NtStatusException(reply.Header.Status); } SessionSetupAndXResponseExtended response = (SessionSetupAndXResponseExtended)reply.Commands[0]; byte[]? authenticateMessage = NtlmAuthenticationHelper.GetAuthenticateMessage(response.SecurityBlob, domainName, userName, password, authenticationMethod, out m_sessionKey); if (authenticateMessage == null) { throw new NtStatusException(NTStatus.SEC_E_INVALID_TOKEN); } m_userID = reply.Header.UID; request = new SessionSetupAndXRequestExtended { MaxBufferSize = ClientMaxBufferSize, MaxMpxCount = m_maxMpxCount, Capabilities = clientCapabilities, SecurityBlob = authenticateMessage }; SendMessage(request); reply = WaitForMessage(CommandName.SMB_COM_SESSION_SETUP_ANDX); m_isLoggedIn = (reply.Header.Status == NTStatus.STATUS_SUCCESS); reply.IsSuccessElseThrow(); } }