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);
        }
Example #5
0
        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;
            }
        }
Example #6
0
        /// <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);
        }
Example #11
0
        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);
 }
Example #17
0
 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);
                }
            }
        }
Example #19
0
        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);
                }
            }
        }
Example #23
0
        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;
            }
        }
Example #44
0
        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
        }
Example #45
0
        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());
        }
Example #46
0
        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);
            }
        }