public static void Process(NetworkTrace trace)
        {
            foreach (ConversationData c in trace.conversations)
            {
                if (c.sourcePort == 88)
                {
                    TDSParser.reverseSourceDest(c);
                }


                if (c.destPort != 88)
                {
                    continue;
                }


                KerberosData KerbData = null;

                try
                {
                    if (c.isUDP) // UDP
                    {
                        KerbData = ProcessUDP(c);
                    }
                    else        // TCP
                    {
                        KerbData = ProcessTCP(c);
                    }
                    // ignore non KRB_TGS requests
                    // ignore responses without an associated request - we don't want to log errors for unidentified request types
                    // ignore SNames we don't know what they are ... or how to read them
                    //if (KerbData.RequestType == MessageTypes.KRB_TGS_REQ
                    //   && (KerbData.SNameType == 2 || KerbData.SNameType == 10))
                    if (KerbData.RequestType == MessageTypes.KRB_TGS_REQ)
                    {
                        trace.KerbResponses.Add(KerbData);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception during Kerberos processing." + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);
                    Program.logDiagnostic("Exception during Kerberos processing." + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);
                } // catch
            }     // foreach
        }         // void Process(...)
        static void Main(string[] args)
        {
            string fileSpec    = null;
            string outFile     = null;
            string diagOutFile = null;
            string statOutFile = null;

            ArrayList sqlHints = new ArrayList();

            ActivityTimer T = new ActivityTimer();

            //
            // Set command-line rules and parse the command-line
            //

            CommandLineParser cp = new CommandLineParser();

            cp.AddRule(new ArgRule("", true, false, true, true));                 // file name is required
            cp.AddRule(new ArgRule("output", true, false, true, false));          // -output filename is optional and case-insensitive, one time only
            cp.AddRule(new ArgRule("sql", true, true, false, false));             // -sql 10:10:10:10,1433 -sql 10.10.10.11,1433 ... -sql ip,port     0..n times   (ipv4 or ipv6)
            cp.AddRule(new ArgRule("convList", false, false, true, false));       // -convList     outputs a rather lengthy report segment that is normally not required
            cp.AddRule(new ArgRule("filterFmt", true, false, true, false));       // -filterFmt NETMON|WireShark   replaces the Client IP address and port columns with a filter string, instead
            string ruleViolation = cp.Parse(args);

            if (ruleViolation != "")
            {
                Console.WriteLine("Bad arguments: " + ruleViolation);
                displayUsage();
                return;           // exit the application
            }
            else  // for case-insensitive argument names, use lower-case to match
            {
                ArrayList values = null;
                //
                // set filename -> fileSpec
                //
                values   = cp.GetArgs("");
                fileSpec = ((CommandLineArgs)values[0]).value;  // required, so it's here or we'd get a ruleViolation earlier
                //
                // set outputFile -> outFile
                //
                values = cp.GetArgs("output");
                if (values.Count != 0)  // argument supplied
                {
                    outFile = ((CommandLineArgs)values[0]).value;
                }
                else // argument omitted
                {
                    outFile = utility.getLogFileName(fileSpec);
                }
                diagOutFile = utility.getDiagLogFileName(outFile);
                statOutFile = utility.getStatLogFileName(outFile);
                //
                // set sqlHints
                //
                values = cp.GetArgs("sql");
                if (values.Count != 0) // argument supplied
                {
                    foreach (CommandLineArgs value in values)
                    {
                        sqlHints.Add(value.value);
                    }
                }
                //
                // set outputConversationList
                //
                values = cp.GetArgs("convlist");
                if (values.Count != 0)
                {
                    outputConversationList = true;
                }
                //
                // set filterFormat
                //
                values = cp.GetArgs("filterfmt");
                if (values.Count != 0)
                {
                    string value = ((CommandLineArgs)values[0]).value.ToUpper();
                    switch (value)
                    {
                    case "NETMON":
                    {
                        filterFormat = "N";
                        break;
                    }

                    case "WIRESHARK":
                    {
                        filterFormat = "W";
                        break;
                    }

                    case "AUTO":
                    {
                        filterFormat = "A";          // gets set to N or W based on the file type of the first file opened
                        break;
                    }

                    default:
                    {
                        Console.WriteLine("Bad arguments: filterFmt");
                        displayUsage();
                        return;                   // exit the application
                    }
                    }
                }
            }

            commandLine = string.Join(" ", args);

            try
            {
                diagFile = new StreamWriter(diagOutFile);

                // output diagnostic header
                logDiagnostic("SQL Server Network Analyzer " + VERSION_NUMBER);
                logDiagnostic("Command line arguments:      " + string.Join(" ", args));
                logDiagnostic("Analysis run on:             " + DateTime.Now.ToString(utility.DATE_FORMAT));

                // open log file
                CurrentActivity = "opening log file: " + outFile;
                logFile         = new StreamWriter(outFile);

                NetworkTrace Trace = new NetworkTrace();

                // add SQL hints
                foreach (string value in sqlHints)
                {
                    bool   isIPV6 = false;
                    ushort port = 0;
                    uint   ipv4 = 0;
                    ulong  ipv6hi = 0, ipv6lo = 0;
                    utility.ParseIPPortString(value, ref isIPV6, ref port, ref ipv4, ref ipv6hi, ref ipv6lo);
                    Trace.GetSQLServer(ipv4, ipv6hi, ipv6lo, port, isIPV6); // creates an entry in the SQl Server table if not one already - allows for duplicate -sql command-line arguments
                }

                // read files and parse into memory structures
                CurrentActivity = "parsing input file(s) from the folder.";
                Parser.ParseFileSpec(fileSpec, Trace);

                //Post Processing
                CurrentActivity = "processing data.";

                T.start("\nReversing backward conversations");
                Parser.ReverseBackwardConversations(Trace);
                T.stop();

                T.start("Finding retransmitted packets");
                Parser.FindRetransmits(Trace);
                T.stop();

                T.start("Finding retransmitted Keep-Alive packets");
                Parser.FindKeepAliveRetransmits(Trace);
                T.stop();

                T.start("Finding continuation packets");
                Parser.FindContinuationFrames(Trace);
                T.stop();

                T.start("Parsing TDS frames");
                TDSParser.ProcessTDS(Trace);
                T.stop();

                T.start("Finding stray SQL conversations");
                TDSParser.FindStraySQLConversations(Trace);
                T.stop();

                T.start("Finding stray SQL Servers");
                TDSParser.FindStraySQLServers(Trace);
                T.stop();

                T.start("Creating packets from frames for SQL Conversations");
                TDSParser.CreatingPacketsFromFrames(Trace);
                T.stop();

                T.start("Parsing UDP frames");
                SSRPParser.ProcessUDP(Trace);
                T.stop();

                T.start("Parsing DNS frames");
                NameResolutionParser.ProcessUDP(Trace);
                T.stop();

                T.start("Parsing Kerberos frames");
                //CurrentActivity = "analyzing data.";
                KerberosParser.Process(Trace);
                T.stop();

                T.start("Locating Domain Controllers");
                //CurrentActivity = "analyzing data.";
                DomainControllerParser.Process(Trace);
                T.stop();

                //Analysis

                CurrentActivity = "writing report.";
                statFile        = new StreamWriter(statOutFile);
                OutputText.TextReport(Trace);
                statFile.Close();
                statFile = null;
            }
            catch (Exception ex)
            {
                Console.WriteLine("An error occurred while " + CurrentActivity + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);
                logDiagnostic("An error occurred while " + CurrentActivity + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);
            }
            finally
            {
                if (logFile != null)
                {
                    logFile.Close();
                }
                if (diagFile != null)
                {
                    diagFile.Close();
                }
                if (statFile != null)
                {
                    statFile.Close();
                }
            }
        }
Exemple #3
0
        public static void ProcessUDP(NetworkTrace trace)
        {
            foreach (ConversationData c in trace.conversations)
            {
                if (c.isUDP && c.sourcePort == 1434)
                {
                    TDSParser.reverseSourceDest(c);
                }
                //parse only UDP conversations that are on port 1434
                if ((!c.isUDP) || ((c.isUDP) && (c.destPort != 1434)))
                {
                    continue;
                }


                SSRPData SSRPRequest = trace.GetSSRPRequest(c.destIP, c.destIPHi, c.destIPLo, c.isIPV6);

                if (!SSRPRequest.hasConversation(c))
                {
                    SSRPRequest.conversations.Add(c);
                }

                foreach (FrameData fd in c.frames)
                {
                    try
                    {
                        if ((byte)(fd.payload[0]) == (byte)3) // CLNT_UCAST_EX
                        {
                            SSRPRequest.hasResponse = false;
                        }

                        else if ((byte)(fd.payload[0]) == (byte)4) // Request for specific instance  (CLNT_UCAST_INST)
                        {
                            SSRPRequest.hasResponse = false;

                            if (c.frames.Count == 1)
                            {
                                SSRPRequest.hasNoResponse = true;
                            }

                            ushort Length = utility.ReadUInt16(fd.payload, 1);
                            SSRPRequest.instanceRequested = utility.ReadAnsiString(fd.payload, 3, Length);
                            //SSRPRequest.clientPort = c.sourcePort;
                            //SSRPRequest.clientIP = (c.isIPV6) ? utility.FormatIPV6Address(c.sourceIPHi, c.sourceIPLo) : utility.FormatIPV4Address(c.sourceIP);
                            SSRPRequest.sqlIP   = c.destIP;
                            SSRPRequest.sqlIPHi = c.destIPHi;
                            SSRPRequest.sqlIPLo = c.destIPLo;
                        }
                        else if ((byte)(fd.payload[0]) == (byte)5) // Response of specifric instance (SVR_RESP)
                        {
                            SSRPRequest.hasResponse = true;
                            ushort Length   = utility.ReadUInt16(fd.payload, 1);
                            String Response = utility.ReadAnsiString(fd.payload, 3, Length);
                            ParseSSRPResponse(Response, SSRPRequest, trace);
                            //if (SSRPRequest.sqlPort != 0)
                            //{
                            //    SQLServer s = trace.GetSQLServer(SSRPRequest.sqlIP, SSRPRequest.sqlIPHi, SSRPRequest.sqlIPLo, SSRPRequest.sqlPort, SSRPRequest.isIPV6);
                            //    if (s != null)
                            //    {
                            //        if (s.sqlHostName == "") s.sqlHostName = SSRPRequest.sqlHostName;
                            //        if (s.instanceName == "") s.instanceName = SSRPRequest.instanceName;
                            //        if (s.isClustered == "") s.isClustered = SSRPRequest.isClustered;
                            //        if (s.serverVersion == "") s.serverVersion = SSRPRequest.serverVersion;
                            //        if (s.namedPipe == "") s.namedPipe = SSRPRequest.namedPipe;
                            //    }
                        }
                    }
                    catch (Exception ex)
                    {
                        Program.logDiagnostic("SSRP Parser: Problem parsing frame " + fd.frameNo + " in file " + fd.file.filePath + ".");
                        Program.logDiagnostic(ex.Message);
                    }
                }
            }
        } // Process UDP