private void AddCompressionCapabilities(DetectionInfo info) { var excludedCompressionAlogrithms = new CompressionAlgorithm[] { CompressionAlgorithm.NONE, CompressionAlgorithm.Unsupported, }; var possibleCompressionAlogrithms = Enum.GetValues(typeof(CompressionAlgorithm)).Cast <CompressionAlgorithm>().Except(excludedCompressionAlogrithms); foreach (var compressionAlgorithm in possibleCompressionAlogrithms) { if (info.smb2Info.SupportedCompressionAlgorithms.Contains(compressionAlgorithm)) { AddResultItem(ref this.compressionItems, compressionAlgorithm.ToString(), DetectResult.Supported); } else { AddResultItem(ref this.compressionItems, compressionAlgorithm.ToString(), DetectResult.UnSupported); } } var chainedCompressionResult = info.smb2Info.IsChainedCompressionSupported ? DetectResult.Supported : DetectResult.UnSupported; AddResultItem(ref this.compressionItems, "Chained compression", chainedCompressionResult); }
public bool FetchClusterShareInfo(DetectionInfo info) { if (string.IsNullOrEmpty(info.clusterShareFullPath)) { return(false); } // Try to connect the share which is input by the user in the "Cluster Share" field of Auto-Detection page. using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; try { logWriter.AddLog(DetectLogLevel.Information, string.Format("Try to connect share {0}.", info.clusterShareFullPath)); ConnectToClusterShare(info, client, out messageId, out sessionId, out treeId); } catch { // Show error to user. logWriter.AddLog(DetectLogLevel.Error, string.Format("Cannot connect to cluster share {0}. Please check the share setting and SUT password.", info.clusterShareFullPath)); return(false); } } return(true); }
public void LoadDetectionInfo(DetectionInfo detectionInfo) { this.info = detectionInfo; // Add/Update detected Dialects AddDialect(this.info.smb2Info.MaxSupportedDialectRevision); // Add/Update detected Capablities AddCapability(Capabilities_Values.GLOBAL_CAP_DFS, "DFS (Distributed File System)"); AddCapability(Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING, "Directory Leasing"); AddCapability(Capabilities_Values.GLOBAL_CAP_ENCRYPTION, "Encryption"); AddCapability(Capabilities_Values.GLOBAL_CAP_LARGE_MTU, "Large MTU (multi-credit operations)"); AddCapability(Capabilities_Values.GLOBAL_CAP_LEASING, "Leasing"); AddCapability(Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, "Multiple Channel"); AddCapability(Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, "Persistent Handle"); // Add/Update detected IoCtl codes AddIoctlCode(CtlCode_Values.FSCTL_OFFLOAD_READ, this.info.F_CopyOffload[0]); AddIoctlCode(CtlCode_Values.FSCTL_OFFLOAD_WRITE, this.info.F_CopyOffload[1]); AddIoctlCode(CtlCode_Values.FSCTL_FILE_LEVEL_TRIM, this.info.F_FileLevelTrim); AddIoctlCode(CtlCode_Values.FSCTL_GET_INTEGRITY_INFORMATION, this.info.F_IntegrityInfo[0]); AddIoctlCode(CtlCode_Values.FSCTL_SET_INTEGRITY_INFORMATION, this.info.F_IntegrityInfo[1]); AddIoctlCode(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY, this.info.F_ResilientHandle); AddIoctlCode(CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO, this.info.F_ValidateNegotiateInfo); // Add/Update detected Create Contexts AddCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID, this.info.F_AppInstanceId); AddCreateContext( CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST, (info.F_HandleV1_BatchOplock == DetectResult.Supported || info.F_HandleV1_LeaseV1 == DetectResult.Supported) ? DetectResult.Supported : DetectResult.UnSupported); AddCreateContext( CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT, (info.F_HandleV1_BatchOplock == DetectResult.Supported || info.F_HandleV1_LeaseV1 == DetectResult.Supported) ? DetectResult.Supported : DetectResult.UnSupported); AddCreateContext( CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, (info.F_HandleV2_BatchOplock == DetectResult.Supported || info.F_HandleV2_LeaseV1 == DetectResult.Supported || info.F_HandleV2_LeaseV2 == DetectResult.Supported) ? DetectResult.Supported : DetectResult.UnSupported); AddCreateContext( CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, (info.F_HandleV2_BatchOplock == DetectResult.Supported || info.F_HandleV2_LeaseV1 == DetectResult.Supported || info.F_HandleV2_LeaseV2 == DetectResult.Supported) ? DetectResult.Supported : DetectResult.UnSupported); AddCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE, this.info.F_Leasing_V1); AddCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2, this.info.F_Leasing_V2); //Bind the data to the control resultItemMapList.Add(dialectsItems); resultItemMapList.Add(capabilitiesItems); resultItemMapList.Add(ioctlCodesItems); resultItemMapList.Add(createContextsItems); ResultMapList.ItemsSource = resultItemMapList; }
public NetworkInfo FetchLocalNetworkInfo(DetectionInfo info) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { LogIPConfig(); } //Get the network information with SUTIpList NetworkInfo networkInfo = info.networkInfo; #region Get Local IP List networkInfo.LocalIpList = new List <IPAddress>(); foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces()) { if (adapter.OperationalStatus != OperationalStatus.Up) { continue; } if (adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet || adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || adapter.NetworkInterfaceType == NetworkInterfaceType.GigabitEthernet) { foreach (var ip in adapter.GetIPProperties().UnicastAddresses) { if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { try { smb2Client.ConnectOverTCP(SUTIpAddress, ip.Address); networkInfo.LocalIpList.Add(ip.Address); } catch (Exception ex) { logWriter.AddLog( DetectLogLevel.Information, string.Format("Connect from client IP {0} to SUT IP {1} failed, reason: {2}", ip.Address, SUTIpAddress, ex.Message)); } } } } } } if (networkInfo.LocalIpList.Count == 0) { logWriter.AddLog(DetectLogLevel.Error, "No available local IP address"); } #endregion return(networkInfo); }
private void FetchPlatformInfo(ref DetectionInfo info) { ManagementObjectCollection resultCollection = QueryWmiObject(SUTName, "SELECT * FROM Win32_OperatingSystem"); foreach (ManagementObject result in resultCollection) { info.platform = ConvertPlatform(result["Version"].ToString(), result["BuildNumber"].ToString()); logWriter.AddLog(LogLevel.Information, "Platform: " + info.platform); break; } }
/// <summary> /// Check if the server supports RSVD. /// </summary> public DetectResult CheckRsvdSupport(ref DetectionInfo info) { DetectResult result = DetectResult.DetectFail; logWriter.AddLog(LogLevel.Information, "Share path: " + info.targetShareFullPath); #region Copy test VHD file to the target share to begin detecting RSVD string vhdOnSharePath = Path.Combine(info.targetShareFullPath, vhdName); CopyTestVHD(info.targetShareFullPath, vhdOnSharePath); #endregion try { #region RSVD version 2 bool versionTestRes = TestRsvdVersion(vhdName + fileNameSuffix, info.BasicShareName, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2); if (versionTestRes) { info.RsvdVersion = RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "RSVD version 2 is supported"); return(result); } else { logWriter.AddLog(LogLevel.Information, "The server doesn't support RSVD version 2."); } #endregion #region RSVD version 1 versionTestRes = TestRsvdVersion(vhdName + fileNameSuffix, info.BasicShareName, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_1); if (versionTestRes) { info.RsvdVersion = RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_1; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "RSVD version 1 is supported"); return(result); } else { result = DetectResult.UnSupported; logWriter.AddLog(LogLevel.Information, @"The server doesn't support RSVD."); } #endregion } catch (Exception e) { logWriter.AddLog(LogLevel.Information, @"Detect RSVD failed with exception: " + e.Message); } DeleteTestVHD(info.targetShareFullPath, vhdOnSharePath); return(result); }
/// <summary> /// Negotiate, SessionSetup, TreeConnect /// </summary> /// <returns>Return true for success, false for failure</returns> private void ConnectToShare( string sharename, DetectionInfo info, Smb2Client client, out ulong messageId, out ulong sessionId, out uint treeId) { Packet_Header header; Guid clientGuid; NEGOTIATE_Response negotiateResp; bool encryptionRequired = false; UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResp, out encryptionRequired); #region TreeConnect TREE_CONNECT_Response treeConnectResp; string uncSharePath = Smb2Utility.GetUncPath(info.targetSUT, sharename); logWriter.AddLog(DetectLogLevel.Information, "Client sends TreeConnect to server"); if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted. { client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired); } client.TreeConnect( 1, 1, (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncSharePath, out treeId, out header, out treeConnectResp); // When dialect is 3.11, for the messages other than TreeConnect, signing is not required. // Set it back to the configuration of the SUT. if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) { client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired); } if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREECONNECT", header.Status); throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion }
/// <summary> /// Check if the server supports SQOS. /// </summary> public DetectResult CheckSqosSupport(ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "Share name: " + info.targetShareFullPath); DetectResult result = DetectResult.UnSupported; if (info.smb2Info.MaxSupportedDialectRevision < DialectRevision.Smb311) { return(result); } #region copy test VHD file to share string vhdOnSharePath = Path.Combine(info.targetShareFullPath, vhdName); CopyTestVHD(info.targetShareFullPath, vhdOnSharePath); #endregion #region SQOS dialect 1.1 bool versionTestRes = TestSqosVersion(info.BasicShareName, SQOS_PROTOCOL_VERSION.Sqos11); if (versionTestRes) { info.SqosVersion = SQOS_PROTOCOL_VERSION.Sqos11; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "SQOS dialect 1.1 is supported"); return(result); } else { logWriter.AddLog(LogLevel.Information, "The server doesn't support SQOS version 2."); } #endregion #region SQOS dialect 1.0 versionTestRes = TestSqosVersion(info.BasicShareName, SQOS_PROTOCOL_VERSION.Sqos10); if (versionTestRes) { info.SqosVersion = SQOS_PROTOCOL_VERSION.Sqos10; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "SQOS dialect 1.0 is supported"); return(result); } else { result = DetectResult.UnSupported; logWriter.AddLog(LogLevel.Information, @"The server doesn't support SQOS."); } #endregion DeleteTestVHD(info.targetShareFullPath, vhdOnSharePath); return(result); }
/// <summary> /// Check if the server supports SQOS. /// </summary> public DetectResult CheckSqosSupport(ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "Share name: " + info.targetShareFullPath); DetectResult result = DetectResult.UnSupported; if (info.smb2Info.MaxSupportedDialectRevision < DialectRevision.Smb311) { return result; } #region copy test VHD file to share string vhdOnSharePath = info.targetShareFullPath + @"\" + vhdName; CopyTestVHD(vhdOnSharePath); #endregion #region SQOS dialect 1.1 bool versionTestRes = TestSqosVersion(info.BasicShareName, SQOS_PROTOCOL_VERSION.Sqos11); if (versionTestRes) { info.SqosVersion = SQOS_PROTOCOL_VERSION.Sqos11; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "SQOS dialect 1.1 is supported"); return result; } else { logWriter.AddLog(LogLevel.Information, "The server doesn't support SQOS version 2."); } #endregion #region SQOS dialect 1.0 versionTestRes = TestSqosVersion(info.BasicShareName, SQOS_PROTOCOL_VERSION.Sqos10); if (versionTestRes) { info.SqosVersion = SQOS_PROTOCOL_VERSION.Sqos10; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "SQOS dialect 1.0 is supported"); return result; } else { result = DetectResult.UnSupported; logWriter.AddLog(LogLevel.Information, @"The server doesn't support SQOS."); } #endregion return result; }
public Smb2Info FetchSmb2Info(DetectionInfo info) { Smb2Info smb2Info = new Smb2Info(); using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { logWriter.AddLog(DetectLogLevel.Information, "Client connects to server"); smb2Client.ConnectOverTCP(SUTIpAddress); DialectRevision selectedDialect; byte[] gssToken; Packet_Header responseHeader; NEGOTIATE_Response responsePayload; ulong messageId = 1; logWriter.AddLog(DetectLogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( smb2Client, 0, 1, Packet_Header_Flags_Values.NONE, ref messageId, info.requestDialect, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, Guid.NewGuid(), out selectedDialect, out gssToken, out responseHeader, out responsePayload); if (responseHeader.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", responseHeader.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(responseHeader.Status))); } smb2Info.MaxSupportedDialectRevision = responsePayload.DialectRevision; smb2Info.SupportedCapabilities = (Capabilities_Values)responsePayload.Capabilities; smb2Info.SelectedCipherID = smb2Client.SelectedCipherID; smb2Info.IsRequireMessageSigning = responsePayload.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); } FetchSmb2CompressionInfo(smb2Info); FetchSmb2EncryptionInfo(smb2Info); return(smb2Info); }
private void AddCompressionCapabilities(DetectionInfo info) { var possibleCompressionAlogrithms = new CompressionAlgorithm[] { CompressionAlgorithm.LZ77, CompressionAlgorithm.LZ77Huffman, CompressionAlgorithm.LZNT1 }; foreach (var compressionAlgorithm in possibleCompressionAlogrithms) { if (info.smb2Info.SupportedCompressionAlgorithms.Contains(compressionAlgorithm)) { AddResultItem(ref this.compressionItems, compressionAlgorithm.ToString(), DetectResult.Supported); } else { AddResultItem(ref this.compressionItems, compressionAlgorithm.ToString(), DetectResult.UnSupported); } } }
/// <summary> /// Check if the server supports RSVD. /// </summary> public DetectResult CheckRsvdSupport(ref DetectionInfo info) { DetectResult result = DetectResult.DetectFail; logWriter.AddLog(LogLevel.Information, "Share path: " + info.targetShareFullPath); #region Copy test VHD file to the target share to begin detecting RSVD string vhdOnSharePath = info.targetShareFullPath + @"\" + vhdName; CopyTestVHD(vhdOnSharePath); #endregion #region RSVD version 2 bool versionTestRes = TestRsvdVersion(vhdName + fileNameSuffix, info.BasicShareName, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2); if (versionTestRes) { info.RsvdVersion = RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "RSVD version 2 is supported"); return result; } else { logWriter.AddLog(LogLevel.Information, "The server doesn't support RSVD version 2."); } #endregion #region RSVD version 1 versionTestRes = TestRsvdVersion(vhdName + fileNameSuffix, info.BasicShareName, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_1); if (versionTestRes) { info.RsvdVersion = RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_1; result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "RSVD version 1 is supported"); return result; } else { result = DetectResult.UnSupported; logWriter.AddLog(LogLevel.Information, @"The server doesn't support RSVD."); } #endregion return result; }
public ShareInfo[] FetchShareInfo(DetectionInfo info) { string[] shareList = null; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { shareList = ServerHelper.EnumShares(SUTName, Credential.AccountName, Credential.DomainName, Credential.Password); } catch (Exception ex) { logWriter.AddLog(DetectLogLevel.Information, string.Format("EnumShares failed, reason: {0}", ex.Message)); } } if (shareList == null) { // EnumShares may fail because the SUT doesn't support SRVS. // Try to connect the share which is input by the user in the "Target Share" field of Auto-Detection page. using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; try { logWriter.AddLog(DetectLogLevel.Information, string.Format("Try to connect share {0}.", info.BasicShareName)); ConnectToShare(info.BasicShareName, info, client, out messageId, out sessionId, out treeId); shareList = new string[] { info.BasicShareName }; } catch { // Show error to user. logWriter.AddLog(DetectLogLevel.Error, "Did not find shares on SUT. Please check the share setting and SUT password."); } } } return(RetrieveShareProperties(shareList, info)); }
private void AddSQOS(DetectionInfo info) { if (info.SqosSupport == DetectResult.Supported) { if (info.SqosVersion == SQOS_PROTOCOL_VERSION.Sqos10) { AddResultItem(ref this.sqosItems, "SQOS dialect 1.0", DetectResult.Supported); AddResultItem(ref this.sqosItems, "SQOS dialect 1.1", DetectResult.UnSupported); } else { AddResultItem(ref this.sqosItems, "SQOS dialect 1.0", DetectResult.Supported); AddResultItem(ref this.sqosItems, "SQOS dialect 1.1", DetectResult.Supported); } } // DetectResult.UnSupported and DetectResult.DetectFail else { AddResultItem(ref this.sqosItems, "SQOS", info.SqosSupport); } }
private void AddRSVD(DetectionInfo info) { if (info.RsvdSupport == DetectResult.Supported) { if (info.RsvdVersion == RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_1) { AddResultItem(ref this.rsvdItems, "RSVD Protocol version 1", DetectResult.Supported); AddResultItem(ref this.rsvdItems, "RSVD Protocol version 2", DetectResult.UnSupported); } else { AddResultItem(ref this.rsvdItems, "RSVD Protocol version 1", DetectResult.Supported); AddResultItem(ref this.rsvdItems, "RSVD Protocol version 2", DetectResult.Supported); } } // DetectResult.UnSupported and DetectResult.DetectFail else { AddResultItem(ref this.rsvdItems, "RSVD", info.RsvdSupport); } }
/// <summary> /// Detect the existence of a share with the detection info client /// </summary> /// <param name="info"></param> /// <returns></returns> public DetectResult DetectShareExistence(DetectionInfo info, string shareName) { using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; try { logWriter.AddLog(DetectLogLevel.Information, string.Format("Try to connect share {0}.", shareName)); ConnectToShare(shareName, info, client, out messageId, out sessionId, out treeId); logWriter.AddLog(DetectLogLevel.Information, string.Format("Succeed to connect share {0}.", shareName)); } catch (Exception e) { // Show error to user. logWriter.AddLog(DetectLogLevel.Information, string.Format("Connect to share {0} failed with error message: {1}.", shareName, e.Message)); return(DetectResult.DetectFail); } } return(DetectResult.Supported); }
public void FetchPlatformAndUseraccounts(ref DetectionInfo info) { // Set the default values info.platform = Platform.NonWindows; info.nonadminUserAccounts = new List <string>(); try { FetchPlatformInfo(ref info); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, "Detect platform failure. Reason: " + ex.Message); } try { FetchNonAdminUseraccountInfo(ref info); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, "Detect useraccounts failure. Reason: " + ex.Message); } }
private void AddSMB2EncryptionAlgorithms(DetectionInfo info) { var excludedEncryptionAlogrithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_NONE, EncryptionAlgorithm.ENCRYPTION_INVALID, }; var possibleEncryptionAlogrithms = Enum.GetValues(typeof(EncryptionAlgorithm)).Cast <EncryptionAlgorithm>().Except(excludedEncryptionAlogrithms); foreach (var encryptionAlgorithm in possibleEncryptionAlogrithms) { if (info.smb2Info.SutSupportedEncryptionAlgorithms.Contains(encryptionAlgorithm)) { AddResultItem(ref this.encryptionAlgorithmItems, encryptionAlgorithm.ToString(), DetectResult.Supported); } else { AddResultItem(ref this.encryptionAlgorithmItems, encryptionAlgorithm.ToString(), DetectResult.UnSupported); } } }
public ShareInfo[] FetchShareInfo(DetectionInfo info) { string[] shareList = null; try { shareList = ServerHelper.EnumShares(SUTName, Credential.AccountName, Credential.DomainName, Credential.Password); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, string.Format("EnumShares failed, reason: {0}", ex.Message)); } if (shareList == null) { // EnumShares may fail because the SUT doesn't support SRVS. // Try to connect the default share "SMBBasic" using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; try { ConnectToShare(defautBasicShare, info, client, out messageId, out sessionId, out treeId); shareList = new string[] { defautBasicShare }; } catch { // Show error to user. logWriter.AddLog(LogLevel.Error, "Did not find shares on SUT. Please check share setting and SUT password."); } } } return(RetrieveShareProperties(shareList, info)); }
private void AddSQOS(DetectionInfo info) { if (info.SqosSupport == DetectResult.Supported) { if (info.SqosVersion == SQOS_PROTOCOL_VERSION.Sqos10) { AddResultItem(ref this.sqosItems, "SQOS dialect 1.0", DetectResult.Supported); AddResultItem(ref this.sqosItems, "SQOS dialect 1.1", DetectResult.UnSupported); } else { AddResultItem(ref this.sqosItems, "SQOS dialect 1.0", DetectResult.Supported); AddResultItem(ref this.sqosItems, "SQOS dialect 1.1", DetectResult.Supported); } } else if (info.SqosSupport == DetectResult.UnSupported) { AddResultItem(ref this.sqosItems, "The server doesn't support SQOS", info.SqosSupport); } else { AddResultItem(ref this.sqosItems, "Detection failed", this.info.SqosSupport); } }
private void AddRSVD(DetectionInfo info) { if (info.RsvdSupport == DetectResult.Supported) { if (info.RsvdVersion == RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_1) { AddResultItem(ref this.rsvdItems, "RSVD Protocol version 1", DetectResult.Supported); AddResultItem(ref this.rsvdItems, "RSVD Protocol version 2", DetectResult.UnSupported); } else { AddResultItem(ref this.rsvdItems, "RSVD Protocol version 1", DetectResult.Supported); AddResultItem(ref this.rsvdItems, "RSVD Protocol version 2", DetectResult.Supported); } } else if (info.RsvdSupport == DetectResult.UnSupported) { AddResultItem(ref this.rsvdItems, "The server doesn't support RSVD", info.RsvdSupport); } else { AddResultItem(ref this.rsvdItems, "Detection failed", this.info.RsvdSupport); } }
public void CheckUsernamePassword(DetectionInfo info) { using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; Guid clientGuid; NEGOTIATE_Response negotiateResp; bool encryptionRequired; UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResp, out encryptionRequired); try { Packet_Header header; LOGOFF_Response logoffResponse; client.LogOff( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, out header, out logoffResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("LOGOFF", header.Status); } } catch (Exception e) { // Swallow all exceptions when cleaning up. logWriter.AddLog(LogLevel.Information, "Exception in Cleanup: " + e.Message); } } }
public Smb2Info FetchSmb2Info(DetectionInfo info) { Smb2Info smb2Info = new Smb2Info(); using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { logWriter.AddLog(LogLevel.Information, "Client connects to server"); smb2Client.ConnectOverTCP(SUTIpAddress); DialectRevision selectedDialect; byte[] gssToken; Packet_Header responseHeader; NEGOTIATE_Response responsePayload; logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( smb2Client, 0, 1, Packet_Header_Flags_Values.NONE, 1, info.requestDialect, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, Guid.NewGuid(), out selectedDialect, out gssToken, out responseHeader, out responsePayload); if (responseHeader.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", responseHeader.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(responseHeader.Status))); } smb2Info.MaxSupportedDialectRevision = responsePayload.DialectRevision; smb2Info.SupportedCapabilities = (Capabilities_Values)responsePayload.Capabilities; smb2Info.SelectedCipherID = smb2Client.SelectedCipherID; smb2Info.IsRequireMessageSigning = responsePayload.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); return smb2Info; } }
public ShareInfo[] FetchShareInfo(DetectionInfo info) { string[] shareList = null; try { shareList = ServerHelper.EnumShares(SUTName, Credential.AccountName, Credential.DomainName, Credential.Password); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, string.Format("EnumShares failed, reason: {0}", ex.Message)); } if (shareList == null) { // EnumShares may fail because the SUT doesn't support SRVS. // Try to connect the default share "SMBBasic" using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; try { ConnectToShare(defautBasicShare, info, client, out messageId, out sessionId, out treeId); shareList = new string[] { defautBasicShare }; } catch { // Show error to user. logWriter.AddLog(LogLevel.Error, "Did not find shares on SUT. Please check share setting and SUT password."); } } } return RetrieveShareProperties(shareList, info); }
public void FetchPlatformAndUseraccounts(ref DetectionInfo info) { // Set the default values info.platform = Platform.NonWindows; info.nonadminUserAccounts = new List<string>(); try { FetchPlatformInfo(ref info); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, "Detect platform failure. Reason: " + ex.Message); } try { FetchNonAdminUseraccountInfo(ref info); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, "Detect useraccounts failure. Reason: " + ex.Message); } }
public NetworkInfo FetchLocalNetworkInfo(DetectionInfo info) { LogIPConfig(); //Get the network information with SUTIpList NetworkInfo networkInfo = info.networkInfo; #region Get Local IP List networkInfo.LocalIpList = new List<IPAddress>(); foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces()) { if (adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet || adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || adapter.NetworkInterfaceType == NetworkInterfaceType.GigabitEthernet) { foreach (var ip in adapter.GetIPProperties().UnicastAddresses) { if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { try { smb2Client.ConnectOverTCP(SUTIpAddress, ip.Address); networkInfo.LocalIpList.Add(ip.Address); } catch (Exception ex) { logWriter.AddLog( LogLevel.Information, string.Format("Connect from client IP {0} to SUT IP {1} failed, reason: {2}", ip.Address, SUTIpAddress, ex.Message)); } } } } } } if (networkInfo.LocalIpList.Count == 0) { logWriter.AddLog(LogLevel.Error, "No available local IP address"); } #endregion return networkInfo; }
public DetectResult[] CheckIOCTL_IntegrityInfo(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL IntegrityInfo ====="); logWriter.AddLog(LogLevel.Information, "Share name: " + sharename); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); #region Create Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; CREATE_Response createResponse; Packet_Header header; logWriter.AddLog(LogLevel.Information, "Client opens a file"); client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region IOCTL GET IntegrityInfo logWriter.AddLog(LogLevel.Information, "Client sends IOCTL request with FSCTL_GET_INTEGRITY_INFORMATION."); FSCTL_GET_INTEGRITY_INFO_OUTPUT getIntegrityInfo; IOCTL_Response ioCtlResponse; byte[] buffer = new byte[1024]; byte[] respInput = new byte[1024]; byte[] respOutput = new byte[1024]; client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_GET_INTEGRITY_INFORMATION, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); DetectResult[] result = { DetectResult.UnSupported, DetectResult.UnSupported }; if (header.Status != Smb2Status.STATUS_SUCCESS) { // Get_Integrity is not supported // Set_Integrity cannot be tested. LogFailedStatus("GET_INTEGRITY_INFORMATION", header.Status); return result; } getIntegrityInfo = TypeMarshal.ToStruct<FSCTL_GET_INTEGRITY_INFO_OUTPUT>(respOutput); result[0] = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_GET_INTEGRITY_INFORMATION is supported"); #endregion #region IOCTL SET IntegrityInfo logWriter.AddLog(LogLevel.Information, "Client sends IOCTL request with FSCTL_SET_INTEGRITY_INFORMATION after changed the value of the following fields in FSCTL_SET_INTEGRIY_INFO_INPUT: " + "ChecksumAlgorithm, Flags, Reserved."); FSCTL_SET_INTEGRIY_INFO_INPUT setIntegrityInfo; setIntegrityInfo.ChecksumAlgorithm = FSCTL_SET_INTEGRITY_INFO_INPUT_CHECKSUMALGORITHM.CHECKSUM_TYPE_CRC64; setIntegrityInfo.Flags = FSCTL_SET_INTEGRITY_INFO_INPUT_FLAGS.FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF; setIntegrityInfo.Reserved = FSCTL_SET_INTEGRITY_INFO_INPUT_RESERVED.V1; buffer = TypeMarshal.ToBytes<FSCTL_SET_INTEGRIY_INFO_INPUT>(setIntegrityInfo); respInput = new byte[1024]; respOutput = new byte[1024]; client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_SET_INTEGRITY_INFORMATION, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); #endregion if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SET_INTEGRITY_INFORMATION", header.Status); } else { #region IOCTL GET IntegrityInfo buffer = new byte[1024]; respInput = new byte[1024]; respOutput = new byte[1024]; logWriter.AddLog(LogLevel.Information, "Client sends second FSCTL_GET_INTEGRITY_INFORMATION."); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_GET_INTEGRITY_INFORMATION, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); getIntegrityInfo = TypeMarshal.ToStruct<FSCTL_GET_INTEGRITY_INFO_OUTPUT>(respOutput); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Second GET_INTEGRITY_INFORMATION", header.Status); } if ((ushort)setIntegrityInfo.ChecksumAlgorithm != (ushort)getIntegrityInfo.ChecksumAlgorithm) { logWriter.AddLog(LogLevel.Information, "Failed to set the ChecksumAlgorithm field to value " + setIntegrityInfo.ChecksumAlgorithm); } result[1] = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_SET_INTEGRITY_INFORMATION is supported"); #endregion } #region Close CLOSE_Response closeResponse; client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); } #endregion #region Tree Disconnect TREE_DISCONNECT_Response treeDisconnectResponse; client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
private ShareInfo[] RetrieveShareProperties(string[] shareList, DetectionInfo info) { List<ShareInfo> shareInfoList = new List<ShareInfo>(); string uncShare; foreach (var share in shareList) { using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { Packet_Header header; ulong messageId; ulong sessionId; Guid clientGuid; uncShare = string.Format(@"\\{0}\{1}", SUTName, share); try { NEGOTIATE_Response negotiateResp; bool encryptionRequired = false; UserLogon(info, smb2Client, out messageId, out sessionId, out clientGuid, out negotiateResp, out encryptionRequired); uint treeId; TREE_CONNECT_Response treeConnectResp; if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted. { smb2Client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired); } logWriter.AddLog(LogLevel.Information, string.Format("Client sends TreeConnect to {0} to retrieve the share properties.", uncShare)); smb2Client.TreeConnect( 1, 1, (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncShare, out treeId, out header, out treeConnectResp); if (header.Status != Smb2Status.STATUS_SUCCESS) continue; // When dialect is 3.11, for the messages other than TreeConnect, signing is not required. // Set it back to the configuration of the SUT. if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) { smb2Client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired); } ShareInfo shareInfo = new ShareInfo(); shareInfo.ShareName = share; shareInfo.ShareCapabilities = treeConnectResp.Capabilities; shareInfo.ShareFlags = treeConnectResp.ShareFlags; shareInfo.ShareType = treeConnectResp.ShareType; shareInfoList.Add(shareInfo); TREE_DISCONNECT_Response treeDisconnectResponse; smb2Client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); LOGOFF_Response logoffResponse; smb2Client.LogOff(1, 1, Packet_Header_Flags_Values.NONE, messageId++, sessionId, out header, out logoffResponse); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, string.Format("Exception when retrieving share properties: " + ex.Message)); // Swallow all exceptions when cleaning up. } } } return shareInfoList.ToArray(); }
private void FetchNonAdminUseraccountInfo(ref DetectionInfo info) { // If SUT is in Domain, get the Domain nonadmin useraccounts // If SUT is in WORKGROUP, get the SUT nonadmin useraccounts ManagementObjectCollection resultCollection = QueryWmiObject(info.domainName, "SELECT * FROM Win32_UserAccount"); foreach (ManagementObject result in resultCollection) { #region Filter out administrator accounts according to SID string accountSID = result["SID"].ToString(); if (accountSID.StartsWith("S-1-5-21")) { // System administrator if (accountSID.EndsWith("500")) continue; // Domain administrator if (accountSID.EndsWith("512")) continue; // Schema administrator if (accountSID.EndsWith("518")) continue; // Enterprise Administrator if (accountSID.EndsWith("519")) continue; // Group Policy Creator Owners if (accountSID.EndsWith("520")) continue; } // Administrators (built-in group) if (accountSID.StartsWith("S-1-5-32") && accountSID.EndsWith("544")) continue; #endregion // TODO: Further investigation required. // Find a better to filter out admin accounts // Or check SID to confirm that no admin account omitted string userAccount = result["Name"].ToString(); // Put the "nonadmin" user name to the first as the default value if (userAccount.ToLower() == "nonadmin") { info.nonadminUserAccounts.Insert(0, userAccount); continue; } // If get the "guest" use name, set it in the result // Keep the "guest" in the nonadmin useraccounts if (userAccount.ToLower() == "guest") info.guestUserAccount = userAccount; info.nonadminUserAccounts.Add(userAccount); } logWriter.AddLog(LogLevel.Information, "Nonadmin Useraccounts: "); foreach (string account in info.nonadminUserAccounts) { logWriter.AddLog(LogLevel.Information, "\t" + account); } }
/// <summary> /// To check the create contexts. /// </summary> /// <param name="sharename">The share name</param> /// <param name="info">The detection information</param> /// <returns>Returns a DetectResult instance</returns> public DetectResult CheckCreateContexts_AppInstanceId(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting create context AppInstanceId ====="); using (Smb2Client clientForInitialOpen = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds)), clientForReOpen = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageIdInitial; ulong sessionIdInitial; uint treeIdInitial; logWriter.AddLog(LogLevel.Information, "Start first client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); ConnectToShare(sharename, info, clientForInitialOpen, out messageIdInitial, out sessionIdInitial, out treeIdInitial); #region client 1 connect to server Guid appInstanceId = Guid.NewGuid(); FILEID fileIdInitial; CREATE_Response createResponse; Packet_Header header; Smb2CreateContextResponse[] serverCreateContexts; string fileName = "AppInstanceId_" + Guid.NewGuid() + ".txt"; logWriter.AddLog(LogLevel.Information, "The first client opens a file with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 and SMB2_CREATE_APP_INSTANCE_ID."); uint status = clientForInitialOpen.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageIdInitial++, sessionIdInitial, treeIdInitial, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid() }, new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId } }, out fileIdInitial, out serverCreateContexts, out header, out createResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create", header.Status); return(DetectResult.UnSupported); } #endregion #region client 2 connect to server ulong messageId; ulong sessionId; uint treeId; logWriter.AddLog(LogLevel.Information, "Start second client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); ConnectToShare(sharename, info, clientForReOpen, out messageId, out sessionId, out treeId); try { // Test if a second client can close the previous open. FILEID fileId; logWriter.AddLog(LogLevel.Information, "The second client opens the same file with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 and same AppInstanceId."); status = clientForReOpen.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid() }, new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId } }, out fileId, out serverCreateContexts, out header, out createResponse, 0); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, "Create failed, reason: " + ex.Message); return(DetectResult.UnSupported); } if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create", header.Status); return(DetectResult.UnSupported); } #endregion // Write data using the first client // If AppInstanceId is supported, then the open should be closed. WRITE_Response writeResponse; logWriter.AddLog(LogLevel.Information, "The first client writes to the file to check if the open is closed"); status = clientForInitialOpen.Write( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageIdInitial++, sessionIdInitial, treeIdInitial, 0, fileIdInitial, Channel_Values.CHANNEL_NONE, WRITE_Request_Flags_Values.None, new byte[0], Encoding.ASCII.GetBytes("AppInstanceId"), out header, out writeResponse, 0); DetectResult result = DetectResult.UnSupported; if (status == Smb2Status.STATUS_FILE_CLOSED) { result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "The open is closed. So Create context AppInstanceId is supported"); } else { logWriter.AddLog(LogLevel.Information, "The open is not closed. So Create context AppInstanceId is not supported"); } return(result); } }
public DetectResult CheckCreateContexts_HandleV2LeaseV2(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting create context HandleV2 with LeaseV2 ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; Guid leaseKey = Guid.NewGuid(); Guid createGuid = Guid.NewGuid(); CREATE_Response createResponse; Packet_Header header; string fileName = "DurableHandleV2LeaseV2_" + Guid.NewGuid() + ".txt"; logWriter.AddLog(LogLevel.Information, "Client opens file with a durable handle v2 and lease v2 context"); client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Timeout = 0, }, new Smb2CreateRequestLeaseV2 { LeaseKey = Guid.NewGuid(), LeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING, } }, out fileId, out serverCreateContexts, out header, out createResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create with lease v2", header.Status); return(DetectResult.UnSupported); } if (serverCreateContexts != null) { foreach (Smb2CreateContextResponse ctx in serverCreateContexts) { if (ctx is Smb2CreateDurableHandleResponseV2) { logWriter.AddLog(LogLevel.Information, "Create context HandleV2 with LeaseV2 is supported"); return(DetectResult.Supported); } } } logWriter.AddLog(LogLevel.Information, "The returned Create response doesn't contain durable handle v2 response. So Create context HandleV2 with LeaseV2 is not supported"); return(DetectResult.UnSupported); } }
public DetectResult CheckCreateContexts_HandleV1BatchOplock(string sharename, DialectRevision smb2Dialect, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting create context HandleV1 with Batch oplock ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); Packet_Header header; #region Create FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts = null; string fileName = "DurableHandleV1BatchOplock_" + Guid.NewGuid() + ".txt"; CREATE_Response createResponse; logWriter.AddLog(LogLevel.Information, "Client opens file with a durable handle v1 and batch oplock"); uint status = client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequest { DurableRequest = Guid.Empty, }, }, out fileId, out serverCreateContexts, out header, out createResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create durable handle v1 with batch oplock", header.Status); return(DetectResult.UnSupported); } #endregion if (serverCreateContexts != null) { foreach (Smb2CreateContextResponse ctx in serverCreateContexts) { if (ctx is Smb2CreateDurableHandleResponse) { logWriter.AddLog(LogLevel.Information, "Create context HandleV1 with Batch oplock is supported"); return(DetectResult.Supported); } } } logWriter.AddLog(LogLevel.Information, "The returned Create response doesn't contain handle v1 context. So Create context HandleV1 with Batch oplock is not supported"); return(DetectResult.UnSupported); } }
public DetectResult CheckIOCTL_ValidateNegotiateInfo(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL ValidateNegotiateInfo ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; NEGOTIATE_Response negotiateResponse; Guid clientGuid; bool encryptionRequired = false; UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResponse, out encryptionRequired); #region TreeConnect TREE_CONNECT_Response treeConnectResp; string uncShare = string.Format(@"\\{0}\{1}", SUTName, sharename); Packet_Header header; logWriter.AddLog(LogLevel.Information, "Client sends TreeConnect to server"); if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted. { client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired); } client.TreeConnect( 1, 1, (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncShare, out treeId, out header, out treeConnectResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREECONNECT", header.Status); throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status)); } // When dialect is 3.11, for the messages other than TreeConnect, signing is not required. // Set it back to the configuration of the SUT. if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) { client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired); } #endregion TREE_DISCONNECT_Response treeDisconnectResponse; #region IOCTL FSCTL_VALIDATE_NEGOTIATE_INFO VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq; validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION; validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; validateNegotiateInfoReq.DialectCount = (ushort)(info.requestDialect.Length); validateNegotiateInfoReq.Dialects = info.requestDialect; byte[] inputBuffer = TypeMarshal.ToBytes<VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq); byte[] outputBuffer; VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResp; IOCTL_Response ioCtlResponse; byte[] respInput = new byte[1024]; FILEID ioCtlFileId = new FILEID(); ioCtlFileId.Persistent = 0xFFFFFFFFFFFFFFFF; ioCtlFileId.Volatile = 0xFFFFFFFFFFFFFFFF; logWriter.AddLog(LogLevel.Information, "Client sends FSCTL_VALIDATE_NEGOTIATE_INFO to server"); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO, ioCtlFileId, 0, inputBuffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out outputBuffer, out header, out ioCtlResponse, 0); DetectResult result = DetectResult.UnSupported; if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Validate Negotiate Information", header.Status); } else { validateNegotiateInfoResp = TypeMarshal.ToStruct<VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer); if ((Capabilities_Values)negotiateResponse.Capabilities != validateNegotiateInfoResp.Capabilities) { logWriter.AddLog(LogLevel.Information, "Capabilities returned in ValidateNegotiateInfo response doesn't eaqual to server capabilities in original Negotiate response"); } if (negotiateResponse.ServerGuid != validateNegotiateInfoResp.Guid) { logWriter.AddLog(LogLevel.Information, "ServerGuid returned in ValidateNegotiateInfo response doesn't eaqual to server ServerGuid in original Negotiate response"); } if ((SecurityMode_Values)negotiateResponse.SecurityMode != validateNegotiateInfoResp.SecurityMode) { logWriter.AddLog(LogLevel.Information, "SecurityMode returned in ValidateNegotiateInfo response doesn't eaqual to server SecurityMode in original Negotiate response"); } if (negotiateResponse.DialectRevision != validateNegotiateInfoResp.Dialect) { logWriter.AddLog(LogLevel.Information, "Validation failed for dialect supported on server"); } result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_VALIDATE_NEGOTIATE_INFO is supported"); } #endregion #region Tree Disconnect client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
public DetectResult CheckIOCTL_ResilientHandle(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL ResilientHandle ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); #region Create Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; CREATE_Response createResponse; Packet_Header header; logWriter.AddLog(LogLevel.Information, "Client opens a file"); client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region IOCTL ResilientHandle IOCTL_Response ioCtlResponse; byte[] inputInResponse; byte[] outputInResponse; uint inputCount = (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)); NETWORK_RESILIENCY_Request resilientRequest = new NETWORK_RESILIENCY_Request() { Timeout = 120 }; byte[] resiliencyRequestBytes = TypeMarshal.ToBytes<NETWORK_RESILIENCY_Request>(resilientRequest); byte[] buffer = resiliencyRequestBytes; if (inputCount < resiliencyRequestBytes.Length) { buffer = new byte[inputCount]; Array.Copy(resiliencyRequestBytes, buffer, buffer.Length); } else if (inputCount > resiliencyRequestBytes.Length) { buffer = new byte[inputCount]; Array.Copy(resiliencyRequestBytes, buffer, resiliencyRequestBytes.Length); } logWriter.AddLog(LogLevel.Information, "Client sends an IOCTL FSCTL_LMR_REQUEST_RESILLIENCY request."); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out inputInResponse, out outputInResponse, out header, out ioCtlResponse, 0); DetectResult result = DetectResult.UnSupported; if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("FSCTL_LMR_REQUEST_RESILIENCY", header.Status); } else { result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_LMR_REQUEST_RESILIENCY is supported"); } #endregion #region Close CLOSE_Response closeResponse; client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); } #endregion #region Tree Disconnect TREE_DISCONNECT_Response treeDisconnectResponse; client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
public void UserLogon( DetectionInfo info, Smb2Client client, out ulong messageId, out ulong sessionId, out Guid clientGuid, out NEGOTIATE_Response negotiateResp, out bool encryptionRequired) { messageId = 1; sessionId = 0; logWriter.AddLog(LogLevel.Information, "Client connects to server"); client.ConnectOverTCP(SUTIpAddress); #region Negotiate DialectRevision selectedDialect; byte[] gssToken; Packet_Header header; clientGuid = Guid.NewGuid(); logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( client, 1, 1, Packet_Header_Flags_Values.NONE, messageId++, info.requestDialect, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION, clientGuid, out selectedDialect, out gssToken, out header, out negotiateResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", header.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(header.Status))); } #endregion #region Session Setup SESSION_SETUP_Response sessionSetupResp; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( SecurityPackageType, Credential, Smb2Utility.GetCifsServicePrincipalName(SUTName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); // Server GSS token is used only for Negotiate authentication when enabled if (SecurityPackageType == SecurityPackageType.Negotiate) sspiClientGss.Initialize(gssToken); else sspiClientGss.Initialize(null); do { logWriter.AddLog(LogLevel.Information, "Client sends SessionSetup to server"); client.SessionSetup( 1, 64, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out gssToken, out header, out sessionSetupResp); if ((header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || header.Status == Smb2Status.STATUS_SUCCESS) && gssToken != null && gssToken.Length > 0) { sspiClientGss.Initialize(gssToken); } } while (header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SESSIONSETUP", header.Status); throw new Exception(string.Format("SESSIONSETUP failed with {0}", Smb2Status.GetStatusCode(header.Status))); } byte[] sessionKey; sessionKey = sspiClientGss.SessionKey; encryptionRequired = sessionSetupResp.SessionFlags == SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA; client.GenerateCryptoKeys( sessionId, sessionKey, info.smb2Info.IsRequireMessageSigning, // Enable signing according to the configuration of SUT encryptionRequired, null, false); #endregion }
public DetectResult[] CheckIOCTL_CopyOffload(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL CopyOffload ====="); #region Initialization int contentLength = 32; string content = Smb2Utility.CreateRandomString(contentLength); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); #endregion #region Create logWriter.AddLog(LogLevel.Information, "Client creates a file with specified length as for offload copy."); Smb2CreateContextResponse[] serverCreateContexts; FILEID fileIdSrc; CREATE_Response createResponse; Packet_Header header; client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileIdSrc, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Write WRITE_Response writeResponse; client.Write( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, 0, fileIdSrc, Channel_Values.CHANNEL_NONE, WRITE_Request_Flags_Values.None, new byte[0], Encoding.ASCII.GetBytes(content), out header, out writeResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("WRITE", header.Status); throw new Exception("WRITE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Flush FLUSH_Response flushResponse; client.Flush( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileIdSrc, out header, out flushResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("FLUSH", header.Status); throw new Exception("FLUSH failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region IOCTL OFFLOAD_READ logWriter.AddLog(LogLevel.Information, "Client sends IOCTL request with FSCTL_OFFLOAD_READ to ask server to generate the token of the content for offload copy."); STORAGE_OFFLOAD_TOKEN token; ulong fileOffsetToRead = 0; //FileOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong copyLengthToRead = (ulong)contentLength / 2 * 1024; //CopyLength should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong transferLength; // Request hardware to generate a token that represents a range of file to be copied FSCTL_OFFLOAD_READ_INPUT offloadReadInput = new FSCTL_OFFLOAD_READ_INPUT(); offloadReadInput.Size = 32; offloadReadInput.FileOffset = fileOffsetToRead; offloadReadInput.CopyLength = copyLengthToRead; byte[] requestInputOffloadRead = TypeMarshal.ToBytes(offloadReadInput); byte[] responseInput; byte[] responseOutput; IOCTL_Response ioCtlResponse; client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_OFFLOAD_READ, fileIdSrc, 0, requestInputOffloadRead, 32000, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out responseInput, out responseOutput, out header, out ioCtlResponse); #endregion DetectResult[] result = { DetectResult.UnSupported, DetectResult.UnSupported }; if (Smb2Status.STATUS_SUCCESS != header.Status) { LogFailedStatus("FSCTL_OFFLOAD_READ", header.Status); } else { result[0] = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_OFFLOAD_READ is supported"); #region IOCTL OFFLOAD_WRITE logWriter.AddLog(LogLevel.Information, "Client creates another file as the destination of offload copy."); // Create another file as the destination of offload copy. FILEID fileIdDes; client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileIdDes, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } // Bug 8016334 // The destination file of CopyOffload Write should not be zero, it should be at least 512 bytes, which is the sector size. client.Write( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, 0, fileIdDes, Channel_Values.CHANNEL_NONE, WRITE_Request_Flags_Values.None, new byte[0], Smb2Utility.CreateRandomByteArray(512), out header, out writeResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("WRITE", header.Status); throw new Exception("WRITE failed with " + Smb2Status.GetStatusCode(header.Status)); } client.Flush( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileIdDes, out header, out flushResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("FLUSH", header.Status); throw new Exception("FLUSH failed with " + Smb2Status.GetStatusCode(header.Status)); } if (responseOutput != null) { var offloadReadOutput = TypeMarshal.ToStruct<FSCTL_OFFLOAD_READ_OUTPUT>(responseOutput); transferLength = offloadReadOutput.TransferLength; token = offloadReadOutput.Token; } else { transferLength = 0; token = new STORAGE_OFFLOAD_TOKEN(); } logWriter.AddLog(LogLevel.Information, "Client sends IOCTL request with FSCTL_OFFLOAD_WRITE to ask server to copy the content from source to destination."); ulong fileOffsetToWrite = (ulong)contentLength / 2 * 1024; //FileOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong copyLengthToWrite = transferLength; //CopyLength should be aligned to logical sector boundary on the volume, e.g. 512 bytes ulong transferOffset = 0; //TransferOffset should be aligned to logical sector boundary on the volume, e.g. 512 bytes FSCTL_OFFLOAD_WRITE_INPUT offloadWriteInput = new FSCTL_OFFLOAD_WRITE_INPUT(); offloadWriteInput.Size = 544; offloadWriteInput.FileOffset = fileOffsetToWrite; offloadWriteInput.CopyLength = copyLengthToWrite; offloadWriteInput.TransferOffset = transferOffset; offloadWriteInput.Token = token; byte[] requestInputOffloadWrite = TypeMarshal.ToBytes(offloadWriteInput); // Client sends IOCTL request with FSCTL_OFFLOAD_WRITE to ask server to copy the content from source to destination. client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_OFFLOAD_WRITE, fileIdDes, 0, requestInputOffloadWrite, 32000, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out responseInput, out responseOutput, out header, out ioCtlResponse); if (Smb2Status.STATUS_SUCCESS == header.Status) { result[1] = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_OFFLOAD_WRITE is supported"); } else { LogFailedStatus("FSCTL_OFFLOAD_WRITE", header.Status); } #endregion } #region Close CLOSE_Response closeResponse; client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileIdSrc, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); } #endregion #region Tree Disconnect TREE_DISCONNECT_Response treeDisconnectResponse; client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
/// <summary> /// Negotiate, SessionSetup, TreeConnect /// </summary> /// <returns>Return true for success, false for failure</returns> private void ConnectToShare( string sharename, DetectionInfo info, Smb2Client client, out ulong messageId, out ulong sessionId, out uint treeId) { Packet_Header header; Guid clientGuid; NEGOTIATE_Response negotiateResp; bool encryptionRequired = false; UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResp, out encryptionRequired); #region TreeConnect TREE_CONNECT_Response treeConnectResp; string uncSharePath = Smb2Utility.GetUncPath(info.targetSUT, sharename); logWriter.AddLog(LogLevel.Information, "Client sends TreeConnect to server"); if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted. { client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired); } client.TreeConnect( 1, 1, (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncSharePath, out treeId, out header, out treeConnectResp); // When dialect is 3.11, for the messages other than TreeConnect, signing is not required. // Set it back to the configuration of the SUT. if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) { client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired); } if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREECONNECT", header.Status); throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion }
public DetectResult CheckCreateContexts_LeaseV2(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting create context LeaseV2 ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); Packet_Header header; #region Create FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts = null; string fileName = "LeaseV2_" + Guid.NewGuid() + ".txt"; CREATE_Response createResponse; logWriter.AddLog(LogLevel.Information, "Client opens file with a leaseV2 context"); client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateRequestLeaseV2 { LeaseKey = Guid.NewGuid(), LeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING, } }, out fileId, out serverCreateContexts, out header, out createResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create with lease v2", header.Status); return DetectResult.UnSupported; } #endregion if (serverCreateContexts != null) { foreach (Smb2CreateContextResponse ctx in serverCreateContexts) { if (ctx is Smb2CreateResponseLeaseV2) { logWriter.AddLog(LogLevel.Information, "Create context LeaseV2 is supported"); return DetectResult.Supported; } } } logWriter.AddLog(LogLevel.Information, "The returned Create response doesn't contain lease v2 context. So Create context LeaseV2 is not supported"); return DetectResult.UnSupported; } }
private void FetchPlatformInfo(ref DetectionInfo info) { ManagementObjectCollection resultCollection = QueryWmiObject(info.targetSUT, "SELECT * FROM Win32_OperatingSystem"); foreach (ManagementObject result in resultCollection) { info.platform = ConvertPlatform(result["Version"].ToString()); logWriter.AddLog(LogLevel.Information, "Platform: " + info.platform); break; } }
/// <summary> /// To check the create contexts. /// </summary> /// <param name="sharename">The share name</param> /// <param name="info">The detection information</param> /// <returns>Returns a DetectResult instance</returns> public DetectResult CheckCreateContexts_AppInstanceId(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting create context AppInstanceId ====="); using (Smb2Client clientForInitialOpen = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds)), clientForReOpen = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageIdInitial; ulong sessionIdInitial; uint treeIdInitial; logWriter.AddLog(LogLevel.Information, "Start first client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); ConnectToShare(sharename, info, clientForInitialOpen, out messageIdInitial, out sessionIdInitial, out treeIdInitial); #region client 1 connect to server Guid appInstanceId = Guid.NewGuid(); FILEID fileIdInitial; CREATE_Response createResponse; Packet_Header header; Smb2CreateContextResponse[] serverCreateContexts; string fileName = "AppInstanceId_" + Guid.NewGuid() + ".txt"; logWriter.AddLog(LogLevel.Information, "The first client opens a file with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 and SMB2_CREATE_APP_INSTANCE_ID."); uint status = clientForInitialOpen.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageIdInitial++, sessionIdInitial, treeIdInitial, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid() }, new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId } }, out fileIdInitial, out serverCreateContexts, out header, out createResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create", header.Status); return DetectResult.UnSupported; } #endregion #region client 2 connect to server ulong messageId; ulong sessionId; uint treeId; logWriter.AddLog(LogLevel.Information, "Start second client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); ConnectToShare(sharename, info, clientForReOpen, out messageId, out sessionId, out treeId); try { // Test if a second client can close the previous open. FILEID fileId; logWriter.AddLog(LogLevel.Information, "The second client opens the same file with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 and same AppInstanceId."); status = clientForReOpen.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid() }, new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId } }, out fileId, out serverCreateContexts, out header, out createResponse, 0); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, "Create failed, reason: " + ex.Message); return DetectResult.UnSupported; } if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create", header.Status); return DetectResult.UnSupported; } #endregion // Write data using the first client // If AppInstanceId is supported, then the open should be closed. WRITE_Response writeResponse; logWriter.AddLog(LogLevel.Information, "The first client writes to the file to check if the open is closed"); status = clientForInitialOpen.Write( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageIdInitial++, sessionIdInitial, treeIdInitial, 0, fileIdInitial, Channel_Values.CHANNEL_NONE, WRITE_Request_Flags_Values.None, new byte[0], Encoding.ASCII.GetBytes("AppInstanceId"), out header, out writeResponse, 0); DetectResult result = DetectResult.UnSupported; if (status == Smb2Status.STATUS_FILE_CLOSED) { result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "The open is closed. So Create context AppInstanceId is supported"); } else { logWriter.AddLog(LogLevel.Information, "The open is not closed. So Create context AppInstanceId is not supported"); } return result; } }
public DetectResult CheckIOCTL_ResilientHandle(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL ResilientHandle ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); #region Create Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; CREATE_Response createResponse; Packet_Header header; logWriter.AddLog(LogLevel.Information, "Client opens a file"); client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region IOCTL ResilientHandle IOCTL_Response ioCtlResponse; byte[] inputInResponse; byte[] outputInResponse; uint inputCount = (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)); NETWORK_RESILIENCY_Request resilientRequest = new NETWORK_RESILIENCY_Request() { Timeout = 120 }; byte[] resiliencyRequestBytes = TypeMarshal.ToBytes <NETWORK_RESILIENCY_Request>(resilientRequest); byte[] buffer = resiliencyRequestBytes; if (inputCount < resiliencyRequestBytes.Length) { buffer = new byte[inputCount]; Array.Copy(resiliencyRequestBytes, buffer, buffer.Length); } else if (inputCount > resiliencyRequestBytes.Length) { buffer = new byte[inputCount]; Array.Copy(resiliencyRequestBytes, buffer, resiliencyRequestBytes.Length); } logWriter.AddLog(LogLevel.Information, "Client sends an IOCTL FSCTL_LMR_REQUEST_RESILLIENCY request."); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out inputInResponse, out outputInResponse, out header, out ioCtlResponse, 0); DetectResult result = DetectResult.UnSupported; if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("FSCTL_LMR_REQUEST_RESILIENCY", header.Status); } else { result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_LMR_REQUEST_RESILIENCY is supported"); } #endregion #region Close CLOSE_Response closeResponse; client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); } #endregion #region Tree Disconnect TREE_DISCONNECT_Response treeDisconnectResponse; client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return(result); } }
public DetectResult CheckIOCTL_FileLevelTrim(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting FSCTL_FILE_LEVEL_TRIM ====="); string content = Smb2Utility.CreateRandomString(32); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); #region Create logWriter.AddLog(LogLevel.Information, "Client creates a file to prepare for the trimming"); Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; CREATE_Response createResponse; Packet_Header header; client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Write WRITE_Response writeResponse; client.Write( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, 0, fileId, Channel_Values.CHANNEL_NONE, WRITE_Request_Flags_Values.None, new byte[0], Encoding.ASCII.GetBytes(content), out header, out writeResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("WRITE", header.Status); throw new Exception("WRITE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Close CLOSE_Response closeResponse; client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); throw new Exception("CLOSE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Create client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("Second CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region IOCTL FileLevelTrim FSCTL_FILE_LEVEL_TRIM_RANGE fileLevelTrimRange; Random random = new Random(); uint offset = (uint)random.Next(0, 32 * 1024); uint length = (uint)random.Next(0, (int)(32 * 1024 - offset)); fileLevelTrimRange.Offset = offset; fileLevelTrimRange.Length = length; FSCTL_FILE_LEVEL_TRIM_INPUT fileLevelTrimInput; fileLevelTrimInput.Key = 0; fileLevelTrimInput.NumRanges = 1; fileLevelTrimInput.Ranges = new FSCTL_FILE_LEVEL_TRIM_RANGE[] { fileLevelTrimRange }; byte[] buffer = TypeMarshal.ToBytes<FSCTL_FILE_LEVEL_TRIM_INPUT>(fileLevelTrimInput); byte[] respOutput; IOCTL_Response ioCtlResponse; byte[] respInput = new byte[1024]; logWriter.AddLog(LogLevel.Information, "Client sends FSCTL_FILE_LEVEL_TRIM to server"); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_FILE_LEVEL_TRIM, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); #endregion DetectResult result = DetectResult.UnSupported; if (header.Status == Smb2Status.STATUS_SUCCESS) { result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_FILE_LEVEL_TRIM is supported"); } else { LogFailedStatus("FSCTL_FILE_LEVEL_TRIM", header.Status); } #region Close client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); } #endregion #region Tree Disconnect TREE_DISCONNECT_Response treeDisconnectResponse; client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
public void UserLogon( DetectionInfo info, Smb2Client client, out ulong messageId, out ulong sessionId, out Guid clientGuid, out NEGOTIATE_Response negotiateResp, out bool encryptionRequired) { messageId = 1; sessionId = 0; logWriter.AddLog(LogLevel.Information, "Client connects to server"); client.ConnectOverTCP(SUTIpAddress); #region Negotiate DialectRevision selectedDialect; byte[] gssToken; Packet_Header header; clientGuid = Guid.NewGuid(); logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( client, 1, 1, Packet_Header_Flags_Values.NONE, messageId++, info.requestDialect, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION, clientGuid, out selectedDialect, out gssToken, out header, out negotiateResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", header.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(header.Status))); } #endregion #region Session Setup SESSION_SETUP_Response sessionSetupResp; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( SecurityPackageType, Credential, Smb2Utility.GetCifsServicePrincipalName(SUTName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); // Server GSS token is used only for Negotiate authentication when enabled if (SecurityPackageType == SecurityPackageType.Negotiate) { sspiClientGss.Initialize(gssToken); } else { sspiClientGss.Initialize(null); } do { logWriter.AddLog(LogLevel.Information, "Client sends SessionSetup to server"); client.SessionSetup( 1, 64, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out gssToken, out header, out sessionSetupResp); if ((header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || header.Status == Smb2Status.STATUS_SUCCESS) && gssToken != null && gssToken.Length > 0) { sspiClientGss.Initialize(gssToken); } } while (header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SESSIONSETUP", header.Status); throw new Exception(string.Format("SESSIONSETUP failed with {0}", Smb2Status.GetStatusCode(header.Status))); } byte[] sessionKey; sessionKey = sspiClientGss.SessionKey; encryptionRequired = sessionSetupResp.SessionFlags == SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA; client.GenerateCryptoKeys( sessionId, sessionKey, info.smb2Info.IsRequireMessageSigning, // Enable signing according to the configuration of SUT encryptionRequired, null, false); #endregion }
private ShareInfo[] RetrieveShareProperties(string[] shareList, DetectionInfo info) { List <ShareInfo> shareInfoList = new List <ShareInfo>(); string uncShare; foreach (var share in shareList) { using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { Packet_Header header; ulong messageId; ulong sessionId; Guid clientGuid; uncShare = string.Format(@"\\{0}\{1}", SUTName, share); try { NEGOTIATE_Response negotiateResp; bool encryptionRequired = false; UserLogon(info, smb2Client, out messageId, out sessionId, out clientGuid, out negotiateResp, out encryptionRequired); uint treeId; TREE_CONNECT_Response treeConnectResp; if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted. { smb2Client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired); } logWriter.AddLog(LogLevel.Information, string.Format("Client sends TreeConnect to {0} to retrieve the share properties.", uncShare)); smb2Client.TreeConnect( 1, 1, (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncShare, out treeId, out header, out treeConnectResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { continue; } // When dialect is 3.11, for the messages other than TreeConnect, signing is not required. // Set it back to the configuration of the SUT. if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) { smb2Client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired); } ShareInfo shareInfo = new ShareInfo(); shareInfo.ShareName = share; shareInfo.ShareCapabilities = treeConnectResp.Capabilities; shareInfo.ShareFlags = treeConnectResp.ShareFlags; shareInfo.ShareType = treeConnectResp.ShareType; shareInfoList.Add(shareInfo); TREE_DISCONNECT_Response treeDisconnectResponse; smb2Client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); LOGOFF_Response logoffResponse; smb2Client.LogOff(1, 1, Packet_Header_Flags_Values.NONE, messageId++, sessionId, out header, out logoffResponse); } catch (Exception ex) { logWriter.AddLog(LogLevel.Information, string.Format("Exception when retrieving share properties: " + ex.Message)); // Swallow all exceptions when cleaning up. } } } return(shareInfoList.ToArray()); }
private void FetchNonAdminUseraccountInfo(ref DetectionInfo info) { // If SUT is in Domain, get the Domain nonadmin useraccounts // If SUT is in WORKGROUP, get the SUT nonadmin useraccounts ManagementObjectCollection resultCollection = QueryWmiObject(info.domainName, "SELECT * FROM Win32_UserAccount"); foreach (ManagementObject result in resultCollection) { #region Filter out administrator accounts according to SID string accountSID = result["SID"].ToString(); if (accountSID.StartsWith("S-1-5-21")) { // System administrator if (accountSID.EndsWith("500")) { continue; } // Domain administrator if (accountSID.EndsWith("512")) { continue; } // Schema administrator if (accountSID.EndsWith("518")) { continue; } // Enterprise Administrator if (accountSID.EndsWith("519")) { continue; } // Group Policy Creator Owners if (accountSID.EndsWith("520")) { continue; } } // Administrators (built-in group) if (accountSID.StartsWith("S-1-5-32") && accountSID.EndsWith("544")) { continue; } #endregion // TODO: Further investigation required. // Find a better to filter out admin accounts // Or check SID to confirm that no admin account omitted string userAccount = result["Name"].ToString(); // Put the "nonadmin" user name to the first as the default value if (userAccount.ToLower() == "nonadmin") { info.nonadminUserAccounts.Insert(0, userAccount); continue; } // If get the "guest" use name, set it in the result // Keep the "guest" in the nonadmin useraccounts if (userAccount.ToLower() == "guest") { info.guestUserAccount = userAccount; } info.nonadminUserAccounts.Add(userAccount); } logWriter.AddLog(LogLevel.Information, "Nonadmin Useraccounts: "); foreach (string account in info.nonadminUserAccounts) { logWriter.AddLog(LogLevel.Information, "\t" + account); } }
public DetectResult CheckCreateContexts_HandleV2BatchOplock(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting create context HandleV2 with Batch oplock ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; Guid leaseKey = Guid.NewGuid(); Guid createGuid = Guid.NewGuid(); CREATE_Response createResponse; Packet_Header header; string fileName = "DurableHandleV2WithBatchOplock_" + Guid.NewGuid() + ".txt"; logWriter.AddLog(LogLevel.Information, "Client opens file with a durable handle v2 and Batch oplock"); client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileName, AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.NONE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Timeout = 0, } }, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Create durable handle v2 with Batch oplock", header.Status); return DetectResult.UnSupported; } if (serverCreateContexts != null) { foreach (Smb2CreateContextResponse ctx in serverCreateContexts) { if (ctx is Smb2CreateDurableHandleResponseV2) { logWriter.AddLog(LogLevel.Information, "Create context HandleV2 with Batch oplock is supported"); return DetectResult.Supported; } } } logWriter.AddLog(LogLevel.Information, "The returned Create response doesn't contain durable handle v2 response. So Create context HandleV2 with Batch oplock is not supported"); return DetectResult.UnSupported; } }
public DetectResult CheckIOCTL_FileLevelTrim(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting FSCTL_FILE_LEVEL_TRIM ====="); string content = Smb2Utility.CreateRandomString(32); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); #region Create logWriter.AddLog(LogLevel.Information, "Client creates a file to prepare for the trimming"); Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; CREATE_Response createResponse; Packet_Header header; client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Write WRITE_Response writeResponse; client.Write( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, 0, fileId, Channel_Values.CHANNEL_NONE, WRITE_Request_Flags_Values.None, new byte[0], Encoding.ASCII.GetBytes(content), out header, out writeResponse, 0); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("WRITE", header.Status); throw new Exception("WRITE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Close CLOSE_Response closeResponse; client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); throw new Exception("CLOSE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region Create client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("Second CREATE failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region IOCTL FileLevelTrim FSCTL_FILE_LEVEL_TRIM_RANGE fileLevelTrimRange; Random random = new Random(); uint offset = (uint)random.Next(0, 32 * 1024); uint length = (uint)random.Next(0, (int)(32 * 1024 - offset)); fileLevelTrimRange.Offset = offset; fileLevelTrimRange.Length = length; FSCTL_FILE_LEVEL_TRIM_INPUT fileLevelTrimInput; fileLevelTrimInput.Key = 0; fileLevelTrimInput.NumRanges = 1; fileLevelTrimInput.Ranges = new FSCTL_FILE_LEVEL_TRIM_RANGE[] { fileLevelTrimRange }; byte[] buffer = TypeMarshal.ToBytes <FSCTL_FILE_LEVEL_TRIM_INPUT>(fileLevelTrimInput); byte[] respOutput; IOCTL_Response ioCtlResponse; byte[] respInput = new byte[1024]; logWriter.AddLog(LogLevel.Information, "Client sends FSCTL_FILE_LEVEL_TRIM to server"); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_FILE_LEVEL_TRIM, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); #endregion DetectResult result = DetectResult.UnSupported; if (header.Status == Smb2Status.STATUS_SUCCESS) { result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_FILE_LEVEL_TRIM is supported"); } else { LogFailedStatus("FSCTL_FILE_LEVEL_TRIM", header.Status); } #region Close client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); } #endregion #region Tree Disconnect TREE_DISCONNECT_Response treeDisconnectResponse; client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return(result); } }
public DetectResult CheckIOCTL_ValidateNegotiateInfo(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL ValidateNegotiateInfo ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; NEGOTIATE_Response negotiateResponse; Guid clientGuid; bool encryptionRequired = false; UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResponse, out encryptionRequired); #region TreeConnect TREE_CONNECT_Response treeConnectResp; string uncShare = string.Format(@"\\{0}\{1}", SUTName, sharename); Packet_Header header; logWriter.AddLog(LogLevel.Information, "Client sends TreeConnect to server"); if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted. { client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired); } client.TreeConnect( 1, 1, (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncShare, out treeId, out header, out treeConnectResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREECONNECT", header.Status); throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status)); } // When dialect is 3.11, for the messages other than TreeConnect, signing is not required. // Set it back to the configuration of the SUT. if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) { client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired); } #endregion TREE_DISCONNECT_Response treeDisconnectResponse; #region IOCTL FSCTL_VALIDATE_NEGOTIATE_INFO VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq; validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION; validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; validateNegotiateInfoReq.DialectCount = (ushort)(info.requestDialect.Length); validateNegotiateInfoReq.Dialects = info.requestDialect; byte[] inputBuffer = TypeMarshal.ToBytes <VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq); byte[] outputBuffer; VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResp; IOCTL_Response ioCtlResponse; byte[] respInput = new byte[1024]; FILEID ioCtlFileId = new FILEID(); ioCtlFileId.Persistent = 0xFFFFFFFFFFFFFFFF; ioCtlFileId.Volatile = 0xFFFFFFFFFFFFFFFF; logWriter.AddLog(LogLevel.Information, "Client sends FSCTL_VALIDATE_NEGOTIATE_INFO to server"); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO, ioCtlFileId, 0, inputBuffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out outputBuffer, out header, out ioCtlResponse, 0); DetectResult result = DetectResult.UnSupported; if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Validate Negotiate Information", header.Status); } else { validateNegotiateInfoResp = TypeMarshal.ToStruct <VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer); if ((Capabilities_Values)negotiateResponse.Capabilities != validateNegotiateInfoResp.Capabilities) { logWriter.AddLog(LogLevel.Information, "Capabilities returned in ValidateNegotiateInfo response doesn't eaqual to server capabilities in original Negotiate response"); } if (negotiateResponse.ServerGuid != validateNegotiateInfoResp.Guid) { logWriter.AddLog(LogLevel.Information, "ServerGuid returned in ValidateNegotiateInfo response doesn't eaqual to server ServerGuid in original Negotiate response"); } if ((SecurityMode_Values)negotiateResponse.SecurityMode != validateNegotiateInfoResp.SecurityMode) { logWriter.AddLog(LogLevel.Information, "SecurityMode returned in ValidateNegotiateInfo response doesn't eaqual to server SecurityMode in original Negotiate response"); } if (negotiateResponse.DialectRevision != validateNegotiateInfoResp.Dialect) { logWriter.AddLog(LogLevel.Information, "Validation failed for dialect supported on server"); } result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_VALIDATE_NEGOTIATE_INFO is supported"); } #endregion #region Tree Disconnect client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return(result); } }
public DetectResult CheckIOCTL_ValidateNegotiateInfo(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL ValidateNegotiateInfo ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId = 1; ulong sessionId = 0; uint treeId; NEGOTIATE_Response negotiateResponse; Guid clientGuid; bool encryptionRequired = false; DialectRevision[] preferredDialects; logWriter.AddLog(LogLevel.Information, "Client connects to server"); client.ConnectOverTCP(SUTIpAddress); if (info.CheckHigherDialect(info.smb2Info.MaxSupportedDialectRevision, DialectRevision.Smb311)) { // VALIDATE_NEGOTIATE_INFO request is only used in 3.0 and 3.0.2 preferredDialects = Smb2Utility.GetDialects(DialectRevision.Smb302); } else { preferredDialects = info.requestDialect; } #region Negotiate DialectRevision selectedDialect; byte[] gssToken; Packet_Header header; clientGuid = Guid.NewGuid(); logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( client, 1, 1, Packet_Header_Flags_Values.NONE, messageId++, preferredDialects, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION, clientGuid, out selectedDialect, out gssToken, out header, out negotiateResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", header.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(header.Status))); } #endregion #region Session Setup SESSION_SETUP_Response sessionSetupResp; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( SecurityPackageType, Credential, Smb2Utility.GetCifsServicePrincipalName(SUTName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); // Server GSS token is used only for Negotiate authentication when enabled if (SecurityPackageType == SecurityPackageType.Negotiate) sspiClientGss.Initialize(gssToken); else sspiClientGss.Initialize(null); do { logWriter.AddLog(LogLevel.Information, "Client sends SessionSetup to server"); client.SessionSetup( 1, 64, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out gssToken, out header, out sessionSetupResp); if ((header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || header.Status == Smb2Status.STATUS_SUCCESS) && gssToken != null && gssToken.Length > 0) { sspiClientGss.Initialize(gssToken); } } while (header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SESSIONSETUP", header.Status); throw new Exception(string.Format("SESSIONSETUP failed with {0}", Smb2Status.GetStatusCode(header.Status))); } byte[] sessionKey; sessionKey = sspiClientGss.SessionKey; encryptionRequired = sessionSetupResp.SessionFlags == SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA; client.GenerateCryptoKeys( sessionId, sessionKey, info.smb2Info.IsRequireMessageSigning, // Enable signing according to the configuration of SUT encryptionRequired, null, false); #endregion #region TreeConnect TREE_CONNECT_Response treeConnectResp; string uncShare = string.Format(@"\\{0}\{1}", SUTName, sharename); logWriter.AddLog(LogLevel.Information, "Client sends TreeConnect to server"); client.TreeConnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncShare, out treeId, out header, out treeConnectResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREECONNECT", header.Status); throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion TREE_DISCONNECT_Response treeDisconnectResponse; #region IOCTL FSCTL_VALIDATE_NEGOTIATE_INFO VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq; validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION; validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; validateNegotiateInfoReq.DialectCount = (ushort)(preferredDialects.Length); validateNegotiateInfoReq.Dialects = preferredDialects; byte[] inputBuffer = TypeMarshal.ToBytes<VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq); byte[] outputBuffer; VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResp; IOCTL_Response ioCtlResponse; byte[] respInput = new byte[1024]; FILEID ioCtlFileId = new FILEID(); ioCtlFileId.Persistent = 0xFFFFFFFFFFFFFFFF; ioCtlFileId.Volatile = 0xFFFFFFFFFFFFFFFF; logWriter.AddLog(LogLevel.Information, "Client sends FSCTL_VALIDATE_NEGOTIATE_INFO to server"); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO, ioCtlFileId, 0, inputBuffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out outputBuffer, out header, out ioCtlResponse, 0); DetectResult result = DetectResult.UnSupported; if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Validate Negotiate Information", header.Status); } else { validateNegotiateInfoResp = TypeMarshal.ToStruct<VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer); if ((Capabilities_Values)negotiateResponse.Capabilities != validateNegotiateInfoResp.Capabilities) { logWriter.AddLog(LogLevel.Information, "Capabilities returned in ValidateNegotiateInfo response doesn't eaqual to server capabilities in original Negotiate response"); } if (negotiateResponse.ServerGuid != validateNegotiateInfoResp.Guid) { logWriter.AddLog(LogLevel.Information, "ServerGuid returned in ValidateNegotiateInfo response doesn't eaqual to server ServerGuid in original Negotiate response"); } if ((SecurityMode_Values)negotiateResponse.SecurityMode != validateNegotiateInfoResp.SecurityMode) { logWriter.AddLog(LogLevel.Information, "SecurityMode returned in ValidateNegotiateInfo response doesn't eaqual to server SecurityMode in original Negotiate response"); } if (negotiateResponse.DialectRevision != validateNegotiateInfoResp.Dialect) { logWriter.AddLog(LogLevel.Information, "Validation failed for dialect supported on server"); } result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_VALIDATE_NEGOTIATE_INFO is supported"); } #endregion #region Tree Disconnect client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
public DetectResult[] CheckIOCTL_IntegrityInfo(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL IntegrityInfo ====="); logWriter.AddLog(LogLevel.Information, "Share name: " + sharename); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId); #region Create Smb2CreateContextResponse[] serverCreateContexts; FILEID fileId; CREATE_Response createResponse; Packet_Header header; logWriter.AddLog(LogLevel.Information, "Client opens a file"); client.Create( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, Guid.NewGuid().ToString(), AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE, ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CREATE", header.Status); throw new Exception("CREATE failed with with " + Smb2Status.GetStatusCode(header.Status)); } #endregion #region IOCTL GET IntegrityInfo logWriter.AddLog(LogLevel.Information, "Client sends IOCTL request with FSCTL_GET_INTEGRITY_INFORMATION."); FSCTL_GET_INTEGRITY_INFO_OUTPUT getIntegrityInfo; IOCTL_Response ioCtlResponse; byte[] buffer = new byte[1024]; byte[] respInput = new byte[1024]; byte[] respOutput = new byte[1024]; client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_GET_INTEGRITY_INFORMATION, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); DetectResult[] result = { DetectResult.UnSupported, DetectResult.UnSupported }; if (header.Status != Smb2Status.STATUS_SUCCESS) { // Get_Integrity is not supported // Set_Integrity cannot be tested. LogFailedStatus("GET_INTEGRITY_INFORMATION", header.Status); return(result); } getIntegrityInfo = TypeMarshal.ToStruct <FSCTL_GET_INTEGRITY_INFO_OUTPUT>(respOutput); result[0] = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_GET_INTEGRITY_INFORMATION is supported"); #endregion #region IOCTL SET IntegrityInfo logWriter.AddLog(LogLevel.Information, "Client sends IOCTL request with FSCTL_SET_INTEGRITY_INFORMATION after changed the value of the following fields in FSCTL_SET_INTEGRIY_INFO_INPUT: " + "ChecksumAlgorithm, Flags, Reserved."); FSCTL_SET_INTEGRIY_INFO_INPUT setIntegrityInfo; setIntegrityInfo.ChecksumAlgorithm = FSCTL_SET_INTEGRITY_INFO_INPUT_CHECKSUMALGORITHM.CHECKSUM_TYPE_CRC64; setIntegrityInfo.Flags = FSCTL_SET_INTEGRITY_INFO_INPUT_FLAGS.FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF; setIntegrityInfo.Reserved = FSCTL_SET_INTEGRITY_INFO_INPUT_RESERVED.V1; buffer = TypeMarshal.ToBytes <FSCTL_SET_INTEGRIY_INFO_INPUT>(setIntegrityInfo); respInput = new byte[1024]; respOutput = new byte[1024]; client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_SET_INTEGRITY_INFORMATION, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); #endregion if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SET_INTEGRITY_INFORMATION", header.Status); } else { #region IOCTL GET IntegrityInfo buffer = new byte[1024]; respInput = new byte[1024]; respOutput = new byte[1024]; logWriter.AddLog(LogLevel.Information, "Client sends second FSCTL_GET_INTEGRITY_INFORMATION."); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_GET_INTEGRITY_INFORMATION, fileId, 0, buffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out respOutput, out header, out ioCtlResponse, 0); getIntegrityInfo = TypeMarshal.ToStruct <FSCTL_GET_INTEGRITY_INFO_OUTPUT>(respOutput); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Second GET_INTEGRITY_INFORMATION", header.Status); } if ((ushort)setIntegrityInfo.ChecksumAlgorithm != (ushort)getIntegrityInfo.ChecksumAlgorithm) { logWriter.AddLog(LogLevel.Information, "Failed to set the ChecksumAlgorithm field to value " + setIntegrityInfo.ChecksumAlgorithm); } result[1] = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_SET_INTEGRITY_INFORMATION is supported"); #endregion } #region Close CLOSE_Response closeResponse; client.Close( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out header, out closeResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("CLOSE", header.Status); } #endregion #region Tree Disconnect TREE_DISCONNECT_Response treeDisconnectResponse; client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return(result); } }