private void ParseHeader(RawDGram p, int len) { Console.WriteLine("Parsing Header"); IPHeader header = new IPHeader(p.rawBytes, len); switch (header.ProtocolType) { case Protocol.ICMP: ICMPHeader icmpHeader = new ICMPHeader(header.Data, header.MessageLength); //Console.WriteLine(String.Format("ICMP type: {0} code: {1}", icmpHeader.Type, icmpHeader.Code)); if (icmpHeader.Type == ICMPHeader.ICMPTypes.DestinationUnreachable && icmpHeader.Code == 3) { //Binary search the MTU (this is used during the probe phase of some congestion control //algorithms. Also, the initial congestion window should be calculated in terms of bytes i.e. (mtu/windowsize = packets) } break; case Protocol.TCP: //Console.WriteLine("TCP packet received"); break; case Protocol.UDP: UDPHeader udpHeader = new UDPHeader(header.Data, header.MessageLength); HandleUDP(header, udpHeader); break; case Protocol.Unknown: //Console.WriteLine("Unknown packet received"); break; default: throw new ArgumentOutOfRangeException(); } }
static void Main(string[] args) { Console.CancelKeyPress += delegate { _running = false; }; // open handle using (var handle = Diversion.WinDivertOpen("true", WinDivertLayer.Network, 100, 0)) { if (handle.IsInvalid) { Console.WriteLine("Unable to open handle. Error: " + Marshal.GetLastWin32Error()); return; } // prepare headers var ipHeader = new IPHeader(); var ipv6Header = new IPv6Header(); var icmpHeader = new ICMPHeader(); var icmpv6Header = new ICMPv6Header(); var tcpHeader = new TCPHeader(); var udpHeader = new UDPHeader(); var address = new Address(); byte[] buffer = new byte[65535]; uint receiveLength = 0; uint sendLength = 0; string processName; uint pid = 0; // loop while (_running) { pid = 0; } receiveLength = 0; sendLength = 0; fixed(byte *data = buffer) { Diversion.WinDivertHelperParsePacket(data, receiveLength, ipHeader, ipv6Header, icmpHeader, icmpv6Header, tcpHeader, udpHeader, null, null); } } }
private void Init() { data = new byte[BUFFER_SIZE]; host = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp); iep = new IPEndPoint(IPAddress.Parse(hostIP), 0); ep = (EndPoint)iep; packet = new ICMPHeader(); packet.Type = 0x08; packet.Code = 0x00; packet.Checksum = 0; Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, packet.Message, 0, 2); Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, packet.Message, 2, 2); data = Encoding.ASCII.GetBytes("a"); Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length); packet.Messagesize = data.Length + 4; packet.Checksum = packet.getChecksum(); host.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100); }
static void Main(string[] args) { // This is not really like the netdump example in the native WinDivert examples. Since we are // pulling the names of processes behind packet flows, we need to fully intercept/divert packets, // make the process query, then reinject. If we just sniff, the process will either be closed or // no longer bound to the local port the packet is associated with, and the process query will // be hit or miss (probably fail). So, by fully diverting rather than sniffing, we force // the process to hang open waiting for the packet while we check the process identity, then // hand the packet over untouched. // // Ideally you do not want to be querying the process on every single packet. Rather, you would // create a stucture that keeps track of a network flow, identify the process (protocol, whatever // else) one time, then only re-check when the flow has ended and a new flow has begun. This is // just for basic demonstration though, so we don't create and track any flows. // // Note also that the process identification is still not 100%. Many system processes run under // PID 4. I'm not satisfied with just getting SYSTEM for these processes, and I'd like to // ideally be able to identify exactly which processes they are. Still working on that. Console.WindowWidth = Console.LargestWindowWidth; bool running = true; Console.CancelKeyPress += delegate { running = false; }; Diversion diversion; string filter = "true"; try { diversion = Diversion.Open(filter, DivertLayer.Network, 100, 0); } catch(Exception e) { Console.WriteLine(e.Message); return; } if(!diversion.Handle.Valid) { Console.WriteLine("Failed to open divert handle with error {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error()); return; } IPHeader ipHeader = new IPHeader(); IPv6Header ipv6Header = new IPv6Header(); ICMPHeader icmpHeader = new ICMPHeader(); ICMPv6Header icmpv6Header = new ICMPv6Header(); TCPHeader tcpHeader = new TCPHeader(); UDPHeader udpHeader = new UDPHeader(); Address address = new Address(); byte[] buffer = new byte[65535]; uint receiveLength = 0; uint sendLength = 0; string processName; uint pid = 0; while (running) { pid = 0; receiveLength = 0; sendLength = 0; if (!diversion.Receive(buffer, address, ref receiveLength)) { Console.WriteLine("Failed to receive packet with error {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error()); continue; } diversion.ParsePacket(buffer, receiveLength, ipHeader, ipv6Header, icmpHeader, icmpv6Header, tcpHeader, udpHeader); if (ipHeader.Valid && tcpHeader.Valid) { Diversion.GetPacketProcess(address, tcpHeader, ipHeader, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv4 TCP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); Console.WriteLine(string.Format("ack: {0}, syn: {1}, len: {2}, seq: {3}", tcpHeader.Ack, tcpHeader.Syn, ipHeader.Length, tcpHeader.SequenceNumber)); } else if(ipHeader.Valid && udpHeader.Valid) { Diversion.GetPacketProcess(address, udpHeader, ipHeader, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv4 UDP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); } else if(ipv6Header.Valid && tcpHeader.Valid) { Diversion.GetPacketProcess(address, tcpHeader, ipv6Header, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv6 TCP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); Console.WriteLine(string.Format("ack: {0}, syn: {1}, len: {2}, seq: {3}", tcpHeader.Ack, tcpHeader.Syn, ipv6Header.Length, tcpHeader.SequenceNumber)); } else if (ipv6Header.Valid && udpHeader.Valid) { Diversion.GetPacketProcess(address, udpHeader, ipv6Header, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv6 UDP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); } if(address.Direction == DivertDirection.Outbound) { diversion.CalculateChecksums(buffer, receiveLength, 0); } diversion.SendAsync(buffer, receiveLength, address, ref sendLength); } diversion.Close(); }
public void ParseNetworkPacket(PacketRawInfo args) { IPHeader ipHeader = null; IPv6Header ipv6Header = null; EthernetHeader ethernetHeader = null; EthernetPacketType ethernetPackeType = EthernetPacketType.IpV4; PacketInfo packetInfo = new PacketInfo(); packetInfo.protocolE = PacketType.UNKNOWN; packetInfo.count = 1; if (args.linkLayer == LinkLayers.Ethernet) { ethernetHeader = new EthernetHeader(args.data, args.size); ethernetPackeType = ethernetHeader.EtherType; packetInfo.hardwareSource = ethernetHeader.SourceMac; packetInfo.harwareDestination = ethernetHeader.DestinationMac; packetInfo.protocol = ((Protocol)ethernetHeader.EtherType).ToString(); if (ethernetHeader.EtherType == EthernetPacketType.IpV4) { args.data = ethernetHeader.Payload; args.size = ethernetHeader.Payload.Length; } } else { packetInfo.protocol = Protocol.Iplt.ToString(); } switch (ethernetPackeType) { case EthernetPacketType.IpV4: ipHeader = new IPHeader(args.data, args.size); packetInfo.ipDestination = ipHeader.DestinationAddress.ToString(); packetInfo.ipSource = ipHeader.SourceAddress.ToString(); packetInfo.size = ipHeader.MessageLength; if (packetInfo.ipSource == incomingIP) { packetInfo.incoming = true; } Statistics.AddToIPPacketsStats(packetInfo.size, packetInfo.incoming); break; case EthernetPacketType.IpV6: ipv6Header = new IPv6Header(args.data, args.size); packetInfo.ipDestination = ipv6Header.DestinationAddress.ToString(); packetInfo.ipSource = ipv6Header.SourceAddress.ToString(); if (packetInfo.ipSource == incomingIP) { packetInfo.incoming = true; } Statistics.AddToIPPacketsStats(packetInfo.size, packetInfo.incoming); break; case EthernetPacketType.Arp: ARPHeader arpHeader = new ARPHeader(ethernetHeader.Payload, ethernetHeader.Payload.Length); packetInfo.ipDestination = arpHeader.TPA; packetInfo.ipSource = arpHeader.SPA; packetInfo.desription = arpHeader.Description; if (packetInfo.ipSource == incomingIP) { packetInfo.incoming = true; } packetInfo.size = arpHeader.Size; packetInfo.protocol = "ARP"; packetInfo.protocolE = PacketType.ARP; Statistics.AddToARPPacketsStats(packetInfo.size, packetInfo.incoming); break; case EthernetPacketType.WakeOnLan: break; default: packetInfo.desription = "неизвестный Ethernet протокол"; break; } if (ipHeader != null) { switch (ipHeader.ProtocolType) { case Protocol.Udp: NetworkShow.Network.Packets.UDPHeader udpheader = new UDPHeader(ipHeader.Data, ipHeader.Data.Length); packetInfo.portDestination = udpheader.DestinationPort; packetInfo.portSource = udpheader.SourcePort; packetInfo.size = udpheader.Length; packetInfo.protocol = "UDP"; packetInfo.protocolE = PacketType.UDP; packetInfo.active = "T"; Statistics.AddToUDPPacketsStats(packetInfo.size, packetInfo.incoming); break; case Protocol.Tcp: NetworkShow.Network.Packets.TCPHeader tcpheader = new TCPHeader(ipHeader.Data, ipHeader.Data.Length); packetInfo.portDestination = tcpheader.DestinationPort; packetInfo.portSource = tcpheader.SourcePort; packetInfo.size = tcpheader.MessageLength + tcpheader.HeaderLength; packetInfo.active = "T"; packetInfo.protocol = "TCP"; packetInfo.protocolE = PacketType.TCP; Statistics.AddToTCPPacketsStats(packetInfo.size, packetInfo.incoming); break; case Protocol.InternetControlMessageProtocol: NetworkShow.Network.Packets.ICMPHeader icmpheader = new ICMPHeader(ipHeader.Data, ipHeader.Data.Length); packetInfo.desription = icmpheader.Type.ToString(); packetInfo.size = icmpheader.Size; packetInfo.protocol = "ICMP"; packetInfo.protocolE = PacketType.ICMP; Statistics.AddToICMPPacketsStats(packetInfo.size, packetInfo.incoming); break; case Protocol.InternetGroupManagementProtocol: NetworkShow.Network.Packets.IGMPHeader igmpheader = new IGMPHeader(ipHeader.Data, ipHeader.Data.Length); packetInfo.desription = igmpheader.GroupAddress + " " + igmpheader.Type + " " + igmpheader.Version; packetInfo.size = igmpheader.Size; packetInfo.protocol = "IGMP"; packetInfo.protocolE = PacketType.IGMP; Statistics.AddToIGMPPacketsStats(packetInfo.size, packetInfo.incoming); break; default: packetInfo.desription = "неизвестный IP протокол"; packetInfo.protocol = ipHeader.ProtocolType.ToString(); packetInfo.protocolE = PacketType.UNKNOWN; packetInfo.size = ipHeader.MessageLength; break; } } //PacketsInfo.AddToQueue(packetInfo); int pos = -1; if ((packetInfo.protocol == "TCP") || (packetInfo.protocol == "UDP")) { //pos = FindConnection(packetInfo); pos = FindConnection(packetInfo); if (pos >= 0) { packetInfo = UpdateConnection(pos, packetInfo); UpdateInfoEvent(packetInfo.protocol); db.UpdateConnection(packetInfo.pos, packetInfo); } else { packetInfo.pos = db.SaveNewPacket(packetInfo); AddConnection(packetInfo); ChangeRowsCountEvent(packetInfo.protocolE, packetInfo.pos, packetInfo.portSource, packetInfo.portSource); } } else { int position = db.SaveNewPacket(packetInfo); ChangeRowsCountEvent(packetInfo.protocolE, position, packetInfo.portSource, packetInfo.portSource); } }
static void Main(string[] args) { // This is not really like the netdump example in the native WinDivert examples. Since we are // pulling the names of processes behind packet flows, we need to fully intercept/divert packets, // make the process query, then reinject. If we just sniff, the process will either be closed or // no longer bound to the local port the packet is associated with, and the process query will // be hit or miss (probably fail). So, by fully diverting rather than sniffing, we force // the process to hang open waiting for the packet while we check the process identity, then // hand the packet over untouched. // // Ideally you do not want to be querying the process on every single packet. Rather, you would // create a stucture that keeps track of a network flow, identify the process (protocol, whatever // else) one time, then only re-check when the flow has ended and a new flow has begun. This is // just for basic demonstration though, so we don't create and track any flows. // // Note also that the process identification is still not 100%. Many system processes run under // PID 4. I'm not satisfied with just getting SYSTEM for these processes, and I'd like to // ideally be able to identify exactly which processes they are. Still working on that. Console.WindowWidth = Console.LargestWindowWidth; bool running = true; Console.CancelKeyPress += delegate { running = false; }; Diversion diversion; string filter = "true"; try { diversion = Diversion.Open(filter, DivertLayer.Network, 100, 0); } catch (Exception e) { Console.WriteLine(e.Message); return; } if (!diversion.Handle.Valid) { Console.WriteLine("Failed to open divert handle with error {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error()); return; } IPHeader ipHeader = new IPHeader(); IPv6Header ipv6Header = new IPv6Header(); ICMPHeader icmpHeader = new ICMPHeader(); ICMPv6Header icmpv6Header = new ICMPv6Header(); TCPHeader tcpHeader = new TCPHeader(); UDPHeader udpHeader = new UDPHeader(); Address address = new Address(); byte[] buffer = new byte[65535]; uint receiveLength = 0; uint sendLength = 0; string processName; uint pid = 0; while (running) { pid = 0; receiveLength = 0; sendLength = 0; if (!diversion.Receive(buffer, address, ref receiveLength)) { Console.WriteLine("Failed to receive packet with error {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error()); continue; } diversion.ParsePacket(buffer, receiveLength, ipHeader, ipv6Header, icmpHeader, icmpv6Header, tcpHeader, udpHeader); if (ipHeader.Valid && tcpHeader.Valid) { Diversion.GetPacketProcess(address, tcpHeader, ipHeader, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv4 TCP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); Console.WriteLine(string.Format("ack: {0}, syn: {1}, len: {2}, seq: {3}", tcpHeader.Ack, tcpHeader.Syn, ipHeader.Length, tcpHeader.SequenceNumber)); } else if (ipHeader.Valid && udpHeader.Valid) { Diversion.GetPacketProcess(address, udpHeader, ipHeader, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv4 UDP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); } else if (ipv6Header.Valid && tcpHeader.Valid) { Diversion.GetPacketProcess(address, tcpHeader, ipv6Header, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv6 TCP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); Console.WriteLine(string.Format("ack: {0}, syn: {1}, len: {2}, seq: {3}", tcpHeader.Ack, tcpHeader.Syn, ipv6Header.Length, tcpHeader.SequenceNumber)); } else if (ipv6Header.Valid && udpHeader.Valid) { Diversion.GetPacketProcess(address, udpHeader, ipv6Header, ref pid, out processName); if (processName.Equals("SYSTEM", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("ERROR {0} and PID is {1}", System.Runtime.InteropServices.Marshal.GetLastWin32Error(), pid); } Console.WriteLine( "{0} IPv6 UDP packet captured destined for {1}:{2} from {3}:{4} {5}.", address.Direction == DivertDirection.Inbound ? "Inbound" : "Outbound", ipHeader.DestinationAddress.ToString(), tcpHeader.DestinationPort.ToString(), ipHeader.SourceAddress.ToString(), tcpHeader.SourcePort.ToString(), address.Direction == DivertDirection.Inbound ? string.Format("to process {0}", processName) : string.Format("from process {0}", processName) ); } if (address.Direction == DivertDirection.Outbound) { diversion.CalculateChecksums(buffer, receiveLength, 0); } diversion.SendAsync(buffer, receiveLength, address, ref sendLength); } diversion.Close(); }