public static KerberosData ProcessUDP(ConversationData c) { KerberosData KerbData = new KerberosData(); KerbData.SourcePort = c.sourcePort; KerbData.convData = c; int Len2 = 0; int TagLen = 0; string SPN = null; int TagID = 0; bool IsContinueToNextFrame = false; foreach (FrameData fd in c.frames) { if (fd.payloadLength <= 1) { continue; } TDSReader ByteReader = new TDSReader(fd.payload, 0, -1, fd.payloadLength); //Skip over 4 bytes 'ApplicationTag' ReadAsnLen(ByteReader); //Skip over 4 bytes 'KdcReq->SequenceHeader' ReadAsnLen(ByteReader); //Init vars after every frame processing Len2 = 0; TagLen = 0; SPN = null; TagID = 0; do { TagID = ByteReader.ReadByte(); TagLen = ReadAsnLen(ByteReader, false); TagID = TagID & 0x1F; switch (TagID) //Lower 5 bits { case 0: // version# in Tag 0 for KRB_TGS_REP (response) case 1: case 2: { if ((fd.isFromClient && TagID == 1) || (!fd.isFromClient && TagID == 0)) { GetVersion(KerbData, ByteReader); } else if ((!fd.isFromClient && TagID == 1) || (fd.isFromClient && TagID == 2)) { MessageTypes MsgType = GetMessageType(KerbData, ByteReader); KerbData.frameNo = fd.frameNo; if (MsgType == MessageTypes.KRB_TGS_REP) { //ParseNonErrorResponseUDP(KerbData, ByteReader); IsContinueToNextFrame = true; } else if (MsgType == MessageTypes.KRB_ERROR) { ParseErrorResponseUDP(KerbData, ByteReader); IsContinueToNextFrame = true; } } break; } case 3: { //ByteReader.ReadByte(); Len2 = ReadAsnLen(ByteReader); ByteReader.ReadBytes(Len2); // skip the padata tag. break; } case 4: { //ByteReader.ReadByte(); //skip sequence header of ReqBody ReadAsnLen(ByteReader); int TagId2 = 0; do { TagId2 = ByteReader.ReadByte(); Len2 = ReadAsnLen(ByteReader, false); TagId2 = TagId2 & 0x1F; switch (TagId2) { case 0: { ByteReader.ReadByte(); int Len3 = ReadAsnLen(ByteReader, false); //Read and skip 'padding' ByteReader.ReadBytes(Len3 - 4); KerbData.IsForwardable = (ByteReader.ReadByte() & 0x40) != 0; //Read remaining three bytes ByteReader.ReadBytes(3); break; } case 1: case 2: case 4: case 5: case 7: case 8: //skip these tags. { ByteReader.ReadBytes(Len2); break; } case 3: { // UDP SName implementation - replacing with TCP implementation // ReadAsnLen(ByteReader); //Skip sequence header of sname // int Len3 = ReadAsnLen(ByteReader); //Skip Tag0 of sname // ByteReader.ReadBytes(Len3); //skip nametype // ReadAsnLen(ByteReader); //Skip Tag1 of sname // Len3 = ReadAsnLen(ByteReader); //Skip sequence header of sname->Tag1 // Len3 = ReadAsnLen(ByteReader); // Read SPN Length - same as the TCP implementation // SPN = ByteReader.ReadAnsiString(Len3); // KerbData.SPNRequested = SPN; // TCP SName implementation ReadAsnLen(ByteReader); //Skip sequence header of sname int Len3 = ReadAsnLen(ByteReader); //Skip Tag0 of sname // // Read the Name Type: // // 2 = NT-SRV-INST - has two Strings: Service and Instance. '/' separater is implied // 10 = NT-ENTERPRISE - has one String // // Throw error on all other values // Len3 = ReadAsnLen(ByteReader); if (Len3 != 1) { throw new Exception("Unexpected length (" + Len3 + ") reading SName Name Type."); } byte NameType = ByteReader.ReadByte(); KerbData.SNameType = NameType; if (NameType != 2 && NameType != 10) { IsContinueToNextFrame = true; break; } ReadAsnLen(ByteReader); //Skip Tag1 of sname Len3 = ReadAsnLen(ByteReader); //Skip sequenceheader of sname. SPN = ""; if (NameType == 2) // read service type { Len3 = ReadAsnLen(ByteReader); SPN = ByteReader.ReadAnsiString(Len3) + "/"; } Len3 = ReadAsnLen(ByteReader); // read SPN length SPN += ByteReader.ReadAnsiString(Len3); KerbData.SPNRequested = SPN; break; } default: { throw new Exception("Unknonw tag in kerberos packet"); } } } while (TagId2 < 3); break; } default: { // throw new Exception("Un expected tags in kerberos request/response/ problem in parseing"); break; } } }while ((TagID < 4) && (!IsContinueToNextFrame)); } return(KerbData); }
public static void ProcessUDP(NetworkTrace trace) { string[] DnsReturnMessage = new string[] { "Success", "Format error; DNS server did not understand the update request.", "DNS server encountered an internal error, such as a forwarding timeout.", "A name that should exist does not exist.", "DNS server does not support the specified Operation code.", "DNS server refuses to perform the update.", "A name that should not exist does exist.", "A resource record set that should not exist does exist.", "A resource record set that should exist does not exist.", "DNS server is not authoritative for the zone named in the Zone section.", "A name used in the Prerequisite or Update sections is not within the zone specified by the Zone section.", "Invalid return code.", "Invalid return code.", "Invalid return code.", "Invalid return code.", "Reserved." }; foreach (ConversationData c in trace.conversations) { //DNS traffic is over UDP. If the current converstion is not UDP then skip that non DNS conversation. if (!c.isUDP) { continue; } //Skip the conversation, if its just UDP, but not DNS if ((c.isUDP) && c.destPort != 53) { continue; } trace.DNSRequestCount++; try { //Parse the DNS frames of the conversation. foreach (FrameData fd in c.frames) { DNS DNSresponse = new DNS(); if (fd.payloadLength < 1) { continue; } //DNS data starts at 42nd byte of the total payload. so the payload = (Total Payload - 42) bytes. TDSReader ByteReader = new TDSReader(fd.payload, 0, -1, fd.payloadLength); ByteReader.ReadBigEndianUInt16(); //Skip over the query ID. //Read the Flags and convert into bytes. int FlagsHigh = ByteReader.ReadByte(); int FlagsLow = ByteReader.ReadByte(); if ((FlagsHigh & (int)0x80) == (int)0x0) // DNS request { //DNSresponse.srcServerIP = c.sourceIP.ToString(); DNSresponse.dnsServerIP = c.destIP.ToString(); } else if ((FlagsHigh & (int)0x80) == (int)0x80) // DNS response { int rCode = FlagsLow & 0x0F; // should be between 0 - 15. //DNSresponse.srcServerIP= c.destIP.ToString(); DNSresponse.dnsServerIP = c.sourceIP.ToString(); DNSresponse.frameNo = fd.frameNo; DNSresponse.TimeStamp = new DateTime(((FrameData)c.frames[c.frames.Count - 1]).ticks).ToString(utility.TIME_FORMAT); //new DateTime(((FrameData)trace.frames[0]).ticks).ToString(utility.TIME_FORMAT); DNSresponse.errorCode = rCode; DNSresponse.ErrorDesc = DnsReturnMessage[rCode]; //Question Count - 2 bytes DNSresponse.QuestionCount = ByteReader.ReadInt16(); //Answer Count - 2 bytes DNSresponse.AnswerCount = ByteReader.ReadInt16(); //Skip 2 bytes - Name Server count ByteReader.ReadInt16(); //Skip 2 bytes - Additional count ByteReader.ReadInt16(); //Start reading the QName //13th byte of the DNS Payload - payload[12] byte length = ByteReader.ReadByte(); string Name = ""; while (length != 0) { Name += (Name == "" ? "" : ".") + ByteReader.ReadAnsiString(length); length = ByteReader.ReadByte(); } DNSresponse.nameReqested = Name; DNSresponse.convData = c; //DNSresponse.srcPort = c.sourcePort; // Console.WriteLine(fd.file.filePath + "\t" + fd.frameNo.ToString()); if (rCode != (int)DNSReturnCodes.NOERROR) { trace.DNSResponses.Add(DNSresponse); } } } } catch (Exception ex) { Console.WriteLine("Error parsing DNS conversation: " + ex.Message + "\r\n" + ex.StackTrace); Program.logDiagnostic("Error parsing DNS conversation: " + ex.Message + "\r\n" + ex.StackTrace); } } }