Implementing filter functionality in C#

Home Forums Discussions Support Portal Implementing filter functionality in C#

This topic contains 2 replies, has 2 voices, and was last updated by  Vadim Smirnov 2 years, 6 months ago.

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
    Moderator

    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.