Implementing filter functionality in C#

Home Forums Discussions Support Implementing filter functionality in C#

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #5413
    stsf
    Participant

      Hi guys, I was messing around with the sample code and noticed that the filter sample was only available in c++, and I have yet to figure out how to implement the C++ example in C#

      What would I have to do in the C# passthrough example so that packets of a particular port (let’s say, port 5000), always go through, while all of the other packets are passed in user mode?

      Right now, the default passthrough code processes each individual packet.

      Thanks in advance.

      #7183
      stsf
      Participant

        So I came up with somewhat of a solution to the post above, after heavy experimentation:

        Here is the C# version of the 2nd case in filter.cpp – process port 80, pass everything else:

        var filter1 = new STATIC_FILTER();

        filter1.m_Adapter = 0;
        filter1.m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND;
        filter1.m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
        filter1.m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;

        // Network layer filter
        filter1.m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
        filter1.m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL;
        filter1.m_NetworkFilter.m_IPv4.m_Protocol = 6;

        // Transport layer filter
        filter1.m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
        filter1.m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_DEST_PORT;
        filter1.m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; // HTTP
        filter1.m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80t;

        var filter2 = new STATIC_FILTER();

        filter2.m_Adapter = 0;
        filter2.m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE;
        filter2.m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
        filter2.m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;

        // Network layer filter
        filter2.m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
        filter2.m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL;
        filter2.m_NetworkFilter.m_IPv4.m_Protocol = 6;

        // Transport layer filter
        filter2.m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
        filter2.m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_SRC_PORT;
        filter2.m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; // HTTP
        filter2.m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80;

        /// IPV6
        ///
        var filter3 = new STATIC_FILTER();

        filter3.m_Adapter = 0;
        filter3.m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND;
        filter3.m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
        filter3.m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;

        // Network layer filter
        filter3.m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV6;
        filter3.m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V6_FILTER_PROTOCOL;
        filter3.m_NetworkFilter.m_IPv4.m_Protocol = 6;

        // Transport layer filter
        filter3.m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
        filter3.m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_DEST_PORT;
        filter3.m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; // HTTP
        filter3.m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80;

        var filter4 = new STATIC_FILTER();

        filter4.m_Adapter = 0;
        filter4.m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE;
        filter4.m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
        filter4.m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;

        // Network layer filter
        filter4.m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV6;
        filter4.m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V6_FILTER_PROTOCOL;
        filter4.m_NetworkFilter.m_IPv4.m_Protocol = 6;

        // Transport layer filter
        filter4.m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
        filter4.m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_SRC_PORT;
        filter4.m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; // HTTP
        filter4.m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80;

        var filter5 = new STATIC_FILTER();
        //filter5.m_Adapter.QuadPart = 0; // applied to all adapters
        filter5.m_Adapter = 0;
        filter5.m_ValidFields = 0;
        filter5.m_FilterAction = Ndisapi.FILTER_PACKET_PASS;
        filter5.m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE | Ndisapi.PACKET_FLAG_ON_SEND;

        //STATIC_FILTER[] filterarray = new STATIC_FILTER[5];
        //filterarray[0] = filter1;
        //filterarray[1] = filter2;
        //filterarray[2] = filter3;
        //filterarray[3] = filter4;
        //filterarray[4] = filter5;

        var filtertable = new STATIC_FILTER_TABLE();

        filtertable.m_TableSize = 5;
        filtertable.m_StaticFilters = new STATIC_FILTER[256];
        filtertable.m_StaticFilters[0] = filter1;
        filtertable.m_StaticFilters[1] = filter2;
        filtertable.m_StaticFilters[2] = filter3;
        filtertable.m_StaticFilters[3] = filter4;
        filtertable.m_StaticFilters[4] = filter5;

        Ndisapi.SetPacketFilterTable(driverPtr, ref filtertable);

        However – after figuring this out, I discovered a new issue that I can not solve:

        If my goal was to process every packed EXCEPT port 80, I would assume I would change Ndisapi.FILTER_PACKET_REDIRECT to Ndisapi.FILTER_PACKET_PASS; in the filters above and vice versa.

        However, when I do this, the packets to port 80 still end up being processed. I have tried re-arranging the order that I put them into the filter, and that did not yield any results

        I was wondering – how would it be possible to achieve this scenario – to process all packets EXCEPT a particular port?

        #7184
        Vadim Smirnov
        Keymaster

          I have ported filter sample to C#. Please refer the code below:

          using System;
          using System.Runtime.InteropServices;
          using System.Threading;
          using System.Net;
          using NdisApiWrapper;

          namespace Filter
          {
          class Program
          {
          static void Main(string[] args)
          {
          try
          {
          if (args.Length < 2)
          {
          Console.WriteLine(
          "Command line syntax:ntfilter.exe index scenario ntindex - network interface index.ntscenario - sample set of filters to load.ntYou can use ListAdapters to determine correct index.");
          Console.WriteLine("Available Scenarios:");
          Console.WriteLine("1 - Redirect only IPv4 DNS packets for processing in user mode.");
          Console.WriteLine("2 - Redirect only HTTP(TCP port 80) packets for processing in user mode. Both IPv4 and IPv6 protocols.");
          Console.WriteLine("3 - Drop all IPv4 ICMP packets. Redirect all other packets to user mode (default behaviour).");
          Console.WriteLine("4 - Block IPv4 access to http://www.ntkernel.com. Pass all other packets without processing in user mode.");
          Console.WriteLine("5 - Redirect only ARP/RARP packets to user mode. Pass all others.");
          return;
          }

          var adapterIndex = uint.Parse(args[0]);
          var scena = uint.Parse(args[1]);

          var driverPtr = Ndisapi.OpenFilterDriver();
          if (!Ndisapi.IsDriverLoaded(driverPtr))
          {
          Console.WriteLine("Driver not installed on this system of failed to load.");
          return;
          }

          // Retrieve adapter list
          var adapters = new TCP_AdapterList();
          Ndisapi.GetTcpipBoundAdaptersInfo(driverPtr, ref adapters);

          // Set tunnel mode for the selected network interface
          var mode = new ADAPTER_MODE
          {
          dwFlags = Ndisapi.MSTCP_FLAG_SENT_TUNNEL | Ndisapi.MSTCP_FLAG_RECV_TUNNEL,
          hAdapterHandle = adapters.m_nAdapterHandle[adapterIndex]
          };

          Ndisapi.SetAdapterMode(driverPtr, ref mode);

          // Create and set event for the adapter
          var manualResetEvent = new ManualResetEvent(false);
          Ndisapi.SetPacketEvent(driverPtr, adapters.m_nAdapterHandle[adapterIndex], manualResetEvent.SafeWaitHandle);

          var filtersTable = new STATIC_FILTER_TABLE();
          filtersTable.m_StaticFilters = new STATIC_FILTER[256];

          switch(scena)
          {
          case 1:
          filtersTable.m_TableSize = 3;

          //**************************************************************************************
          // 1. Outgoing DNS requests filter: REDIRECT OUT UDP packets with destination PORT 53
          // Common values
          filtersTable.m_StaticFilters[0].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[0].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;
          filtersTable.m_StaticFilters[0].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[0].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND;

          // Network layer filter
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_Protocol = 17; //IPPROTO_UDP

          // Transport layer filter
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_DEST_PORT;
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 53; // DNS
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 53;

          //****************************************************************************************
          // 2. Incoming DNS responses filter: REDIRECT IN UDP packets with source PORT 53
          // Common values
          filtersTable.m_StaticFilters[1].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[1].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;
          filtersTable.m_StaticFilters[1].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[1].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE;

          // Network layer filter
          filtersTable.m_StaticFilters[1].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
          filtersTable.m_StaticFilters[1].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL;
          filtersTable.m_StaticFilters[1].m_NetworkFilter.m_IPv4.m_Protocol = 17;//IPPROTO_UDP

          // Transport layer filter
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_SRC_PORT;
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_TcpUdp.m_SourcePort.m_StartRange = 53; // DNS
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_TcpUdp.m_SourcePort.m_EndRange = 53;

          //***************************************************************************************
          // 3. Pass all packets (skipped by previous filters) without processing in user mode
          // Common values
          filtersTable.m_StaticFilters[2].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[2].m_ValidFields = 0;
          filtersTable.m_StaticFilters[2].m_FilterAction = Ndisapi.FILTER_PACKET_PASS;
          filtersTable.m_StaticFilters[2].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE | Ndisapi.PACKET_FLAG_ON_SEND;

          break;

          case 2:
          filtersTable.m_TableSize = 5;

          //**************************************************************************************
          // 1. Outgoing HTTP requests filter: REDIRECT OUT TCP packets with destination PORT 80 IPv4
          // Common values
          filtersTable.m_StaticFilters[0].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[0].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;
          filtersTable.m_StaticFilters[0].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[0].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND;

          // Network layer filter
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_Protocol = 6;//IPPROTO_TCP

          // Transport layer filter
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_DEST_PORT;
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; // HTTP
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80;

          //****************************************************************************************
          // 2. Incoming HTTP responses filter: REDIRECT IN TCP packets with source PORT 80 IPv4
          // Common values
          filtersTable.m_StaticFilters[1].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[1].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;
          filtersTable.m_StaticFilters[1].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[1].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE;

          // Network layer filter
          filtersTable.m_StaticFilters[1].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
          filtersTable.m_StaticFilters[1].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL;
          filtersTable.m_StaticFilters[1].m_NetworkFilter.m_IPv4.m_Protocol = 6; //IPPROTO_TCP

          // Transport layer filter
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_SRC_PORT;
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_TcpUdp.m_SourcePort.m_StartRange = 80; // HTTP
          filtersTable.m_StaticFilters[1].m_TransportFilter.m_TcpUdp.m_SourcePort.m_EndRange = 80;

          //****************************************************************************************
          // 3. Outgoing HTTP requests filter: REDIRECT OUT TCP packets with destination PORT 80 IPv6
          // Common values
          filtersTable.m_StaticFilters[2].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[2].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;
          filtersTable.m_StaticFilters[2].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[2].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND;

          // Network layer filter
          filtersTable.m_StaticFilters[2].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV6;
          filtersTable.m_StaticFilters[2].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V6_FILTER_PROTOCOL;
          filtersTable.m_StaticFilters[2].m_NetworkFilter.m_IPv4.m_Protocol = 6; //IPPROTO_TCP

          // Transport layer filter
          filtersTable.m_StaticFilters[2].m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
          filtersTable.m_StaticFilters[2].m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_DEST_PORT;
          filtersTable.m_StaticFilters[2].m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; // HTTP
          filtersTable.m_StaticFilters[2].m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80;

          //****************************************************************************************
          // 4. Incoming HTTP responses filter: REDIRECT IN TCP packets with source PORT 80 IPv6
          // Common values
          filtersTable.m_StaticFilters[3].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[3].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;
          filtersTable.m_StaticFilters[3].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[3].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE;

          // Network layer filter
          filtersTable.m_StaticFilters[3].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV6;
          filtersTable.m_StaticFilters[3].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V6_FILTER_PROTOCOL;
          filtersTable.m_StaticFilters[3].m_NetworkFilter.m_IPv4.m_Protocol = 6;// IPPROTO_TCP

          // Transport layer filter
          filtersTable.m_StaticFilters[3].m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
          filtersTable.m_StaticFilters[3].m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_SRC_PORT;
          filtersTable.m_StaticFilters[3].m_TransportFilter.m_TcpUdp.m_SourcePort.m_StartRange = 80; // HTTP
          filtersTable.m_StaticFilters[3].m_TransportFilter.m_TcpUdp.m_SourcePort.m_EndRange = 80;

          //***************************************************************************************
          // 5. Pass all packets (skipped by previous filters) without processing in user mode
          // Common values
          filtersTable.m_StaticFilters[4].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[4].m_ValidFields = 0;
          filtersTable.m_StaticFilters[4].m_FilterAction = Ndisapi.FILTER_PACKET_PASS;
          filtersTable.m_StaticFilters[4].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE | Ndisapi.PACKET_FLAG_ON_SEND;

          break;

          case 3:
          filtersTable.m_TableSize = 5;

          //**************************************************************************************
          // 1. Block all ICMP packets
          // Common values
          filtersTable.m_StaticFilters[0].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[0].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID;
          filtersTable.m_StaticFilters[0].m_FilterAction = Ndisapi.FILTER_PACKET_DROP;
          filtersTable.m_StaticFilters[0].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND | Ndisapi.PACKET_FLAG_ON_RECEIVE;

          // Network layer filter
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_Protocol = 1;//IPPROTO_ICMP

          break;

          case 4:

          filtersTable.m_TableSize = 2;

          //**************************************************************************************
          // 1. Outgoing HTTP requests filter: DROP OUT TCP packets with destination IP 190.120.229.77 PORT 80 (http://www.ntkernel.com)
          // Common values
          filtersTable.m_StaticFilters[0].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[0].m_ValidFields = Ndisapi.NETWORK_LAYER_VALID | Ndisapi.TRANSPORT_LAYER_VALID;
          filtersTable.m_StaticFilters[0].m_FilterAction = Ndisapi.FILTER_PACKET_DROP;
          filtersTable.m_StaticFilters[0].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND;

          // Network layer filter
          var address = new in_addr();
          var mask = new in_addr();

          // IP address 190.120.229.77
          address.s_b1 = 23;
          address.s_b2 = 97;
          address.s_b3 = 138;
          address.s_b4 = 240;

          // Network mask 255.255.255.255
          mask.s_b1 = 255;
          mask.s_b2 = 255;
          mask.s_b3 = 255;
          mask.s_b4 = 255;

          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_dwUnionSelector = Ndisapi.IPV4;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_ValidFields = Ndisapi.IP_V4_FILTER_PROTOCOL | Ndisapi.IP_V4_FILTER_DEST_ADDRESS;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_DestAddress.m_AddressType = Ndisapi.IP_SUBNET_V4_TYPE;
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_DestAddress.m_IpSubnet.m_Ip = address.s_addr; // IP address
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_DestAddress.m_IpSubnet.m_IpMask = mask.s_addr; // network mask
          filtersTable.m_StaticFilters[0].m_NetworkFilter.m_IPv4.m_Protocol = 6; //IPPROTO_TCP

          // Transport layer filter
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_dwUnionSelector = Ndisapi.TCPUDP;
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_ValidFields = Ndisapi.TCPUDP_DEST_PORT;
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_DestPort.m_StartRange = 80; // HTTP
          filtersTable.m_StaticFilters[0].m_TransportFilter.m_TcpUdp.m_DestPort.m_EndRange = 80;

          //***************************************************************************************
          // 2. Pass all packets (skipped by previous filters) without processing in user mode
          // Common values
          filtersTable.m_StaticFilters[1].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[1].m_ValidFields = 0;
          filtersTable.m_StaticFilters[1].m_FilterAction = Ndisapi.FILTER_PACKET_PASS;
          filtersTable.m_StaticFilters[1].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE | Ndisapi.PACKET_FLAG_ON_SEND;

          break;

          case 5:

          filtersTable.m_TableSize = 3;

          //**************************************************************************************
          // 1. Redirects all ARP packets to be processes by user mode application
          // Common values
          filtersTable.m_StaticFilters[0].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[0].m_ValidFields = Ndisapi.DATA_LINK_LAYER_VALID;
          filtersTable.m_StaticFilters[0].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[0].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND | Ndisapi.PACKET_FLAG_ON_RECEIVE;
          filtersTable.m_StaticFilters[0].m_DataLinkFilter.m_dwUnionSelector = Ndisapi.ETH_802_3;
          filtersTable.m_StaticFilters[0].m_DataLinkFilter.m_Eth8023Filter.m_ValidFields = Ndisapi.ETH_802_3_PROTOCOL;
          filtersTable.m_StaticFilters[0].m_DataLinkFilter.m_Eth8023Filter.m_Protocol = 0x0806; // ETH_P_ARP;


          //**************************************************************************************
          // 1. Redirects all RARP packets to be processes by user mode application
          // Common values
          filtersTable.m_StaticFilters[1].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[1].m_ValidFields = Ndisapi.DATA_LINK_LAYER_VALID;
          filtersTable.m_StaticFilters[1].m_FilterAction = Ndisapi.FILTER_PACKET_REDIRECT;
          filtersTable.m_StaticFilters[1].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_SEND | Ndisapi.PACKET_FLAG_ON_RECEIVE;
          filtersTable.m_StaticFilters[1].m_DataLinkFilter.m_dwUnionSelector = Ndisapi.ETH_802_3;
          filtersTable.m_StaticFilters[1].m_DataLinkFilter.m_Eth8023Filter.m_ValidFields = Ndisapi.ETH_802_3_PROTOCOL;
          filtersTable.m_StaticFilters[1].m_DataLinkFilter.m_Eth8023Filter.m_Protocol = 0x0806; // ETH_P_ARP;


          //***************************************************************************************
          // 2. Pass all packets (skipped by previous filters) without processing in user mode
          // Common values
          filtersTable.m_StaticFilters[2].m_Adapter = 0; // applied to all adapters
          filtersTable.m_StaticFilters[2].m_ValidFields = 0;
          filtersTable.m_StaticFilters[2].m_FilterAction = Ndisapi.FILTER_PACKET_PASS;
          filtersTable.m_StaticFilters[2].m_dwDirectionFlags = Ndisapi.PACKET_FLAG_ON_RECEIVE | Ndisapi.PACKET_FLAG_ON_SEND;

          break;
          default:
          Console.WriteLine ("Unknown test scenario specified. Exiting.");
          return;
          }

          // Load filters into driver
          Ndisapi.SetPacketFilterTable(driverPtr, ref filtersTable);

          // Allocate and initialize packet structures
          var request = new ETH_REQUEST();
          var buffer = new INTERMEDIATE_BUFFER();
          var bufferPtr = Marshal.AllocHGlobal(Marshal.SizeOf(buffer));

          Win32Api.ZeroMemory(bufferPtr, Marshal.SizeOf(buffer));

          request.hAdapterHandle = adapters.m_nAdapterHandle[adapterIndex];
          request.EthPacket.Buffer = bufferPtr;

          while(true)
          {
          manualResetEvent.WaitOne();

          while (Ndisapi.ReadPacket(driverPtr, ref request))
          {
          buffer = (INTERMEDIATE_BUFFER)Marshal.PtrToStructure(bufferPtr, typeof(INTERMEDIATE_BUFFER));

          WriteToConsole(buffer, bufferPtr);

          if (buffer.m_dwDeviceFlags == Ndisapi.PACKET_FLAG_ON_SEND)
          Ndisapi.SendPacketToAdapter(driverPtr, ref request);
          else
          Ndisapi.SendPacketToMstcp(driverPtr, ref request);
          }

          manualResetEvent.Reset();
          }
          }
          catch (Exception ex)
          {
          Console.WriteLine(ex);
          }
          }

          private unsafe static void WriteToConsole(INTERMEDIATE_BUFFER packetBuffer, IntPtr packetBufferPtr)
          {
          Console.WriteLine(packetBuffer.m_dwDeviceFlags == Ndisapi.PACKET_FLAG_ON_SEND ? "nMSTCP --> Interface" : "nInterface --> MSTCP");
          Console.WriteLine("Packet size = {0}", packetBuffer.m_Length);

          var ethernetHeader = (ETHER_HEADER*)((byte*)packetBufferPtr + (Marshal.OffsetOf(typeof(INTERMEDIATE_BUFFER), "m_IBuffer")).ToInt32());
          Console.WriteLine(
          "tETHERNET {0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2} --> {6:X2}{7:X2}{8:X2}{9:X2}{10:X2}{11:X2}",
          ethernetHeader->source.b1,
          ethernetHeader->source.b2,
          ethernetHeader->source.b3,
          ethernetHeader->source.b4,
          ethernetHeader->source.b5,
          ethernetHeader->source.b6,
          ethernetHeader->dest.b1,
          ethernetHeader->dest.b2,
          ethernetHeader->dest.b3,
          ethernetHeader->dest.b4,
          ethernetHeader->dest.b5,
          ethernetHeader->dest.b6
          );

          switch (ntohs(ethernetHeader->proto))
          {
          case ETHER_HEADER.ETH_P_IP:
          {
          var ipHeader = (IPHeader*)((byte*)ethernetHeader + Marshal.SizeOf(typeof(ETHER_HEADER)));

          var sourceAddress = new IPAddress(ipHeader->Src);
          var destinationAddress = new IPAddress(ipHeader->Dest);

          Console.WriteLine("tIP {0} --> {1} PROTOCOL: {2}", sourceAddress, destinationAddress, ipHeader->P);

          var tcpHeader = ipHeader->P == IPHeader.IPPROTO_TCP ? (TcpHeader*)((byte*)ipHeader + ((ipHeader->IPLenVer) & 0xF) * 4) : null;
          var udpHeader = ipHeader->P == IPHeader.IPPROTO_UDP ? (UdpHeader*)((byte*)ipHeader + ((ipHeader->IPLenVer) & 0xF) * 4) : null;

          if (udpHeader != null)
          Console.WriteLine("tUDP SRC PORT: {0} DST PORT: {1}", ntohs(udpHeader->th_sport), ntohs(udpHeader->th_dport));

          if (tcpHeader != null)
          Console.WriteLine("tTCP SRC PORT: {0} DST PORT: {1}", ntohs(tcpHeader->th_sport), ntohs(tcpHeader->th_dport));
          }
          break;
          case ETHER_HEADER.ETH_P_RARP:
          Console.WriteLine("tReverse Addr Res packet");
          break;
          case ETHER_HEADER.ETH_P_ARP:
          Console.WriteLine("tAddress Resolution packet");
          break;
          }
          }

          static ushort ntohs(ushort netshort)
          {
          var hostshort = (ushort)(((netshort >> 8) & 0x00FF) | ((netshort << 8) & 0xFF00));
          return hostshort;
          }

          [StructLayout(LayoutKind.Explicit, Size = 4)]
          internal struct in_addr
          {
          [FieldOffset(0)]
          internal byte s_b1;
          [FieldOffset(1)]
          internal byte s_b2;
          [FieldOffset(2)]
          internal byte s_b3;
          [FieldOffset(3)]
          internal byte s_b4;

          [FieldOffset(0)]
          internal ushort s_w1;
          [FieldOffset(2)]
          internal ushort s_w2;

          [FieldOffset(0)]
          internal uint S_addr;

          ///
          /// can be used for most tcp & ip code
          ///

          internal uint s_addr
          {
          get { return S_addr; }
          }

          ///
          /// host on imp
          ///

          internal byte s_host
          {
          get { return s_b2; }
          }

          ///
          /// network
          ///

          internal byte s_net
          {
          get { return s_b1; }
          }

          ///
          /// imp
          ///

          internal ushort s_imp
          {
          get { return s_w2; }
          }

          ///
          /// imp #
          ///

          internal byte s_impno
          {
          get { return s_b4; }
          }

          ///
          /// logical host
          ///

          internal byte s_lh
          {
          get { return s_b3; }
          }
          }
          }
          }
        Viewing 3 posts - 1 through 3 (of 3 total)
        • You must be logged in to reply to this topic.