diff --git a/SMBLibrary/Client/SMB2Client.cs b/SMBLibrary/Client/SMB2Client.cs
index 7601a66..5d22b79 100644
--- a/SMBLibrary/Client/SMB2Client.cs
+++ b/SMBLibrary/Client/SMB2Client.cs
@@ -56,6 +56,7 @@ namespace SMBLibrary.Client
private ulong m_sessionID;
private byte[] m_securityBlob;
private byte[] m_sessionKey;
+ private byte[] m_preauthIntegrityHashValue; // SMB 3.1.1
private ushort m_availableCredits = 1;
public SMB2Client()
@@ -203,7 +204,14 @@ namespace SMBLibrary.Client
request.Dialects.Add(SMB2Dialect.SMB202);
request.Dialects.Add(SMB2Dialect.SMB210);
request.Dialects.Add(SMB2Dialect.SMB300);
-
+#if SMB302_CLIENT
+ request.Dialects.Add(SMB2Dialect.SMB302);
+#endif
+#if SMB311_CLIENT
+ request.Dialects.Add(SMB2Dialect.SMB311);
+ request.NegotiateContextList = GetNegotiateContextList();
+ m_preauthIntegrityHashValue = new byte[64];
+#endif
TrySendCommand(request);
NegotiateResponse response = WaitForCommand(request.MessageID) as NegotiateResponse;
if (response != null && response.Header.Status == NTStatus.STATUS_SUCCESS)
@@ -280,14 +288,14 @@ namespace SMBLibrary.Client
}
else
{
- m_signingKey = SMB2Cryptography.GenerateSigningKey(m_sessionKey, m_dialect, null);
+ m_signingKey = SMB2Cryptography.GenerateSigningKey(m_sessionKey, m_dialect, m_preauthIntegrityHashValue);
}
if (m_dialect >= SMB2Dialect.SMB300)
{
m_encryptSessionData = (sessionFlags & SessionFlags.EncryptData) > 0;
- m_encryptionKey = SMB2Cryptography.GenerateClientEncryptionKey(m_sessionKey, m_dialect, null);
- m_decryptionKey = SMB2Cryptography.GenerateClientDecryptionKey(m_sessionKey, m_dialect, null);
+ m_encryptionKey = SMB2Cryptography.GenerateClientEncryptionKey(m_sessionKey, m_dialect, m_preauthIntegrityHashValue);
+ m_decryptionKey = SMB2Cryptography.GenerateClientDecryptionKey(m_sessionKey, m_dialect, m_preauthIntegrityHashValue);
}
}
return response.Header.Status;
@@ -488,6 +496,11 @@ namespace SMBLibrary.Client
return;
}
+ if (m_preauthIntegrityHashValue != null && (command is NegotiateResponse || (command is SessionSetupResponse sessionSetupResponse && sessionSetupResponse.Header.Status == NTStatus.STATUS_MORE_PROCESSING_REQUIRED)))
+ {
+ m_preauthIntegrityHashValue = SMB2Cryptography.ComputeHash(HashAlgorithm.SHA512, ByteUtils.Concatenate(m_preauthIntegrityHashValue, messageBytes));
+ }
+
m_availableCredits += command.Header.Credits;
if (m_transport == SMBTransportType.DirectTCPTransport && command is NegotiateResponse)
@@ -657,6 +670,24 @@ namespace SMBLibrary.Client
}
}
+ /// SMB 3.1.1 only
+ private List GetNegotiateContextList()
+ {
+ PreAuthIntegrityCapabilities preAuthIntegrityCapabilities = new PreAuthIntegrityCapabilities();
+ preAuthIntegrityCapabilities.HashAlgorithms.Add(HashAlgorithm.SHA512);
+ preAuthIntegrityCapabilities.Salt = new byte[32];
+ new Random().NextBytes(preAuthIntegrityCapabilities.Salt);
+
+ EncryptionCapabilities encryptionCapabilities = new EncryptionCapabilities();
+ encryptionCapabilities.Ciphers.Add(CipherAlgorithm.Aes128Ccm);
+
+ return new List()
+ {
+ new NegotiateContext(preAuthIntegrityCapabilities),
+ new NegotiateContext(encryptionCapabilities)
+ };
+ }
+
public uint MaxTransactSize
{
get
@@ -700,6 +731,10 @@ namespace SMBLibrary.Client
else
{
packet.Trailer = request.GetBytes();
+ if (m_preauthIntegrityHashValue != null && (request is NegotiateRequest || request is SessionSetupRequest))
+ {
+ m_preauthIntegrityHashValue = SMB2Cryptography.ComputeHash(HashAlgorithm.SHA512, ByteUtils.Concatenate(m_preauthIntegrityHashValue, packet.Trailer));
+ }
}
TrySendPacket(socket, packet);
}