public HTTPG(Packet pkt) : base(pkt) { // note: base class constructor is called first (due to : base(pkt) above) // set group properties here }
public UDPG(Packet pkt) : base(pkt) { // note: base class constructor is called first (due to : base(pkt) above) // set group properties here SrcIP4 = pkt.SrcIP4; SrcPort = pkt.SrcPort; DestIP4 = pkt.DestIP4; DestPort = pkt.DestPort; }
public uint DHCP4XID; // these are the header fields that define an DHCPv4 group #endregion Fields #region Constructors public DHCP4G(Packet pkt) : base(pkt) { // note: base class constructor is called first (due to : base(pkt) above) // set group properties here foreach (H h in pkt.phlist) if (h.headerprot == Protocols.DHCP4) { DHCP4XID = ((DHCP4H)h).DHCP4XID; break; } }
public ICMPH(FileStream fs, PcapFile pfh, Packet pkt, uint i) { if ((pkt.Len - i) < 0x08) return; Type = (uint)pkt.PData[i++]; Code = (uint)pkt.PData[i++]; Checksum = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; switch (Type) { case 3: // destination unreachable case 11: // time exceeded case 4: // source quench Unused = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; break; case 12: // parameter problem Pointer = (uint)pkt.PData[i++]; Unused = (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; break; case 5: // redirect GatewayAddress = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; break; case 8: // echo case 0: // echo reply case 15: // information request case 16: // information reply Identifier = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; SequenceNumber = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; break; case 13: // timestamp case 14: // timestamp reply if ((pkt.Len - i) < 0x0c) return; OriginateTimestamp = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; ReceiveTimestamp = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; TransmitTimestamp = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; break; default: break; } // set generic header utility properties headerprot = Protocols.ICMP; payloadindex = i; payloadlen = (int)(pkt.Len - i); // set packet-level convenience properties pkt.Prots |= Protocols.ICMP; pkt.phlist.Add(this); }
// returns true if pkt belongs to group public override bool Belongs(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this save this function from having to search for the protocol header in pkt.phlist each time it is called // rules for membership in an Example packet group: // packet is // can assume GList.CanBelong has returned true // also set Complete = true if this packet completes group // first test whether packet has flag set for this protocol if (0 == (pkt.Prots & Protocols.Generic)) return false; return false; }
public ARPG(Packet pkt) : base(pkt) { // note: base class constructor is called first (due to : base(pkt) above) // set group properties here ARPH arph = null; foreach (H ph in pkt.phlist) if (ph.headerprot == Protocols.ARP) { arph = (ARPH)ph; break; } HWType = arph.HWType; Prot = arph.Prot; SenderHW = arph.SenderHW; SenderProt = arph.SenderProt; TargetProt = arph.TargetProt; if (SenderProt == TargetProt) Complete = true; // if this is a gratuitous ARP, mark the group complete immediately }
// returns true if pkt belongs to group public override bool Belongs(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this save this function from having to search for the protocol header in pkt.phlist each time it is called // rules for membership in an DHCP4 packet group: // XID's match // can assume GList.CanBelong has returned true // for DHCPv4, need to study further for completion criteria, in the meantime, never set complete if ((DHCP4H)h != null) return (DHCP4XID == ((DHCP4H)h).DHCP4XID); else { MessageBox.Show("Packet with DHCP4 protocol flag set but no DHCP4 header in phlist"); // this should never happen return false; // if we got this far, there was no DHCP4 header, despite the DHCP4 protocol flag being set } }
public StreamViewer(byte[] streamdata, ulong bytestoshow) { InitializeComponent(); // try to restore window position - see "Programing WPF Second Edition" page 321 try { Rect bounds = Properties.Settings.Default.WindowPositionStreamViewer; this.Top = bounds.Top; this.Left = bounds.Left; this.Width = bounds.Width; this.Height = bounds.Height; } catch { } Closing += PacketViewerWindow_Closing; // add handler for Closing event, to save window state // appears that object hierarchy is // FlowDocumentScrollViewer.Document is the document in the viewer // FlowDocumentScrollViewer.Document.Blocks is the list of blocks in the document // Paragraph is one of the types of blocks // Paragraph.Inlines is the list of inline elements // Paragraph.Inlines list can include TextBlocks, Spans and Runs // TextBlock.Inlines can include Spans and Runs // Spans consist of Runs // e.g. // para.Inlines.Add(tblk1); // tblk1.Inlines.Add(span1); // para.Inlines.Add(new LineBreak()); // tblk1.TextWrapping = TextWrapping.NoWrap; Packet testpkt = new Packet(); testpkt.PData = new byte[64] {0x02, 0x05, 0x03, 0x04, 0x06, 0x0a, 0x0f, 0x0e, 0x03, 0x05, 0x34, 0x58, 0x89, 0xff, 0xfe, 0x02, 0x02, 0x05, 0x03, 0x04, 0x06, 0x0a, 0x0f, 0x0e, 0x03, 0x05, 0x34, 0x58, 0x89, 0xff, 0xfe, 0x02, 0x02, 0x05, 0x03, 0x04, 0x06, 0x0a, 0x0f, 0x0e, 0x03, 0x05, 0x34, 0x58, 0x89, 0xff, 0xfe, 0x02, 0x02, 0x05, 0x03, 0x04, 0x06, 0x0a, 0x0f, 0x0e, 0x03, 0x05, 0x34, 0x58, 0x89, 0xff, 0xfe, 0x02}; para.Inlines.Add(RenderLine(testpkt, 0, 6, 16, 0, 0)); para.Inlines.Add(RenderLine(testpkt, 0, 16, 16, 0, 0)); // packet metadata in brief form // packet headers in one line fomr // check boxes next to packet headers to highlight their data }
public uint LocalPort; // the port that is not 0x35, whether it be sender or receiver (the ID may be enough to uniquely identify the group, but making the local port part of the key as well can't hurt (can it?) #endregion Fields #region Constructors public DNSG(Packet pkt) : base(pkt) { // note: base class constructor is called first (due to : base(pkt) above) // set group properties here ID = 0; foreach (H h in pkt.phlist) if (h.headerprot == Protocols.DNS) { ID = ((DNSH)h).ID; break; } if (pkt.SrcPort != 0x35) LocalPort = pkt.SrcPort; else LocalPort = pkt.DestPort; }
// pkt - Packet containing source data // offset - offset in packet of first byte // datalen - length of valid data in Data // linelen - lenght of display line in bytes // firsttohighlight, lasttohighlight - first and last bytes to be highglighted in bold // Data - byte array with packet data public TextBlock RenderLine(Packet pkt, uint offset, uint datalen, uint linelen, uint firsttohighlight, uint lasttohighlight) { string s; byte c; TextBlock tb = new TextBlock(); s = String.Format("{0:X8} | ", offset); for (int i = 0; i < linelen; i++) { if (i < datalen) { s = s + String.Format("{0:X2} ", pkt.PData[offset + i]); } else s = s + " "; if ((i % 8) == 7) s = s + " "; } s += " | "; for (int i = 0; i < linelen; i++) { if (i < datalen) { c = pkt.PData[offset + i]; if ((c >= 0x20) && (c < 0x7e)) s = s + (char)c; else s = s + "."; } else s = s + " "; if ((i % 8) == 7) s = s + " "; } tb.Inlines.Add(new Span(new Run(s))); tb.TextWrapping = TextWrapping.NoWrap; // basic render is byte values, string // handle short array // add argument for line lenghth // add argument for offset label (and add label to result) // add arguments for formatting to apply to subsets of the data return tb; }
bool RSTFound; // set to true if and when an RST packet found #endregion Fields #region Constructors public TCPG(Packet pkt, H h) : base(pkt) { // note: base class constructor is called first (due to : base(pkt) above) TCPH th = (TCPH)h; // set group properties here S1IP4 = pkt.SrcIP4; S1Port = pkt.SrcPort; S2IP4 = pkt.DestIP4; S2Port = pkt.DestPort; // SET ADDITIONAL GROUP PROPERTIES AS NECESSARY OPL1 = new OPL(this, S1Port); OPL2 = new OPL(this, S2Port); State = TCPGState.NotSequencedYet; RSTFound = false; }
// returns true if pkt belongs to group public override bool Belongs(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this save this function from having to search for the protocol header in pkt.phlist each time it is called // rules for membership in an DNS packet group: // packet has DNS protocol present // AND SrcPort matches // AND ID matches // can assume GList.CanBelong has returned true DNSH dnsh = (DNSH)h; // can assume CanBelongToThisType has returned true return ((dnsh.ID == ID) && ((pkt.SrcPort == LocalPort) || (pkt.DestPort == LocalPort))); // also set Complete = true if this packet completes group // not sure what the conditions are for a DNS group to be complete - have to look it up }
public EthernetH(FileStream fs, PcapFile pfh, Packet pkt, uint i) { if ((pkt.Len - i) < 0xe) return; DestMAC = (ulong)pkt.PData[i++] * 0x0010000000000 + (ulong)pkt.PData[i++] * 0x000100000000 + (ulong)pkt.PData[i++] * 0x000001000000 + (ulong)pkt.PData[i++] * 0x000000010000 + (ulong)pkt.PData[i++] * 0x000000000100 + (ulong)pkt.PData[i++] ; SrcMAC = (ulong)pkt.PData[i++] * 0x0010000000000 + (ulong)pkt.PData[i++] * 0x000100000000 + (ulong)pkt.PData[i++] * 0x000001000000 + (ulong)pkt.PData[i++] * 0x000000010000 + (ulong)pkt.PData[i++] * 0x000000000100 + (ulong)pkt.PData[i++] ; TypeLen = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; // NEED TO HANDLE Q-TAGGED FRAMES // set generic header properties headerprot = Protocols.Ethernet; payloadindex = i; payloadlen = (int)(pkt.Len - i); // set packet-level convenience properties pkt.Prots |= Protocols.Ethernet; pkt.SrcMAC = SrcMAC; pkt.DestMAC = DestMAC; pkt.phlist.Add(this); if (QuickFilterTools.QFMAC.Exclude(DestMAC) || QuickFilterTools.QFMAC.Exclude(SrcMAC)) { pkt.qfexcluded = true; return; } switch (TypeLen) { case 0x800: //L3Protocol = Protocols.IP4; new IP4H(fs, pfh, pkt, payloadindex); break; case 0x806: new ARPH(fs, pfh, pkt, payloadindex); break; case 0x8dd: // L3Protocol = Protocols.IPv6; break; default: break; } }
// returns true if pkt belongs to group public override bool Belongs(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this save this function from having to search for the protocol header in pkt.phlist each time it is called // rules for membership in an UDP packet group: // packet is an IP4 packet (later handle ipv6 and other layer 3 protocols) // all packets with same pair of IP/Port in source and destination (either direction) // UDP group header specification members: // src ip (in ip header) // src port (in udp header) // dest ip (in ip header) // dest port (in udp header) // can assume GList.CanBelong has returned true // also set Complete = true if this packet completes group return (((pkt.SrcIP4 == SrcIP4) && (pkt.SrcPort == SrcPort) && (pkt.DestIP4 == DestIP4) && (pkt.DestPort == DestPort)) // if source==source and dest==dest || ((pkt.SrcIP4 == DestIP4) && (pkt.SrcPort == DestPort) && (pkt.DestIP4 == SrcIP4) && (pkt.DestPort == SrcPort))); // or source==dest and dest==source }
// returns true if pkt belongs to group public override bool Belongs(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this save this function from having to search for the protocol header in pkt.phlist each time it is called // rules for membership in an ARP packet group: // the first packet found is included (it may be a reply, if the request occurred before the capture file) // if the packet is a gratuitous ARP, group is immediately marked complete // further packets will be included if they are a valid response to the first packet (i.e., sender == original target, and opcode == 2) // ARP group header specification members: // HWType // Prot // SenderHW address // SenderProt address // TargetProt address // can assume GList.CanBelong has returned true if (h == null) return false; // if no ARP header, return false now ARPH arph = (ARPH)h; if ((arph.TargetHW == SenderHW) && (arph.TargetProt == SenderProt) && (arph.SenderProt == TargetProt)) // if this packet is a proper response to the original request.... if ((arph.HWType == HWType) && (arph.Prot == Prot) && (arph.Opn == 2)) // ... and if the hardware type and protocol fields match, and opcode == 2 { Complete = true; // then this packet completes the group return true; // return true } return false; }
// must match on ALL filter items to return true public bool Match(Packet pkt) { if (filterlist.Count() == 0) return false; foreach (FilterItem fi in filterlist) if (fi.Match(pkt) == false) return false; return true; }
public ARPH(FileStream fs, PcapFile pfh, Packet pkt, uint i) { if ((pkt.Len - i) < 0x8) return; HWType = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; Prot = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; HWAddrLen = (uint)pkt.PData[i++] ; ProtAddrLen = (uint)pkt.PData[i++] ; Opn = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; if ((pkt.Len - i) < (2 * HWAddrLen + 2 * ProtAddrLen)) return; // HANDLE OTHER ADDR LEN VARIATIONS if ((HWAddrLen != 6) || (ProtAddrLen != 4)) return; SenderHW = (ulong)pkt.PData[i++] * 0x0010000000000 + (ulong)pkt.PData[i++] * 0x000100000000 + (ulong)pkt.PData[i++] * 0x000001000000 + (ulong)pkt.PData[i++] * 0x000000010000 + (ulong)pkt.PData[i++] * 0x000000000100 + (ulong)pkt.PData[i++] ; SenderProt = (uint)pkt.PData[i++] * 0x000001000000 + (uint)pkt.PData[i++] * 0x000000010000 + (uint)pkt.PData[i++] * 0x000000000100 + (uint)pkt.PData[i++] ; TargetHW = (ulong)pkt.PData[i++] * 0x0010000000000 + (ulong)pkt.PData[i++] * 0x000100000000 + (ulong)pkt.PData[i++] * 0x000001000000 + (ulong)pkt.PData[i++] * 0x000000010000 + (ulong)pkt.PData[i++] * 0x000000000100 + (ulong)pkt.PData[i++] ; TargetProt = (uint)pkt.PData[i++] * 0x000001000000 + (uint)pkt.PData[i++] * 0x000000010000 + (uint)pkt.PData[i++] * 0x000000000100 + (uint)pkt.PData[i++] ; // set generic header properties headerprot = Protocols.ARP; payloadindex = i; payloadlen = (int)(pkt.Len - i); // set packet-level convenience properties pkt.Prots |= Protocols.ARP; // add to packet header list pkt.phlist.Add(this); }
// returns true if packet can belong to a group of this type public override bool CanBelong(Packet pkt, H h) { // h argument: the GList.GroupPacket function can pass in a reference to a relevant protocol header, so CanBelong does not have to search the header list every time it is called return true; }
public DNSH(FileStream fs, PcapFile pfh, Packet pkt, uint i) { Len = (uint)(pkt.phlist[pkt.phlist.Count() - 1]).payloadlen; // if not enough data remaining, return without reading anything // note that we have not added the header to the packet's header list yet, so we are not leaving an invalid header in the packet if ((pkt.Len - i) < Len) return; ID = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; QR = ((uint)pkt.PData[i] & 0x80) / 0x80; OpCode = ((uint)pkt.PData[i] & 0x78) / 0x08; AA = ((uint)pkt.PData[i] & 0x04) / 0x04; TC = ((uint)pkt.PData[i] & 0x02) / 0x02; RD = ((uint)pkt.PData[i++] & 0x01); RA = ((uint)pkt.PData[i] & 0x80) / 0x80; Z = ((uint)pkt.PData[i] & 0x70) / 0x10; RCode = ((uint)pkt.PData[i++] & 0x000f); QDCOUNT = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; ANCOUNT = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; NSCOUNT = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; ARCOUNT = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; RRs = new List<DNSRRList>(); RRs.Add(new DNSRRList()); // add empty list to containt the questions for (int ii = 0; ii < QDCOUNT; ii++) RRs[0].Items.Add(new DNSRR(pkt, ref i, true)); //ffadfdadfadd // finish debugging reading individual packets // add sub tree display for dns packets // make question and answer rrs a single list // add variables to index the list for firstAN, firstNS, firstAR // add datatemplate for dnsitem // create dns grouping logic - simply match ID fields RRs.Add(new DNSRRList()); for (int ii = 0; ii < ANCOUNT; ii++) RRs[1].Items.Add(new DNSRR(pkt, ref i, false)); RRs.Add(new DNSRRList()); for (int ii = 0; ii < NSCOUNT; ii++) RRs[2].Items.Add(new DNSRR(pkt, ref i, false)); RRs.Add(new DNSRRList()); for (int ii = 0; ii < ARCOUNT; ii++) RRs[3].Items.Add(new DNSRR(pkt, ref i, false)); if (i != pkt.Len) MessageBox.Show("Did Not Read DNS record properly? i != pkt.Len"); // set generic header properties headerprot = Protocols.DNS; payloadindex = i; payloadlen = (int)(pkt.Len - i); // set packet-level convenience properties pkt.Prots |= Protocols.DNS; // add header to packet's header list pkt.phlist.Add(this); }
public bool Match(Packet pkt) { uint mval; mval = (pkt.SrcIP4 & Mask); switch (Relation) { case Relations.Equal: return (mval == Value); case Relations.NotEqual: return (mval != Value); case Relations.LessThan: return (mval < Value); case Relations.LessThanOrEqual: return (mval <= Value); case Relations.GreaterThan: return (mval > Value); case Relations.GreaterThanOrEqual: return (mval >= Value); case Relations.Undefined: default: return false; } }
// returns true if packet should be included based on this filterset public bool Include(Packet pkt) { bool include = false; // the default result is to not include the packet, unless one of the filters says to include it if (Filters.Count() == 0) return true; foreach (Filter f in Filters) if (f.Active) if (f.Match(pkt)) { include = f.InclusionFilter; break; } return include; }
public UDPH(FileStream fs, PcapFile pfh, Packet pkt, uint i) { if ((pkt.Len - i) < 0x8) return; SrcPort = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; DestPort = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; Len = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; Checksum = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++]; // set generic header properties headerprot = Protocols.UDP; payloadindex = i; payloadlen = (int)Len - 8; // set packet-level convenience properties pkt.Prots |= Protocols.UDP; pkt.udphdr = this; pkt.SrcPort = SrcPort; pkt.DestPort = DestPort; // add to packet header list pkt.phlist.Add(this); if ((SrcPort == 0x43) || (SrcPort == 0x44) || (DestPort == 0x43) || (DestPort == 0x44)) // DHCP v4 new DHCP4H(fs, pfh, pkt, i); else if ((SrcPort == 0x35) || (DestPort == 0x35)) // DNS new DNSH(fs, pfh, pkt, i); }
public uint NGBlockLen; // total block length, if this is a PcapNG packet (needed by Packet function so it can know how many bytes to read over after packet data section) #endregion Fields #region Constructors public PcapH(FileStream fs, PcapFile pcf, Packet pkt, uint i) { uint timesecs, timeusecs; uint timehigh, timelow; ulong time; PcapFile.InterfaceDescription thisif; uint pcaphdrlen; byte[] d = new byte[0x1c]; if (pcf.Type == PcapFile.PcapFileTypes.PcapOld) // if this is a plain pcap packet (not pcap ng) { headerprot = Protocols.PcapOld; DataLink = pcf.FileHdrOld.DataLink; fs.Read(d, 0, 0x10); // timestamp is stored in file as 2 32 bit integers (per inspection of file and per http://wiki.wireshark.org/Development/LibpcapFileFormat) // first is time in seconds since 1/1/1970 00:00:00, GMT time zone // second is microseconds (or nanoseconds if fileheader nanores == 1) timesecs = (pcf.FileHdrOld.Bigendian ? PcapFile.flip32(d, 0) : BitConverter.ToUInt32(d, 0)); timeusecs = (pcf.FileHdrOld.Bigendian ? PcapFile.flip32(d, 4) : BitConverter.ToUInt32(d, 4)); Time = new DateTime(timesecs * TimeSpan.TicksPerSecond + timeusecs * TimeSpan.TicksPerSecond / 1000000 / ((pcf.FileHdrOld.Nanores == 1) ? 1000 : 1)); CapLen = (pcf.FileHdrOld.Bigendian ? PcapFile.flip32(d, 8) : BitConverter.ToUInt32(d, 8)); Len = (pcf.FileHdrOld.Bigendian ? PcapFile.flip32(d, 12) : BitConverter.ToUInt32(d, 12)); pcaphdrlen = 0x10; payloadindex = 0x10; payloadlen = (int)CapLen - 0x10; fs.Seek(-0x10, SeekOrigin.Current); // rewind so code below can read whole packet into pkt.PData } else { // this is a pcapng packet // currently only handling "enhanced packet block" type packets headerprot = Protocols.PcapNG; pcf.FileHdrNG.ReadBlocksUntilPacket(fs); // read any non-packet blocks fs.Read(d, 0, 0x1c); NGBlockLen = (pcf.FileHdrNG.CurrentSection.bigendian ? PcapFile.flip32(d, 4) : BitConverter.ToUInt32(d, 4)); thisif = pcf.FileHdrNG.IntDescDict[(pcf.FileHdrNG.CurrentSection.bigendian ? PcapFile.flip32(d, 8) : BitConverter.ToUInt32(d, 8))]; DataLink = thisif.LinkType; timehigh = (pcf.FileHdrNG.CurrentSection.bigendian ? PcapFile.flip32(d, 0x0c) : BitConverter.ToUInt32(d, 0x0c)); timelow = (pcf.FileHdrNG.CurrentSection.bigendian ? PcapFile.flip32(d, 0x10) : BitConverter.ToUInt32(d, 0x10)); time = (ulong)timehigh * 0x100000000 + (ulong)timelow; Time = pcf.FileHdrNG.TSBasis; long factor = TimeSpan.TicksPerSecond / (long)thisif.TSUnitsPerSecond; time = (ulong)((long)time * factor); TimeSpan ts = new TimeSpan((long)time); Time = Time.Add(ts); CapLen = (pcf.FileHdrNG.CurrentSection.bigendian ? PcapFile.flip32(d, 0x14) : BitConverter.ToUInt32(d, 0x14)); Len = (pcf.FileHdrNG.CurrentSection.bigendian ? PcapFile.flip32(d, 0x18) : BitConverter.ToUInt32(d, 0x18)); pcaphdrlen = 0x1c; payloadindex = 0x1c; payloadlen = (int)CapLen - 0x1c; fs.Seek(-0x1c, SeekOrigin.Current); // rewind so code below can read whole packet into pkt.PData } pkt.PData = new byte[pcaphdrlen + CapLen]; pkt.Len = pcaphdrlen + CapLen; fs.Read(pkt.PData, 0, (int)(pcaphdrlen + CapLen)); pkt.phlist.Add(this); pkt.Prots |= headerprot; switch (DataLink) { case 1: // ethernet new EthernetH(fs, pcf, pkt, payloadindex); break; default: break; } }
// returns true if packet can belong to a group of this type public override bool CanBelong(Packet pkt, H h) { // h argument: the GList.GroupPacket function can pass in a reference to a relevant protocol header, so CanBelong does not have to search the header list every time it is called return (h != null); // any packet with a DNS header can belong to a DNS group }
// starts a new group if this packet can be the basis for a new group of this type public override G StartNewGroup(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this saves this function from having to search for the protocol header in pkt.phlist each time it is called if (h != null) return new DNSG(pkt); // any packet with a DNS header can start a DNS group else return null; // return null if cannot start a group with this packet }
private void ChooseFile(object sender, RoutedEventArgs e) { PcapFile pfh; OpenFileDialog dlg = new OpenFileDialog(); Nullable<bool> result; FileStream fs; Packet pkt; byte[] b = new byte[1000]; dlg.Multiselect = false; dlg.InitialDirectory = Properties.Settings.Default.LastDirectory; dlg.FileName = Properties.Settings.Default.LastFile; result = dlg.ShowDialog(); if (result == true) { pkts.Clear(); // deprecated: exclpkts.Clear(); foreach (GList gl in grouplistlist) gl.groups.Clear(); QuickFilterTools.QFMAC.ResetCounters(); QuickFilterTools.QFIP4.ResetCounters(); //foreach (PktSet set in setlist.sets) set.pkts.Clear(); //qfexcluded.pkts.Clear(); Properties.Settings.Default.LastDirectory = dlg.InitialDirectory; Properties.Settings.Default.LastFile = dlg.FileName; filename.Content = dlg.FileName; fs = new FileStream(dlg.FileName, FileMode.Open); pfh = new PcapFile(fs); while (fs.Position < fs.Length) { pkt = new Packet(fs, pfh); if (filters.Include(pkt)) pkts.Add(pkt); // lines below are from older "Quickfilter" implementation - this may be permanently obsolete // // NEXT LINE IS TEMPORARY - ONCE QUICKFILTER IS TRUSTED, PACKETS THAT ARE EXCLUDED SHOULD SIMPLY BE DESTROYED // if (pkt.qfexcluded) exclpkts.Add(pkt); // else pkts.Add(pkt); } foreach (Packet p in pkts) foreach (GList gl in grouplistlist) if (gl.GroupPacket(p)) break; foreach (TCPG tg in ((TCPGList)(grouplistlist[2])).groups) { tg.OPL1.CopyBytes(1000, b); tg.OPL2.CopyBytes(1000, b); } CollectionViewSource.GetDefaultView(grouptree.ItemsSource).Refresh(); fs.Close(); } }
public Packet mypkt; // reference to packet that contains this RR, so we can access the name string data #endregion Fields #region Constructors // if isquestion==true, process as a question entry (having only NAME, TYPE and CLASS fields) public DNSRR(Packet pkt, ref uint pos, bool isquestion) { mypkt = pkt; NAME = pos; Advanceposovername(pkt.PData, ref pos); TYPE = (uint)pkt.PData[pos] * 0x100 + (uint)pkt.PData[pos + 1]; pos += 2; CLASS = (uint)pkt.PData[pos] * 0x100 + (uint)pkt.PData[pos + 1]; pos += 2; if (isquestion) return; // if this is a "question" record, there are no further fields TTL = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; RDLENGTH = (uint)pkt.PData[pos] * 0x100 + (uint)pkt.PData[pos + 1]; pos += 2; switch (TYPE) { case 1: // A - a host address RDATA1 = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; // A - internet address (ipv4) break; case 2: // NS - an authoritative name server RDATA1 = pos; pos += RDLENGTH; break; case 5: // CNAME - the canonical name for an alias RDATA1 = pos; pos += RDLENGTH; break; case 6: // SOA - start of zone of authority RDATA1 = pos; // MNAME - name server that was the original or primary source of data for this zone Advanceposovername(pkt.PData, ref pos); RDATA2 = pos; // RNAME - mailbox of person responsible for this zone Advanceposovername(pkt.PData, ref pos); RDATA3 = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; // SERIAL - version number of the original copy of the zone RDATA4 = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; // REFRESH - time (seconds) before zone should be refreshed RDATA5 = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; // RETRY - time (seconds) before a failed refresh should be retried RDATA6 = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; // EXPIRE - upper limit on time (seconds) before zone is no longer authoritative RDATA7 = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; // MINIMUM - TTL that should apply to any RR from this zone break; case 7: // MB - mailbox domain name RDATA1 = pos; pos += RDLENGTH; break; case 8: // MG - mail group member RDATA1 = pos; pos += RDLENGTH; break; case 9: // MR - mail rename domain name RDATA1 = pos; pos += RDLENGTH; break; case 0x0a: // NULL - a null RR pos += RDLENGTH; break; case 0x0b: // WKS - well known service description RDATA1 = (uint)pkt.PData[pos] * 0x1000000 + (uint)pkt.PData[pos + 1] * 0x10000 + (uint)pkt.PData[pos + 2] * 0x100 + (uint)pkt.PData[pos + 3]; pos += 4; // ADDRESS - 32 bit internet address RDATA2 = (uint)pkt.PData[pos]; pos++; // PROTOCOL - 8 bit IP protocol number RDATA3 = pos; // bitmap - bit position corresponds to port number, bit set indicates protocol supported on that port pos += RDLENGTH - 5; break; case 0x0c: // PTR - domain name pointer RDATA1 = pos; pos += RDLENGTH; break; case 0x0d: // HINFO - host information RDATA1 = pos; pos += pkt.PData[pos]; // CPU - character string (first byte is length, no null terminator) RDATA2 = pos; pos += pkt.PData[pos]; // OS - character string (first byte is length, no null terminator) break; case 0x0e: // MINFO - mailbox or mail list information RDATA1 = pos; while (pkt.PData[pos] > 0) pos++; RDATA2 = pos; while (pkt.PData[pos] > 0) pos++; break; case 0x0f: // MX - mail exchange RDATA1 = (uint)pkt.PData[pos] * 0x100 + (uint)pkt.PData[pos + 1]; RDATA2 = pos + 2; pos += RDLENGTH; break; case 0x10: // TXT - text strings RDATA1 = pos; pos += RDLENGTH; // character strings (can be > 1) where first byte is length and no null terminators break; case 3: // MD - a mail destination (OBSOLETE per rfc 1035) case 4: // MF - a mail forwarder (obsolete per rfc 1035) default: MessageBox.Show("Unhandled DNS RR Type"); break; } }
// returns true if pkt belongs to group, also tests for normal start sequence of TCP group public override bool Belongs(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this save this function from having to search for the protocol header in pkt.phlist each time it is called // rules for membership in an TCP packet group: // packet is an IP4 packet (later handle ipv6 and other layer 3 protocols) // all packets with same pair of IP/Port in source and destination (either direction) // can assume GList.CanBelong has returned true // also set Complete = true if this packet completes group if (((pkt.SrcIP4 == S1IP4) && (pkt.SrcPort == S1Port) && (pkt.DestIP4 == S2IP4) && (pkt.DestPort == S2Port)) // if source==source and dest==dest || ((pkt.SrcIP4 == S2IP4) && (pkt.SrcPort == S2Port) && (pkt.DestIP4 == S1IP4) && (pkt.DestPort == S1Port))) // or source==dest and dest==source { if((((TCPH)h).Flags & 0x04) != 0) { if (RSTFound == false) { RSTFound = true; return true; } else { MessageBox.Show("Packet found for TCP group after an RST packet for that group"); return true; } } if (State == TCPGState.NotSequencedYet) { if (L.Count == 2) // NOTE: OTHER LOGIC DEPENDS ON THE FACT THAT "NormalState" SPECIFICALLY IMPLIES THAT FIRST THREE PACKETS ARE // SYN, SYN/ACK AND ACK, THE TYPICAL 3 WAY HANDSHAKE // ANY DEVIATION FROM THAT PATTERN COULD BREAK ASSUMPTIONS MADE DOWNSTREAM // if this is the third packet, test for normal start sequence // if the first three packets match the "normal" sequence, set State = NormalStart // otherwise set State = SequenceFailed // in no case do we leave State as NotSequencedYet { TCPH th = (TCPH)(L[0].groupprotoheader); if ((th.Flags & 0x12)==0x02) // if SYN set and ACK not set in first packet { th = (TCPH)(L[1].groupprotoheader); if (th.SrcPort == S2Port) // and if second packet is from stream 2 { if ((th.Flags & 0x12) == 0x12) // and if SYN set and ACK set in second packet { if (pkt.SrcPort == S1Port) // and if this (the third) packet is from stream 1 { th = (TCPH)(pkt.groupprotoheader); if ((th.Flags & 0x12)==0x10) // and if SYN not set and ACK set in third packet { State = TCPGState.NormalStart; // then we have a normal start sequence } } } } } if (State != TCPGState.NormalStart) State = TCPGState.SequenceFailed; } } return true; } else return false; }
public TCPH(FileStream fs, PcapFile pfh, Packet pkt, uint i) { uint temp; uint optionbytes; H containingheader = pkt.phlist[pkt.phlist.Count()-1]; TCPOption thisoption; List<TCPOption> options = new List<TCPOption>(); // if containing protocol does not know it's payload length, return with no result - need to add code to handle this case // TCP needs to be told the length of its payload by the outer protocol // it may not be all of the remaining bytes in the packet, at least due to cases where the ethernet frame includes padding bytes that are captured by wireshark/pcap if (containingheader.payloadlen == -1) { MessageBox.Show("Trying to parse TCP header where containing protocol did not set payloadlen - need to add code to handle this"); return; } // if not enough data remaining, return without reading anything // note that we have not added the header to the packet's header list yet, so we are not leaving an invalid header in the packet if ((pkt.Len - i) < 0x14) return; // read in the fixed header data SrcPort = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; DestPort = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; SeqNo = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; AckNo = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; temp = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; DataOffset = temp / 0x1000; Flags = temp & 0xfff; WindowSize = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; Checksum = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; UrgentPtr = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; optionbytes = (DataOffset * 4) - 0x14; // number of bytes of options plus any padding to get TCP header to 32 bit boundary if ((pkt.Len - i) < (optionbytes + 0x14)) return; // if not enough bytes to fill options fields, return without adding header to packet for (uint ob = 0; ob < optionbytes; ) { thisoption = new TCPOption(); thisoption.Kind = (uint)pkt.PData[i++] ; i++; switch (thisoption.Kind) { case 0: // end of options list thisoption.Length = 1; i += optionbytes - i; // skip any remaining padding bytes ob = optionbytes; break; case 1: // NOP, just eat the byte thisoption.Length = 1; break; case 2: // maximum segment size, len is 4, segment size is 32 bits thisoption.Length = (uint)pkt.PData[i++] ; thisoption.Data = new uint[1]; thisoption.Data[0] = (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; ob += 3; break; case 3: // window scale thisoption.Length = (uint)pkt.PData[i++] ; thisoption.Data = new uint[1]; thisoption.Data[0] = (uint)pkt.PData[i++] ; ob += 2; break; case 4: // selective acknowledgement permitted thisoption.Length = (uint)pkt.PData[i++] ; ob++; thisoption.Data = null; break; case 5: // selective acknowledgement thisoption.Length = (uint)pkt.PData[i++] ; if (thisoption.Length > 0x22) MessageBox.Show("TCP packet with bad Selective Acknowlegement option"); thisoption.Data = new uint[(thisoption.Length - 2) / 4]; for (int ii = 0; ii < (thisoption.Length - 2) / 4; ii++) thisoption.Data[ii] = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; ob += thisoption.Length - 1; break; case 8: // timestamp and echo of previous timestamp thisoption.Length = (uint)pkt.PData[i++] ; thisoption.Data = new uint[2]; thisoption.Data[0] = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; thisoption.Data[1] = (uint)pkt.PData[i++] * 0x1000000 + (uint)pkt.PData[i++] * 0x10000 + (uint)pkt.PData[i++] * 0x100 + (uint)pkt.PData[i++] ; ob += 9; break; case 0x0e: // TCP alternate checksum request thisoption.Length = (uint)pkt.PData[i++] ; thisoption.Data = new uint[1]; thisoption.Data[0] = (uint)pkt.PData[i++] ; ob += 2; break; case 0x0f: // TCP alternate checksum data thisoption.Length = (uint)pkt.PData[i++] ; thisoption.Data = new uint[thisoption.Length]; for (int ii = 0; ii < thisoption.Length; ii++) thisoption.Data[ii] = (uint)pkt.PData[i++] ; // just naively read each byte into a uint - this option is considered "historic" and probably will never be encountered ob += thisoption.Length - 1; break; default: MessageBox.Show("Unknown TCP header option type"); break; } options.Add(thisoption); } Options = new TCPOption[options.Count]; // copy options into TCPH.Options for (int ii = 0; ii < options.Count; ii++) Options[ii] = options[ii]; // set generic header properties headerprot = Protocols.TCP; payloadindex = i; payloadlen = containingheader.payloadlen - 0x14 - (int)optionbytes; // set packet-level convenience properties pkt.tcphdr = this; pkt.Prots |= Protocols.TCP; pkt.SrcPort = SrcPort; pkt.DestPort = DestPort; // add header to packet's header list pkt.phlist.Add(this); // determine which header constructor to call next, if any, and call it switch (1) { case 0x01: break; default: break; } }
// starts a new group if this packet can be the basis for a new group of this type public override G StartNewGroup(Packet pkt, H h) { // h argument is for utility - GList.GroupPacket function will pass in a reference to the packet header matching the protocol specified in the GList - this saves this function from having to search for the protocol header in pkt.phlist each time it is called if (true) return new ExampleG(pkt); // replace "true" with test for other qualifications for this packet to start a new group else return null; // return null if cannot start a group with this packet }