Browse Source

Add files via upload

Machtergreifung 3 years ago
parent
commit
1581aac60a

+ 1045 - 0
NetFilterHelper/3rd/NFSDK2/nfapinet.cs

@@ -0,0 +1,1045 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace nfapinet 
+{
+     public enum NF_STATUS
+	{
+		NF_STATUS_SUCCESS		= 0,
+		NF_STATUS_FAIL			= -1,
+		NF_STATUS_INVALID_ENDPOINT_ID	= -2,
+		NF_STATUS_NOT_INITIALIZED	= -3,
+		NF_STATUS_IO_ERROR		= -4
+	};
+
+	public enum NF_DIRECTION
+	{
+		NF_D_IN = 1,		// Incoming TCP connection or UDP packet
+		NF_D_OUT = 2,		// Outgoing TCP connection or UDP packet
+		NF_D_BOTH = 3		// Any direction
+	};
+
+	public enum NF_FILTERING_FLAG
+	{
+		NF_ALLOW = 0,		// Allow the activity without filtering transmitted packets
+		NF_BLOCK = 1,		// Block the activity
+		NF_FILTER = 2,		// Filter the transmitted packets
+		NF_SUSPENDED = 4,	// Suspend receives from server and sends from client
+		NF_OFFLINE = 8,		// Emulate establishing a TCP connection with remote server
+		NF_INDICATE_CONNECT_REQUESTS = 16, // Indicate outgoing connect requests to API
+		NF_DISABLE_REDIRECT_PROTECTION = 32, // Disable blocking indicating connect requests for outgoing connections of local proxies
+        NF_PEND_CONNECT_REQUEST = 64, // Pend outgoing connect request to complete it later using nf_complete(TCP|UDP)ConnectRequest
+        NF_FILTER_AS_IP_PACKETS = 128, // Indicate the traffic as IP packets via ipSend/ipReceive
+        NF_READONLY = 256,				// Don't block the IP packets and indicate them to ipSend/ipReceive only for monitoring
+        NF_CONTROL_FLOW = 512,			// Use the flow limit rules even without NF_FILTER flag
+		NF_REDIRECT = 1024,			// Redirect the outgoing TCP connections to address specified in redirectTo
+    };
+
+    public enum NF_FLAGS
+    {
+	    NFF_NONE = 0, 
+	    NFF_DONT_DISABLE_TEREDO	= 1, // Don't disable Teredo 
+	    NFF_DONT_DISABLE_TCP_OFFLOADING	= 2, // Don't disable TCP offloading
+	    NFF_DISABLE_AUTO_REGISTER	= 4, // Dont' try to register the driver automatically
+	    NFF_DISABLE_AUTO_START	= 8,    // Dont' try to start the driver automatically
+    };
+
+
+    public enum NF_CONSTS
+    {
+		NF_MAX_ADDRESS_LENGTH = 28,
+		NF_MAX_IP_ADDRESS_LENGTH = 16
+    };
+
+    public enum NF_DRIVER_TYPE
+    {
+	    DT_UNKNOWN = 0,
+	    DT_TDI = 1,
+	    DT_WFP = 2
+    };
+
+	/**
+	*	Filtering rule
+	**/
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_RULE
+	{
+        public int protocol;	// IPPROTO_TCP or IPPROTO_UDP        
+        public UInt32 processId;	// Process identifier
+        public Byte direction;	// See NF_DIRECTION
+        public ushort localPort;	// Local port
+        public ushort remotePort;	// Remote port
+        public ushort ip_family;	// AF_INET for IPv4 and AF_INET6 for IPv6
+		
+		// Local IP (or network if localIpAddressMask is not zero)
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst=(int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] localIpAddress;	
+		
+		// Local IP mask
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] localIpAddressMask; 
+		
+		// Remote IP (or network if remoteIpAddressMask is not zero)
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] remoteIpAddress; 
+		
+		// Remote IP mask
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] remoteIpAddressMask;
+
+        public UInt32 filteringFlag;	// See NF_FILTERING_FLAG
+	};
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_PORT_RANGE
+    {
+        public ushort valueLow;
+        public ushort valueHigh;
+    };
+
+    /**
+    *	Filtering rule with additional fields
+    **/
+    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
+    public struct NF_RULE_EX
+    {
+        public int protocol;	// IPPROTO_TCP or IPPROTO_UDP        
+        public UInt32 processId;	// Process identifier
+        public Byte direction;	// See NF_DIRECTION
+        public ushort localPort;	// Local port
+        public ushort remotePort;	// Remote port
+        public ushort ip_family;	// AF_INET for IPv4 and AF_INET6 for IPv6
+
+        // Local IP (or network if localIpAddressMask is not zero)
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] localIpAddress;
+
+        // Local IP mask
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] localIpAddressMask;
+
+        // Remote IP (or network if remoteIpAddressMask is not zero)
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] remoteIpAddress;
+
+        // Remote IP mask
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+        public byte[] remoteIpAddressMask;
+
+        public UInt32 filteringFlag;	// See NF_FILTERING_FLAG
+
+        // Tail part of the process path mask 
+        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
+        public string processName;
+
+	    public NF_PORT_RANGE	localPortRange; // Local port(s)
+	    public NF_PORT_RANGE	remotePortRange; // Remote port(s)
+
+	    // Remote address for redirection as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
+	    [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_ADDRESS_LENGTH)]
+        public byte[] redirectTo;
+	    
+        // Process identifier of a local proxy
+	    public UInt32 localProxyProcessId;	
+    };
+
+	/**
+	*	TCP connection properties
+	**/
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_TCP_CONN_INFO
+	{
+		public UInt32	filteringFlag;	// See NF_FILTERING_FLAG
+        public UInt32 processId;		// Process identifier
+        public Byte direction;		// See NF_DIRECTION
+        public ushort ip_family;		// AF_INET for IPv4 and AF_INET6 for IPv6
+		
+		// Local address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_ADDRESS_LENGTH)]
+        public byte[] localAddress; 
+		
+		// Remote address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_ADDRESS_LENGTH)]
+        public byte[] remoteAddress;
+	};
+
+	/**
+	*	UDP endpoint properties
+	**/
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_UDP_CONN_INFO
+	{
+        public UInt32 processId;		// Process identifier
+        public ushort ip_family;		// AF_INET for IPv4 and AF_INET6 for IPv6
+		
+		// Local address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_ADDRESS_LENGTH)]
+        public byte[] localAddress; 
+	};
+
+    /**
+    *	UDP options
+    **/
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_UDP_OPTIONS
+    {
+        public UInt32 flags;		// UDP flags
+        public Int32 optionsLength; // options length
+        [MarshalAs(UnmanagedType.ByValArray)]
+        public byte[] options; // Options array
+    };
+
+	/**
+	*	UDP connect request properties
+	**/
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_UDP_CONN_REQUEST
+	{
+        public UInt32 filteringFlag;	// See NF_FILTERING_FLAG
+        public UInt32 processId;		// Process identifier
+        public ushort ip_family;		// AF_INET for IPv4 and AF_INET6 for IPv6
+		
+		// Local address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_ADDRESS_LENGTH)]
+        public byte[] localAddress; 
+
+		// Remote address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_ADDRESS_LENGTH)]
+        public byte[] remoteAddress;
+	};
+
+    public enum NF_IP_FLAG
+    {
+        NFIF_NONE = 0,		// No flags
+        NFIF_READONLY = 1,	// The packet was not blocked and indicated only for monitoring in read-only mode 
+                            // (see NF_READ_ONLY flags from NF_FILTERING_FLAG).
+    };
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_IP_PACKET_OPTIONS
+    {	
+	    public ushort	ip_family;	// AF_INET for IPv4 and AF_INET6 for IPv6
+	    public UInt32   ipHeaderSize;	// Size in bytes of IP header
+	    public UInt32	compartmentId;  // Network routing compartment identifier (can be zero)
+	    public UInt32	interfaceIndex; // Index of the interface on which the original packet data was received (irrelevant to outgoing packets)
+        public UInt32   subInterfaceIndex;	// Index of the subinterface on which the original packet data was received (irrelevant to outgoing packets)
+        public UInt32   flags;				// Can be a combination of flags from NF_IP_FLAG enumeration
+    };
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_FLOWCTL_DATA
+    {
+        public ulong inLimit;
+        public ulong outLimit;
+    };
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_FLOWCTL_MODIFY_DATA
+    {
+        public UInt32 fcHandle;
+        public NF_FLOWCTL_DATA	data;
+    };
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_FLOWCTL_STAT
+    {
+        public ulong inBytes;
+        public ulong outBytes;
+    };
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct NF_FLOWCTL_SET_DATA
+    {
+        public ulong endpointId;
+        public UInt32 fcHandle;
+    };
+
+    /**
+    *	Binding rule
+    **/
+    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
+    public struct NF_BINDING_RULE
+    {
+        // IPPROTO_TCP or IPPROTO_UDP
+        public int		protocol;	
+
+        // Process identifier
+	    public UInt32	processId;	
+
+	    // Tail part of the process path mask 
+        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
+        public string   processName;
+
+        // Local port
+	    public ushort	localPort;	
+
+        // AF_INET for IPv4 and AF_INET6 for IPv6
+	    public ushort	ip_family;	
+    	
+	    // Local IP (or network if localIpAddressMask is not zero)
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+	    public byte[]	localIpAddress;	
+    	
+	    // Local IP mask
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+	    public byte[]	localIpAddressMask; 
+    	
+	    // Redirect bind request to this IP 
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)]
+	    public byte[]	newLocalIpAddress; 
+
+	    // Redirect bind request to this port, if it is not zero
+	    public ushort	newLocalPort;
+
+        // See NF_FILTERING_FLAG, NF_ALLOW or NF_FILTER
+	    public ulong	filteringFlag;	
+    };
+
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_threadStart();
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_threadEnd();
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_tcpConnectRequest(ulong id, ref NF_TCP_CONN_INFO pConnInfo);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_tcpConnected(ulong id, ref NF_TCP_CONN_INFO pConnInfo);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_tcpClosed(ulong id, ref NF_TCP_CONN_INFO pConnInfo);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_tcpReceive(ulong id, IntPtr buf, int len);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_tcpSend(ulong id, IntPtr buf, int len);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_tcpCanReceive(ulong id);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_tcpCanSend(ulong id);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_udpCreated(ulong id, ref NF_UDP_CONN_INFO pConnInfo);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_udpConnectRequest(ulong id, ref NF_UDP_CONN_REQUEST pConnReq);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_udpClosed(ulong id, ref NF_UDP_CONN_INFO pConnInfo);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_udpReceive(ulong id, IntPtr remoteAddress, IntPtr buf, int len, IntPtr options);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_udpSend(ulong id, IntPtr remoteAddress, IntPtr buf, int len, IntPtr options);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_udpCanReceive(ulong id);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_udpCanSend(ulong id);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_ipReceive(IntPtr buf, int len, ref NF_IP_PACKET_OPTIONS ipOptions);
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void cbd_ipSend(IntPtr buf, int len, ref NF_IP_PACKET_OPTIONS ipOptions);
+    
+    /*
+     * Event handler interface
+     */
+    public interface NF_EventHandler
+    {
+        void threadStart();
+        void threadEnd();
+	    void tcpConnectRequest(ulong id, ref NF_TCP_CONN_INFO pConnInfo);
+        void tcpConnected(ulong id, NF_TCP_CONN_INFO pConnInfo);
+        void tcpClosed(ulong id, NF_TCP_CONN_INFO pConnInfo);
+        void tcpReceive(ulong id, IntPtr buf, int len);
+        void tcpSend(ulong id, IntPtr buf, int len);
+        void tcpCanReceive(ulong id);
+        void tcpCanSend(ulong id);
+        void udpCreated(ulong id, NF_UDP_CONN_INFO pConnInfo);
+        void udpConnectRequest(ulong id, ref NF_UDP_CONN_REQUEST pConnReq);
+        void udpClosed(ulong id, NF_UDP_CONN_INFO pConnInfo);
+        void udpReceive(ulong id, IntPtr remoteAddress, IntPtr buf, int len, IntPtr options, int optionsLen);
+        void udpSend(ulong id, IntPtr remoteAddress, IntPtr buf, int len, IntPtr options, int optionsLen);
+        void udpCanReceive(ulong id);
+        void udpCanSend(ulong id);
+    };
+
+    /*
+     * IP event handler interface
+     */
+    public interface NF_IPEventHandler
+    {
+        void ipReceive(IntPtr buf, int len, ref NF_IP_PACKET_OPTIONS ipOptions);
+        void ipSend(IntPtr buf, int len, ref NF_IP_PACKET_OPTIONS ipOptions);
+    };
+
+    /*
+     *  Internal events forwarder
+     */
+    class NF_EventHandlerFwd
+    {
+        public static NF_EventHandler m_pEventHandler = null;
+        
+        public static void threadStart()
+        {
+            m_pEventHandler.threadStart();
+        }
+        public static void threadEnd()
+        {
+            m_pEventHandler.threadEnd();
+        }
+	    public static void tcpConnectRequest(ulong id, ref NF_TCP_CONN_INFO pConnInfo)
+        {
+            m_pEventHandler.tcpConnectRequest(id, ref pConnInfo);
+        }
+        public static void tcpConnected(ulong id, ref NF_TCP_CONN_INFO pConnInfo)
+        {
+            m_pEventHandler.tcpConnected(id, pConnInfo);
+        }
+        public static void tcpClosed(ulong id, ref NF_TCP_CONN_INFO pConnInfo)
+        {
+            m_pEventHandler.tcpClosed(id, pConnInfo);
+        }
+        public static void tcpReceive(ulong id, IntPtr buf, int len)
+        {
+            m_pEventHandler.tcpReceive(id, buf, len);
+        }
+        public static void tcpSend(ulong id, IntPtr buf, int len)
+        {
+            m_pEventHandler.tcpSend(id, buf, len);
+        }
+        public static void tcpCanReceive(ulong id)
+        {
+            m_pEventHandler.tcpCanReceive(id);
+        }
+        public static void tcpCanSend(ulong id)
+        {
+            m_pEventHandler.tcpCanSend(id);
+        }
+        public static void udpCreated(ulong id, ref NF_UDP_CONN_INFO pConnInfo)
+        {
+            m_pEventHandler.udpCreated(id, pConnInfo);
+        }
+        public static void udpConnectRequest(ulong id, ref NF_UDP_CONN_REQUEST pConnReq)
+        {
+            m_pEventHandler.udpConnectRequest(id, ref pConnReq);
+        }
+        public static void udpClosed(ulong id, ref NF_UDP_CONN_INFO pConnInfo)
+        {
+            m_pEventHandler.udpClosed(id, pConnInfo);
+        }
+        public static void udpReceive(ulong id, IntPtr remoteAddress, IntPtr buf, int len, IntPtr options)
+        {
+            if (options.ToInt64() != 0)
+            {
+                NF_UDP_OPTIONS optionsCopy = (NF_UDP_OPTIONS)Marshal.PtrToStructure((IntPtr)options, typeof(NF_UDP_OPTIONS));
+                int optionsLen = 8 + optionsCopy.optionsLength;
+                m_pEventHandler.udpReceive(id, remoteAddress, buf, len, options, optionsLen);
+            }
+            else
+            {
+                m_pEventHandler.udpReceive(id, remoteAddress, buf, len, (IntPtr)null, 0);
+            }
+        }
+        public static void udpSend(ulong id, IntPtr remoteAddress, IntPtr buf, int len, IntPtr options)
+        {
+            if (options.ToInt64() != 0)
+            {
+                NF_UDP_OPTIONS optionsCopy = (NF_UDP_OPTIONS)Marshal.PtrToStructure((IntPtr)options, typeof(NF_UDP_OPTIONS));
+                int optionsLen = 8 + optionsCopy.optionsLength;
+                m_pEventHandler.udpSend(id, remoteAddress, buf, len, options, optionsLen);
+            }
+            else
+            {
+                m_pEventHandler.udpSend(id, remoteAddress, buf, len, (IntPtr)null, 0);
+            }
+        }
+        public static void udpCanReceive(ulong id)
+        {
+            m_pEventHandler.udpCanReceive(id);
+        }
+        public static void udpCanSend(ulong id)
+        {
+            m_pEventHandler.udpCanSend(id);
+        }
+    };
+
+    /*
+     *  Internal IP events forwarder
+     */
+    class NF_IPEventHandlerFwd
+    {
+        public static NF_IPEventHandler m_pEventHandler = null;
+
+        public static void ipReceive(IntPtr buf, int len, ref NF_IP_PACKET_OPTIONS ipOptions)
+        {
+            m_pEventHandler.ipReceive(buf, len, ref ipOptions);
+        }
+        public static void ipSend(IntPtr buf, int len, ref NF_IP_PACKET_OPTIONS ipOptions)
+        {
+            m_pEventHandler.ipSend(buf, len, ref ipOptions);
+        }
+    };
+
+    /*
+     *  Event handler structure for C API
+     */
+    [StructLayout(LayoutKind.Sequential, Pack=1)]
+	struct NF_EventHandlerInternal
+	{
+		public cbd_threadStart threadStart;
+		public cbd_threadEnd threadEnd;
+		public cbd_tcpConnectRequest tcpConnectRequest;
+		public cbd_tcpConnected tcpConnected;
+		public cbd_tcpClosed tcpClosed;
+		public cbd_tcpReceive tcpReceive;
+		public cbd_tcpSend tcpSend;
+		public cbd_tcpCanReceive tcpCanReceive;
+		public cbd_tcpCanSend tcpCanSend;
+		public cbd_udpCreated udpCreated;
+		public cbd_udpConnectRequest udpConnectRequest;
+        public cbd_udpClosed udpClosed;
+		public cbd_udpReceive udpReceive;
+		public cbd_udpSend udpSend;
+		public cbd_udpCanReceive udpCanReceive;
+		public cbd_udpCanSend udpCanSend;
+    };
+
+    /*
+     *  IP event handler structure for C API
+     */
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    struct NF_IPEventHandlerInternal
+    {
+        public cbd_ipReceive ipReceive;
+        public cbd_ipSend ipSend;
+    };
+
+    // Managed wrapper over API 
+	public class NFAPI
+	{
+        private static IntPtr m_pEventHandlerRaw = (IntPtr)null;
+        private static NF_EventHandlerInternal m_pEventHandler;
+        private static IntPtr m_pIPEventHandlerRaw = (IntPtr)null;
+        private static NF_IPEventHandlerInternal m_pIPEventHandler;
+
+		/**
+		* Initializes the internal data structures and starts the filtering thread.
+		* @param driverName The name of hooking driver, without ".sys" extension.
+		* @param pHandler Pointer to event handling object
+		**/
+        [DllImport("nfapinet", CallingConvention=CallingConvention.Cdecl)]
+		public static extern NF_STATUS nf_init(String driverName, IntPtr pHandler);
+        
+        public static NF_STATUS nf_init(String driverName, NF_EventHandler pHandler)
+        {
+            NF_EventHandlerFwd.m_pEventHandler = pHandler;
+
+            nf_adjustProcessPriviledges();
+
+            m_pEventHandler = new NF_EventHandlerInternal();
+             
+            m_pEventHandler.threadStart = new cbd_threadStart(NF_EventHandlerFwd.threadStart);
+            m_pEventHandler.threadEnd = new cbd_threadEnd(NF_EventHandlerFwd.threadEnd);
+            m_pEventHandler.tcpConnectRequest = new cbd_tcpConnectRequest(NF_EventHandlerFwd.tcpConnectRequest);
+            m_pEventHandler.tcpConnected = new cbd_tcpConnected(NF_EventHandlerFwd.tcpConnected);
+            m_pEventHandler.tcpClosed = new cbd_tcpClosed(NF_EventHandlerFwd.tcpClosed);
+            m_pEventHandler.tcpReceive = new cbd_tcpReceive(NF_EventHandlerFwd.tcpReceive);
+            m_pEventHandler.tcpSend = new cbd_tcpSend(NF_EventHandlerFwd.tcpSend);
+            m_pEventHandler.tcpCanReceive = new cbd_tcpCanReceive(NF_EventHandlerFwd.tcpCanReceive);
+            m_pEventHandler.tcpCanSend = new cbd_tcpCanSend(NF_EventHandlerFwd.tcpCanSend);
+            m_pEventHandler.udpCreated = new cbd_udpCreated(NF_EventHandlerFwd.udpCreated);
+            m_pEventHandler.udpConnectRequest = new cbd_udpConnectRequest(NF_EventHandlerFwd.udpConnectRequest);
+            m_pEventHandler.udpClosed = new cbd_udpClosed(NF_EventHandlerFwd.udpClosed);
+            m_pEventHandler.udpReceive = new cbd_udpReceive(NF_EventHandlerFwd.udpReceive);
+            m_pEventHandler.udpSend = new cbd_udpSend(NF_EventHandlerFwd.udpSend);
+            m_pEventHandler.udpCanReceive = new cbd_udpCanReceive(NF_EventHandlerFwd.udpCanReceive);
+            m_pEventHandler.udpCanSend = new cbd_udpCanSend(NF_EventHandlerFwd.udpCanSend);
+
+            m_pEventHandlerRaw = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NF_EventHandlerInternal)));
+            Marshal.StructureToPtr(m_pEventHandler, m_pEventHandlerRaw, true);
+
+            return nf_init(driverName, m_pEventHandlerRaw);
+        }
+
+		/**
+		* Stops the filtering thread, breaks all filtered connections and closes
+		* a connection with the hooking driver.
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void nf_free();
+
+		/**
+		* Registers and starts a driver with specified name (without ".sys" extension)
+		* @param driverName 
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_registerDriver(String driverName);
+
+        /**
+        * Registers and starts a driver with specified name (without ".sys" extension) and path to driver folder
+        * @param driverName 
+        * @param driverPath 
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_registerDriverEx(String driverName, String driverPath);
+
+        /**
+		* Unregisters a driver with specified name (without ".sys" extension)
+		* @param driverName 
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_unRegisterDriver(String driverName);
+
+
+		//
+		// TCP control routines
+		//
+
+		/**
+		* Suspends or resumes indicating of sends and receives for specified connection.
+		* @param id Connection identifier
+		* @param suspended true for suspend, false for resume 
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_tcpSetConnectionState(ulong id, int suspended);
+
+		/**
+		* Sends the buffer to remote server via specified connection.
+		* @param id Connection identifier
+		* @param buf Pointer to data buffer
+		* @param len Buffer length
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_tcpPostSend(ulong id, IntPtr buf, int len);
+
+		/**
+		* Indicates the buffer to local process via specified connection.
+		* @param id Unique connection identifier
+		* @param buf Pointer to data buffer
+		* @param len Buffer length
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_tcpPostReceive(ulong id, IntPtr buf, int len);
+
+		/**
+		* Breaks the connection with given id.
+		* @param id Connection identifier
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_tcpClose(ulong id);
+
+		//
+		// UDP control routines
+		//
+
+		/**
+		* Suspends or resumes indicating of sends and receives for specified socket.
+		* @param id Socket identifier
+		* @param suspended true for suspend, false for resume 
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_udpSetConnectionState(ulong id, int suspended);
+
+		/**
+		* Sends the buffer to remote server via specified socket.
+		* @param id Socket identifier
+		* @param remoteAddress Destination address
+		* @param buf Pointer to data buffer
+		* @param len Buffer length
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_udpPostSend(ulong id, 
+			IntPtr remoteAddress, 
+			IntPtr buf, int len,
+			IntPtr options);
+
+        /**
+        * Indicates the buffer to local process via specified socket.
+        * @param id Unique connection identifier
+        * @param remoteAddress Source address
+        * @param buf Pointer to data buffer
+        * @param len Buffer length
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_udpPostReceive(ulong id, 
+			IntPtr remoteAddress, 
+			IntPtr buf, int len,
+			IntPtr options);
+
+	/**
+	* Indicates a packet to TCP/IP stack
+	* @param buf Pointer to IP packet
+	* @param len Buffer length
+	* @param options IP options
+	**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_ipPostReceive(
+            IntPtr buf, int len,
+            ref NF_IP_PACKET_OPTIONS options);
+
+	/**
+	* Sends a packet to remote IP
+	* @param buf Pointer to IP packet
+	* @param len Buffer length
+	* @param options IP options
+	**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_ipPostSend(
+            IntPtr buf, int len,
+            ref NF_IP_PACKET_OPTIONS options);
+
+		//
+		// Filtering rules 
+		//
+
+		/**
+		* Add a rule to the head of rules list in driver.
+		* @param pRule See <tt>NF_RULE</tt>
+		* @param toHead TRUE (1) - add rule to list head, FALSE (0) - add rule to tail
+		**/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern NF_STATUS nf_addRule(ref NF_RULE pRule, int toHead);
+
+        private static void updateAddressLength(ref byte[] buf)
+        {
+            if (buf == null)
+            {
+                buf = new byte[(int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH];
+            }
+            else
+            {
+                if (buf.Length < (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH)
+                {
+                    Array.Resize(ref buf, (int)NF_CONSTS.NF_MAX_IP_ADDRESS_LENGTH);
+                }
+            }
+        }
+
+        public static NF_STATUS nf_addRule(NF_RULE pRule, int toHead)
+        {
+            updateAddressLength(ref pRule.localIpAddress);
+            updateAddressLength(ref pRule.localIpAddressMask);
+            updateAddressLength(ref pRule.remoteIpAddress);
+            updateAddressLength(ref pRule.remoteIpAddressMask);
+
+            return nf_addRule(ref pRule, toHead);
+        }
+
+        /**
+        * Add a rule to the head of rules list in driver.
+        * @param pRule See <tt>NF_RULE</tt>
+        * @param toHead TRUE (1) - add rule to list head, FALSE (0) - add rule to tail
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern NF_STATUS nf_addRuleEx(ref NF_RULE_EX pRule, int toHead);
+
+        public static NF_STATUS nf_addRuleEx(NF_RULE_EX pRule, int toHead)
+        {
+            updateAddressLength(ref pRule.localIpAddress);
+            updateAddressLength(ref pRule.localIpAddressMask);
+            updateAddressLength(ref pRule.remoteIpAddress);
+            updateAddressLength(ref pRule.remoteIpAddressMask);
+
+            return nf_addRuleEx(ref pRule, toHead);
+        }
+
+        /**
+        * Replace the rules in driver with the specified array.
+        * @param pRules Array of <tt>NF_RULE</tt> structures
+        * @param count Number of items in array
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern NF_STATUS nf_setRules(IntPtr pRules, int count);
+
+        public static NF_STATUS nf_setRules(NF_RULE[] rules)
+        {
+            NF_RULE pRule;
+
+            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NF_RULE)) * rules.Length);
+
+            long longPtr = ptr.ToInt64(); 
+            for (int i = 0; i < rules.Length; i++)
+            {
+                pRule = rules[i];
+
+                updateAddressLength(ref pRule.localIpAddress);
+                updateAddressLength(ref pRule.localIpAddressMask);
+                updateAddressLength(ref pRule.remoteIpAddress);
+                updateAddressLength(ref pRule.remoteIpAddressMask);
+
+                Marshal.StructureToPtr(pRule, new IntPtr(longPtr), false);
+
+                longPtr += Marshal.SizeOf(typeof(NF_RULE));
+            }
+
+            return nf_setRules(ptr, rules.Length);
+        }
+
+        /**
+        * Replace the rules in driver with the specified array.
+        * @param pRules Array of <tt>NF_RULE</tt> structures
+        * @param count Number of items in array
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern NF_STATUS nf_setRulesEx(IntPtr pRules, int count);
+
+        public static NF_STATUS nf_setRulesEx(NF_RULE_EX[] rules)
+        {
+            NF_RULE_EX pRule;
+
+            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NF_RULE_EX)) * rules.Length);
+
+            long longPtr = ptr.ToInt64();
+            for (int i = 0; i < rules.Length; i++)
+            {
+                pRule = rules[i];
+
+                updateAddressLength(ref pRule.localIpAddress);
+                updateAddressLength(ref pRule.localIpAddressMask);
+                updateAddressLength(ref pRule.remoteIpAddress);
+                updateAddressLength(ref pRule.remoteIpAddressMask);
+
+                Marshal.StructureToPtr(pRule, new IntPtr(longPtr), false);
+
+                longPtr += Marshal.SizeOf(typeof(NF_RULE_EX));
+            }
+
+            return nf_setRules(ptr, rules.Length);
+        }
+
+        /**
+        * Removes all rules from driver.
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_deleteRules();
+
+		/**
+		 *	Sets the timeout for TCP connections and returns old timeout.
+		 *	@param timeout Timeout value in milliseconds. Specify zero value to disable timeouts.
+		 */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern UInt32 nf_setTCPTimeout(UInt32 timeout);
+
+		/**
+		 *	Disables indicating TCP packets to user mode for the specified endpoint
+		 *  @param id Socket identifier
+		 */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_tcpDisableFiltering(ulong id);
+
+		/**
+		 *	Disables indicating UDP packets to user mode for the specified endpoint
+		 *  @param id Socket identifier
+		 */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_udpDisableFiltering(ulong id);
+
+        /**
+        * Returns TRUE if the specified process acts as a local proxy, accepting the redirected TCP connections.
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern bool nf_tcpIsProxy(uint processId);
+
+        /**
+        * Set the number of worker threads and initialization flags.
+        * The function should be called before nf_init. 
+        * By default nThreads = 1 and flags = 0
+        * @param nThreads Number of worker threads for NF_EventHandler events 
+        * @param flags A combination of flags from <tt>NF_FLAGS</tt>
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void nf_setOptions(uint nThreads, uint flags);
+
+        /**
+        * Complete TCP connect request pended using flag NF_PEND_CONNECT_REQUEST.
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_completeTCPConnectRequest(ulong id, ref NF_TCP_CONN_INFO pConnInfo);
+
+        /**
+        * Complete UDP connect request pended using flag NF_PEND_CONNECT_REQUEST.
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_completeUDPConnectRequest(ulong id, ref NF_UDP_CONN_REQUEST pConnInfo);
+
+        /**
+        * Returns in pConnInfo the properties of TCP connection with specified id.
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_getTCPConnInfo(ulong id, ref NF_TCP_CONN_INFO pConnInfo);
+
+        /**
+        * Returns in pConnInfo the properties of UDP socket with specified id.
+        **/
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_getUDPConnInfo(ulong id, ref NF_UDP_CONN_INFO pConnInfo);
+
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern bool nf_getProcessNameW(uint processId, IntPtr buf, int len);
+
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern bool nf_getProcessNameFromKernel(uint processId, IntPtr buf, int len);
+
+        /**
+        * Returns the process name for given process id
+        **/
+        public static unsafe String nf_getProcessNameFromKernel(UInt32 processId)
+        {
+            char[] buf = new char[1024];
+
+            fixed (char* p = buf)
+            {
+                 if (nf_getProcessNameFromKernel(processId, (IntPtr)p, buf.Length))
+                 {
+                     return Marshal.PtrToStringUni((IntPtr)p);
+                 }
+            }
+
+            return "System";
+        }
+
+        /**
+        * Returns the process name for given process id
+        **/
+        public static unsafe String nf_getProcessName(UInt32 processId)
+        {
+            char[] buf = new char[256];
+
+            fixed (char* p = buf)
+            {
+                if (nf_getProcessNameW(processId, (IntPtr)p, buf.Length))
+                {
+                    return Marshal.PtrToStringUni((IntPtr)p);
+                }
+            }
+
+            return "System";
+        }
+    
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void nf_adjustProcessPriviledges();
+
+        /*
+        * Set the event handler for IP filtering events
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern void nf_setIPEventHandler(IntPtr pHandler);
+
+        /*
+        * Set the event handler for IP filtering events
+        */
+        public static void nf_setIPEventHandler(NF_IPEventHandler pHandler)
+        {
+            NF_IPEventHandlerFwd.m_pEventHandler = pHandler;
+
+            m_pIPEventHandler = new NF_IPEventHandlerInternal();
+
+            m_pIPEventHandler.ipReceive = new cbd_ipReceive(NF_IPEventHandlerFwd.ipReceive);
+            m_pIPEventHandler.ipSend = new cbd_ipSend(NF_IPEventHandlerFwd.ipSend);
+
+            m_pIPEventHandlerRaw = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NF_IPEventHandlerInternal)));
+            Marshal.StructureToPtr(m_pIPEventHandler, m_pIPEventHandlerRaw, true);
+
+            nf_setIPEventHandler(m_pIPEventHandlerRaw);
+        }
+
+        /**
+        * Add flow control context
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_addFlowCtl(ref NF_FLOWCTL_DATA pData, ref UInt32 pFcHandle);
+
+        /**
+        * Delete flow control context
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_deleteFlowCtl(UInt32 fcHandle);
+
+        /**
+        * Associate flow control context with TCP connection
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_setTCPFlowCtl(ulong id, UInt32 fcHandle);
+
+        /**
+        * Associate flow control context with UDP socket
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_setUDPFlowCtl(ulong id, UInt32 fcHandle);
+
+        /**
+        * Modify flow control context limits
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_modifyFlowCtl(UInt32 fcHandle, ref NF_FLOWCTL_DATA pData);
+
+        /**
+        * Get flow control context statistics as the numbers of in/out bytes
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_getFlowCtlStat(UInt32 fcHandle, ref NF_FLOWCTL_STAT pStat);
+
+        /**
+        * Get TCP connection statistics as the numbers of in/out bytes.
+        * The function can be called only from tcpClosed handler!
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_getTCPStat(ulong id, ref NF_FLOWCTL_STAT pStat);
+
+        /**
+        * Get UDP socket statistics as the numbers of in/out bytes.
+        * The function can be called only from udpClosed handler!
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_getUDPStat(ulong id, ref NF_FLOWCTL_STAT pStat);
+
+        public enum NF_SOCKET_OPTIONS
+        {
+            TCP_SOCKET_NODELAY = 1,
+            TCP_SOCKET_KEEPALIVE = 2,
+            TCP_SOCKET_OOBINLINE = 3,
+            TCP_SOCKET_BSDURGENT = 4,
+            TCP_SOCKET_ATMARK = 5,
+            TCP_SOCKET_WINDOW = 6
+        }
+
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_tcpSetSockOpt(ulong id, NF_SOCKET_OPTIONS optname, ref int optval, int optlen);
+
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS nf_tcpSetSockOpt(ulong id, NF_SOCKET_OPTIONS optname, IntPtr optval, int optlen);
+
+        public static NF_STATUS nf_tcpSetSockOpt(ulong id, NF_SOCKET_OPTIONS optname, bool optval)
+        {
+            int dword = optval ? 1 : 0;
+            return nf_tcpSetSockOpt(id, optname, ref dword, Marshal.SizeOf(typeof(int)));
+        }
+
+        /**
+        * Add binding rule to driver
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        private static extern NF_STATUS 
+        nf_addBindingRule(ref NF_BINDING_RULE pRule, int toHead);
+
+        public static NF_STATUS 
+        nf_addBindingRule(NF_BINDING_RULE pRule, int toHead)
+        {
+            updateAddressLength(ref pRule.localIpAddress);
+            updateAddressLength(ref pRule.localIpAddressMask);
+            updateAddressLength(ref pRule.newLocalIpAddress);
+
+            return nf_addBindingRule(ref pRule, toHead);
+        }
+
+        /**
+        * Delete all binding rules from driver
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern NF_STATUS
+        nf_deleteBindingRules();
+
+        /**
+        * Returns the type of attached driver (DT_WFP, DT_TDI or DT_UNKNOWN)
+        */
+        [DllImport("nfapinet", CallingConvention = CallingConvention.Cdecl)]
+        public static extern UInt32
+        nf_getDriverType();
+    };
+
+}

