internal void ReceiveClient(object parameters)
        {
            object[]      parameterArray = parameters as object[];
            Guid          serverGuid     = (Guid)parameterArray[0];
            TcpClient     tcpClient      = (TcpClient)parameterArray[1];
            int           port           = (int)parameterArray[2];
            NetworkStream tcpStream      = tcpClient.GetStream();
            bool          isSMB2;
            string        challenge    = "";
            string        clientIP     = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Address.ToString();
            string        clientPort   = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Port.ToString();
            string        listenerPort = ((IPEndPoint)(tcpClient.Client.LocalEndPoint)).Port.ToString();

            try
            {
                while (tcpClient.Connected && isRunning)
                {
                    byte[] requestData = new byte[4096];

                    do
                    {
                        Thread.Sleep(100);
                    }while (!tcpStream.DataAvailable && tcpClient.Connected);

                    while (tcpStream.DataAvailable)
                    {
                        tcpStream.Read(requestData, 0, requestData.Length);
                    }

                    NetBIOSSessionService requestNetBIOSSessionService = new NetBIOSSessionService(requestData);
                    SMBHelper             smbHelper = new SMBHelper();

                    if (requestNetBIOSSessionService.Type == 0 || smbHelper.Protocol[0] == 0xfe || smbHelper.Protocol[0] == 0xff)
                    {
                        int sessionServiceIndex = 0;

                        if (requestNetBIOSSessionService.Type == 0)
                        {
                            sessionServiceIndex = 4;
                        }

                        byte[]     sendBuffer        = new byte[0];
                        SMBHeader  requestSMBHeader  = new SMBHeader();
                        SMB2Header requestSMB2Header = new SMB2Header();
                        smbHelper.ReadBytes(requestData, sessionServiceIndex);

                        if (smbHelper.Protocol[0] == 0xfe)
                        {
                            isSMB2 = true;
                            requestSMB2Header.ReadBytes(requestData, sessionServiceIndex);
                        }
                        else
                        {
                            isSMB2 = false;
                            requestSMBHeader.ReadBytes(requestData, sessionServiceIndex);
                        }

                        if (!isSMB2 && requestSMBHeader.Command == 0x72 || (isSMB2 && requestSMB2Header.Command == 0))
                        {
                            SMB2NegotiatelRequest smb2NegotiatelRequest = new SMB2NegotiatelRequest(requestData, 64 + sessionServiceIndex);
                            SMB2Header            responseSMB2Header    = new SMB2Header();
                            SMB2NegotiateResponse smb2NegotiateResponse = new SMB2NegotiateResponse();

                            if (!isSMB2)
                            {
                                smb2NegotiateResponse.DialectRivision = new byte[2] {
                                    0xff, 0x02
                                };
                                smb2NegotiateResponse.Capabilities = new byte[4] {
                                    0x07, 0x00, 0x00, 0x00
                                };
                                OutputNegotiation("SMB1", listenerPort, clientIP, clientPort);
                            }
                            else if (isSMB2)
                            {
                                responseSMB2Header.MessageId = requestSMB2Header.MessageId;

                                if (smb2NegotiatelRequest.GetMaxDialect() == 0x311)
                                {
                                    smb2NegotiateResponse.DialectRivision = new byte[2] {
                                        0x11, 0x03
                                    };
                                    smb2NegotiateResponse.NegotiateContextCount = 3;
                                    smb2NegotiateResponse.Capabilities          = new byte[4] {
                                        0x2f, 0x00, 0x00, 0x00
                                    };
                                    smb2NegotiateResponse.NegotiateContextOffset = 448;
                                    smb2NegotiateResponse.NegotiateContextList   = new SMB2NegotiateContext().GetBytes(new string[] { "1", "2", "3" });
                                    OutputNegotiation("SMB3", listenerPort, clientIP, clientPort);
                                }
                                else
                                {
                                    smb2NegotiateResponse.DialectRivision = new byte[2] {
                                        0x10, 0x02
                                    };
                                    smb2NegotiateResponse.Capabilities = new byte[4] {
                                        0x07, 0x00, 0x00, 0x00
                                    };
                                    OutputNegotiation("SMB2", listenerPort, clientIP, clientPort);
                                }

                                responseSMB2Header.Reserved2 = requestSMB2Header.Reserved2; // todo fix
                            }

                            smb2NegotiateResponse.EncodeBuffer();
                            smb2NegotiateResponse.ServerGUID = serverGuid.ToByteArray();
                            sendBuffer = SMB2Helper.GetBytes(new NetBIOSSessionService(), responseSMB2Header, smb2NegotiateResponse);
                        }
                        else if (isSMB2 && requestSMB2Header.Command > 0)
                        {
                            switch (requestSMB2Header.Command)
                            {
                            case 1:
                            {
                                SMB2SessionSetupRequest smb2SessionSetupRequest = new SMB2SessionSetupRequest(requestData, 64 + sessionServiceIndex);
                                NTLMNegotiate           requestNTLMNegotiate    = new NTLMNegotiate(smb2SessionSetupRequest.Buffer, true);

                                if (requestNTLMNegotiate.MessageType == 1)
                                {
                                    SMB2Header responseSMB2Header = new SMB2Header();
                                    SMB2SessionSetupResponse smb2SessionSetupResponse = new SMB2SessionSetupResponse();
                                    responseSMB2Header.Status = new byte[4] {
                                        0x16, 0x00, 0x00, 0xc0
                                    };
                                    responseSMB2Header.CreditCharge = 1;
                                    responseSMB2Header.Reserved2    = requestSMB2Header.Reserved2;
                                    responseSMB2Header.Command      = 1;
                                    responseSMB2Header.Flags        = new byte[4] {
                                        0x11, 0x00, 0x00, 0x00
                                    };
                                    responseSMB2Header.MessageId = requestSMB2Header.MessageId;
                                    responseSMB2Header.SessionId = BitConverter.GetBytes(smb2Session);
                                    smb2Session++;
                                    smb2SessionSetupResponse.Pack(Challenge, NetbiosDomain, ComputerName, DNSDomain, ComputerName, DNSDomain, out byte[] challengeData);
                                    sendBuffer = SMB2Helper.GetBytes(new NetBIOSSessionService(), responseSMB2Header, smb2SessionSetupResponse);
                                    challenge  = BitConverter.ToString(challengeData).Replace("-", "");
                                    OutputChallenge(listenerPort, clientIP, clientPort, challenge);
                                }
                                else if (requestNTLMNegotiate.MessageType == 3)
                                {
                                    NTLMResponse ntlmResponse = new NTLMResponse(smb2SessionSetupRequest.Buffer, true);
                                    string       domain       = Encoding.Unicode.GetString(ntlmResponse.DomainName);
                                    string       user         = Encoding.Unicode.GetString(ntlmResponse.UserName);
                                    string       host         = Encoding.Unicode.GetString(ntlmResponse.Workstation);
                                    string       response     = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
                                    string       lmResponse   = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
                                    OutputNTLM("SMB", listenerPort, clientIP, clientPort, user, domain, host, challenge, response, lmResponse);
                                    SMB2Header responseSMB2Header = new SMB2Header();
                                    SMB2SessionSetupResponse smb2SessionSetupResponse = new SMB2SessionSetupResponse();
                                    responseSMB2Header.Status = new byte[4] {
                                        0x6d, 0x00, 0x00, 0xc0
                                    };
                                    //responseSMB2Header.Status = new byte[4] { 0x00, 0x00, 0x00, 0x00 };
                                    //responseSMB2Header.Status = new byte[4] { 0x22, 0x00, 0x00, 0xc0 }; //access denied
                                    responseSMB2Header.CreditCharge = 1;
                                    responseSMB2Header.Reserved2    = requestSMB2Header.Reserved2;
                                    responseSMB2Header.Command      = 1;
                                    responseSMB2Header.Flags        = new byte[4] {
                                        0x11, 0x00, 0x00, 0x00
                                    };
                                    responseSMB2Header.MessageId = requestSMB2Header.MessageId;
                                    responseSMB2Header.SessionId = requestSMB2Header.SessionId;
                                    smb2SessionSetupResponse.SecurityBufferOffset = 0;
                                    sendBuffer = SMB2Helper.GetBytes(new NetBIOSSessionService(), responseSMB2Header, smb2SessionSetupResponse);
                                }
                            }
                            break;
                            }
                        }

                        tcpStream.Write(sendBuffer, 0, sendBuffer.Length);
                        tcpStream.Flush();
                    }
                    else
                    {
                        tcpClient.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                OutputError(ex, port);
            }
        }
        internal static void ProcessSMB(byte[] data, string clientIP, string listenerIP, string clientPort, string listenerPort)
        {
            if (data.Length >= 4)
            {
                NetBIOSSessionService requestNetBIOSSessionService = new NetBIOSSessionService(data);
                SMBHeader             smbHeader  = new SMBHeader();
                SMB2Header            smb2Header = new SMB2Header();
                int sessionServiceIndex          = 0;

                if (requestNetBIOSSessionService.Type == 0)
                {
                    sessionServiceIndex = 4;
                }

                SMBHelper helper = new SMBHelper(data, sessionServiceIndex);
                string    session;
                string    challenge;

                if (helper.Protocol[0] == 0xff)
                {
                    smbHeader.ReadBytes(data, sessionServiceIndex);
                    string flags = Convert.ToString(smbHeader.Flags, 2).PadLeft(8, '0');

                    switch (smbHeader.Command)
                    {
                    case 0x72:
                    {
                        if (String.Equals(flags.Substring(0, 1), "0"))
                        {
                            Output.Queue(String.Format("[.] [{0}] SMB1({1}) negotiation request detected from {2}:{3}", Output.Timestamp(), listenerPort, clientIP, clientPort));
                        }
                    }

                    break;

                    case 0x73:
                    {
                        if (String.Equals(flags.Substring(0, 1), "1"))
                        {
                            SMBCOMSessionSetupAndXResponse smbCOMSessionSetupAndXResponse = new SMBCOMSessionSetupAndXResponse(data, 32 + sessionServiceIndex);

                            if (smbCOMSessionSetupAndXResponse.SecurityBlobLength > 0)
                            {
                                if (!BitConverter.ToString(smbCOMSessionSetupAndXResponse.SecurityBlob).Contains("2A-86-48-86-F7-12-01-02-02"))         // kerberos
                                {
                                    NTLMHelper ntlmHelper = new NTLMHelper(smbCOMSessionSetupAndXResponse.SecurityBlob);

                                    if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
                                    {
                                        if (ntlmHelper.MessageType == 2)
                                        {
                                            NTLMChallenge ntlmChallenge = new NTLMChallenge(smbCOMSessionSetupAndXResponse.SecurityBlob);
                                            session   = String.Concat(listenerIP, ":", listenerPort);
                                            challenge = BitConverter.ToString(ntlmChallenge.ServerChallenge).Replace("-", "");
                                            Program.smbSessionTable[session] = challenge;
                                            Output.Queue(string.Format("[+] [{0}] SMB({1}) NTLM challenge [{2}] sent to {3}:{4}", Output.Timestamp(), clientPort, challenge, clientIP, listenerPort));
                                        }
                                    }
                                }
                                else
                                {
                                    Output.Queue(string.Format("[.] [{0}] SMB({1}) Kerberos authentication from {2}:{3}", Output.Timestamp(), clientPort, clientIP, listenerPort));
                                }
                            }
                        }
                        else
                        {
                            SMBCOMSessionSetupAndXRequest smbCOMSessionSetupAndXRequest = new SMBCOMSessionSetupAndXRequest(data, 32 + sessionServiceIndex);

                            if (smbCOMSessionSetupAndXRequest.SecurityBlobLength > 0)
                            {
                                if (!BitConverter.ToString(smbCOMSessionSetupAndXRequest.SecurityBlob).Contains("2A-86-48-86-F7-12-01-02-02"))         // kerberos
                                {
                                    NTLMHelper ntlmHelper = new NTLMHelper(smbCOMSessionSetupAndXRequest.SecurityBlob);

                                    if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
                                    {
                                        if (ntlmHelper.MessageType == 3)
                                        {
                                            NTLMResponse ntlmResponse = new NTLMResponse(smbCOMSessionSetupAndXRequest.SecurityBlob);
                                            session   = String.Concat(clientIP, ":", clientPort);
                                            challenge = Program.smbSessionTable[session]?.ToString();
                                            string domain     = Encoding.Unicode.GetString(ntlmResponse.DomainName);
                                            string user       = Encoding.Unicode.GetString(ntlmResponse.UserName);
                                            string host       = Encoding.Unicode.GetString(ntlmResponse.Workstation);
                                            string response   = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
                                            string lmResponse = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
                                            Output.NTLMOutput(user, domain, challenge, response, clientIP, host, "SMB", listenerPort, clientPort, lmResponse);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
                    }
                }
                else if (helper.Protocol[0] == 0xfe)
                {
                    smb2Header.ReadBytes(data, sessionServiceIndex);
                    string flags = Convert.ToString(BitConverter.ToUInt16(smb2Header.Flags, 0), 2).PadLeft(smb2Header.Flags.Length * 8, '0');

                    switch (smb2Header.Command)
                    {
                    case 0:
                    {
                        if (String.Equals(flags.Substring(31, 1), "0"))
                        {
                            Output.Queue(String.Format("[.] [{0}] SMB2+({1}) negotiation request detected from {2}:{3}", Output.Timestamp(), listenerPort, clientIP, clientPort));
                        }
                    }
                    break;

                    case 1:
                    {
                        if (String.Equals(flags.Substring(31, 1), "1"))
                        {
                            SMB2SessionSetupResponse smb2SessionSetupResponse = new SMB2SessionSetupResponse(data, 64 + sessionServiceIndex);

                            if (smb2SessionSetupResponse.SecurityBufferLength > 0)
                            {
                                if (!BitConverter.ToString(smb2SessionSetupResponse.Buffer).Contains("2A-86-48-86-F7-12-01-02-02"))         // kerberos
                                {
                                    NTLMHelper ntlmHelper = new NTLMHelper(smb2SessionSetupResponse.Buffer);

                                    if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
                                    {
                                        if (ntlmHelper.MessageType == 2)
                                        {
                                            NTLMChallenge ntlmChallenge = new NTLMChallenge(smb2SessionSetupResponse.Buffer);
                                            session   = BitConverter.ToString(smb2Header.SessionId).Replace("-", "");
                                            challenge = BitConverter.ToString(ntlmChallenge.ServerChallenge).Replace("-", "");
                                            Program.smbSessionTable[session] = challenge;
                                            Output.Queue(String.Format("[+] [{0}] SMB({1}) NTLM challenge [{2}] sent to {3}:{4}", Output.Timestamp(), clientPort, challenge, clientIP, listenerPort));
                                        }
                                    }
                                }
                                else
                                {
                                    Output.Queue(string.Format("[.] [{0}] SMB({1}) Kerberos authentication from {2}:{3}", Output.Timestamp(), clientPort, clientIP, listenerPort));
                                }
                            }
                        }
                        else
                        {
                            SMB2SessionSetupRequest smb2SessionSetupRequest = new SMB2SessionSetupRequest(data, 64 + sessionServiceIndex);

                            if (smb2SessionSetupRequest.SecurityBufferLength > 0)
                            {
                                if (!BitConverter.ToString(smb2SessionSetupRequest.Buffer).Contains("2A-86-48-86-F7-12-01-02-02"))         // kerberos
                                {
                                    NTLMHelper ntlmHelper = new NTLMHelper(smb2SessionSetupRequest.Buffer);

                                    if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
                                    {
                                        if (ntlmHelper.MessageType == 3)
                                        {
                                            NTLMResponse ntlmResponse = new NTLMResponse(smb2SessionSetupRequest.Buffer);
                                            session   = BitConverter.ToString(smb2Header.SessionId).Replace("-", "");
                                            challenge = Program.smbSessionTable[session]?.ToString();
                                            string domain     = Encoding.Unicode.GetString(ntlmResponse.DomainName);
                                            string user       = Encoding.Unicode.GetString(ntlmResponse.UserName);
                                            string host       = Encoding.Unicode.GetString(ntlmResponse.Workstation);
                                            string response   = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
                                            string lmResponse = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
                                            Output.NTLMOutput(user, domain, challenge, response, clientIP, host, "SMB", listenerPort, clientPort, lmResponse);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
                    }
                }
            }
        }