+ 6 - 0
NetFilterHelper/App.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+    </startup>
+</configuration>

+ 36 - 0
NetFilterHelper/Enums/ResultCode.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NetFilterHelper.Enums
+{
+    public enum ResultCode
+    {
+        /// <summary>
+        /// 不支持的操作
+        /// </summary>
+        NotSupport = -1,
+
+        /// <summary>
+        /// 成功
+        /// </summary>
+        Success = 0,
+
+        /// <summary>
+        /// 复制失败
+        /// </summary>
+        CopyFail = 1,
+
+        /// <summary>
+        /// 注册失败
+        /// </summary>
+        RegisterFail = 2,
+
+        /// <summary>
+        /// 没有权限
+        /// </summary>
+        NoPermission = 3,
+    }
+}

+ 59 - 0
NetFilterHelper/NetFilterHelper.csproj

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{5B0CE8FC-493C-4AC0-8B7A-A24C377F13D1}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>NetFilterHelper</RootNamespace>
+    <AssemblyName>NetFilterHelper</AssemblyName>
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <Deterministic>true</Deterministic>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.ServiceProcess" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="3rd\NFSDK2\nfapinet.cs" />
+    <Compile Include="Enums\ResultCode.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Utils\SystemHelper.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 143 - 0
NetFilterHelper/Program.cs

@@ -0,0 +1,143 @@
+using NetFilterHelper.Utils;
+using NetFilterHelper.Enums;
+using nfapinet;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Principal;
+using System.ServiceProcess;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NetFilterHelper
+{
+    class Program
+    {
+        static ServiceController NFService = new ServiceController("netfilter2");
+        static string BinDriver = string.Empty;
+        static string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
+
+        static int Main(string[] args)
+        {
+            if (!IsAdministrator())
+            {
+                return (int)ResultCode.NoPermission;
+            }
+
+            if (args.Length == 1)
+            {
+                // 在这里初始化
+                Init();
+
+                string command = args[0];
+                switch (command)
+                {
+                    case "install":
+                        return InstallDriver();
+                    case "uninstall":
+                        return UninstallDriver();
+                    case "reinstall":
+                        UninstallDriver();
+                        return InstallDriver();
+                    default:
+                        return (int)ResultCode.NotSupport;
+                }
+            }
+            else
+            {
+                return (int)ResultCode.NotSupport;
+            }
+        }
+
+        static void Init()
+        {
+            string fileName;
+            switch ($"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}")
+            {
+                case "10.0": // Win 10
+                case "6.3":  // Win 8
+                case "6.2":  // Win 8
+                case "6.1":  // Win 7
+                case "6.0":  // Win 7
+                    if (SystemHelper.Is64BitOperatingSystem())
+                        fileName = "netfilter2-amd64.sys";
+                    else
+                        fileName = "netfilter2-i386.sys";
+                    break;
+                default:
+                    return;
+            }
+
+            BinDriver = Path.Combine(Directory.GetCurrentDirectory(), $"{fileName}");
+        }
+
+        static bool IsAdministrator()
+        {
+            return (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
+        }
+
+        static int ValueWithCode(IntPtr wow64Value, ResultCode resultCode)
+        {
+            // 重新启用重定向
+            SystemHelper.Wow64RevertWow64FsRedirection(wow64Value);
+            // 返回对应值
+            return (int)resultCode;
+        }
+
+        static int InstallDriver()
+        {
+            IntPtr wow64Value = IntPtr.Zero;
+
+            // 禁用重定向
+            SystemHelper.Wow64DisableWow64FsRedirection(ref wow64Value);
+
+            try
+            {
+                File.Copy(BinDriver, SystemDriver);
+            }
+            catch (Exception)
+            {
+                return ValueWithCode(wow64Value, ResultCode.CopyFail);
+            }
+
+            // 注册驱动文件
+            var result = NFAPI.nf_registerDriver("netfilter2");
+            if (result != NF_STATUS.NF_STATUS_SUCCESS)
+            {
+                return ValueWithCode(wow64Value, ResultCode.CopyFail);
+            }
+
+            return ValueWithCode(wow64Value, ResultCode.Success);
+        }
+
+        static int UninstallDriver()
+        {
+            IntPtr wow64Value = IntPtr.Zero;
+
+            // 禁用重定向
+            SystemHelper.Wow64DisableWow64FsRedirection(ref wow64Value);
+
+            try
+            {
+                if (NFService.Status == ServiceControllerStatus.Running)
+                {
+                    NFService.Stop();
+                    NFService.WaitForStatus(ServiceControllerStatus.Stopped);
+                }
+            }
+            catch (Exception)
+            {
+                // ignored
+            }
+
+            if (!File.Exists(SystemDriver))
+                return ValueWithCode(wow64Value, ResultCode.Success);
+
+            NFAPI.nf_unRegisterDriver("netfilter2");
+            File.Delete(SystemDriver);
+
+            return ValueWithCode(wow64Value, ResultCode.Success);
+        }
+    }
+}

+ 36 - 0
NetFilterHelper/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("NetFilterHelper")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("NetFilterHelper")]
+[assembly: AssemblyCopyright("Copyright ©  2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("5b0ce8fc-493c-4ac0-8b7a-a24c377f13d1")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 76 - 0
NetFilterHelper/Utils/SystemHelper.cs

@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NetFilterHelper.Utils
+{
+    public class SystemHelper
+    {
+        /// <summary>
+        /// The function determines whether the current operating system is a 
+        /// 64-bit operating system.
+        /// </summary>
+        /// <returns>
+        /// The function returns true if the operating system is 64-bit; 
+        /// otherwise, it returns false.
+        /// </returns>
+        public static bool Is64BitOperatingSystem()
+        {
+            if (IntPtr.Size == 8)  // 64-bit programs run only on Win64
+            {
+                return true;
+            }
+            else  // 32-bit programs run on both 32-bit and 64-bit Windows
+            {
+                // Detect whether the current process is a 32-bit process 
+                // running on a 64-bit system.
+                bool flag;
+                return ((DoesWin32MethodExist("kernel32.dll", "IsWow64Process") &&
+                    IsWow64Process(GetCurrentProcess(), out flag)) && flag);
+            }
+        }
+
+        /// <summary>
+        /// The function determins whether a method exists in the export 
+        /// table of a certain module.
+        /// </summary>
+        /// <param name="moduleName">The name of the module</param>
+        /// <param name="methodName">The name of the method</param>
+        /// <returns>
+        /// The function returns true if the method specified by methodName 
+        /// exists in the export table of the module specified by moduleName.
+        /// </returns>
+        static bool DoesWin32MethodExist(string moduleName, string methodName)
+        {
+            IntPtr moduleHandle = GetModuleHandle(moduleName);
+            if (moduleHandle == IntPtr.Zero)
+            {
+                return false;
+            }
+            return (GetProcAddress(moduleHandle, methodName) != IntPtr.Zero);
+        }
+
+        [DllImport("kernel32.dll")]
+        static extern IntPtr GetCurrentProcess();
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+        static extern IntPtr GetModuleHandle(string moduleName);
+
+        [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
+        static extern IntPtr GetProcAddress(IntPtr hModule,
+            [MarshalAs(UnmanagedType.LPStr)] string procName);
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process);
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
+    }
+}