// LISTENS TO VPN ADAPTER AND SENDS THE SPECIFIC PACKETS OUT THE NORMAL ADAPTER private static void TreatOUTPacketsVPNtoNormal(NdisApiDotNet outNdisapi, NetworkAdapter vpnAdapter, NetworkAdapter normalAdapter) { // Lists for re-injecting packets List <RawPacket> toAdapter = new List <RawPacket>(); List <RawPacket> toMstcp = new List <RawPacket>(); // Unmanaged memory resource for sending receiving bulk of packets // Maximum number of packets to send/receive = 64 NdisBufferResource buffer = new NdisBufferResource(64); outNdisapi.SetAdapterMode(vpnAdapter.Handle, MSTCP_FLAGS.MSTCP_FLAG_TUNNEL); outNdisapi.SetPacketEvent(vpnAdapter.Handle, outPacketEvent); do { outPacketEvent.WaitOne(); var packetList = outNdisapi.ReadPackets(vpnAdapter.Handle, buffer); while (packetList.Item1) { foreach (var packet in packetList.Item2) { Packet p = null; EthernetPacket ethernetPacket = null; TcpPacket tcpPacket = null; IPv4Packet ipv4Packet = null; ushort sport = 0; ushort dport = 0; try { p = Packet.ParsePacket(LinkLayers.Ethernet, packet.Data); ethernetPacket = (EthernetPacket)p; tcpPacket = (TcpPacket)((IPPacket)((EthernetPacket)p).PayloadPacket).PayloadPacket; ipv4Packet = (IPv4Packet)((EthernetPacket)p).PayloadPacket; sport = tcpPacket.SourcePort; dport = tcpPacket.DestinationPort; } catch (Exception ex) { if (packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE) { toMstcp.Add(packet); } else { toAdapter.Add(packet); } Console.WriteLine($"An exeption {ex.Message} occured while trying to parse network packet. Packet will be let thru without any changes"); continue; } DumpSourceChangingFilteredPacket(packet.DeviceFlags, ipv4Packet.SourceAddress.ToString(), sport.ToString(), ipv4Packet.DestinationAddress.ToString(), dport.ToString(), p.Bytes.Length, packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE); if (packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE) { // Packet was received on VPN adapter, leave it as it is toMstcp.Add(packet); } else { if (ipv4Packet.SourceAddress.Equals(vpnIP)) { // Change the Source for outgoing packets that will later be sent thru normal adapter ipv4Packet.SourceAddress = localIp; ethernetPacket.SourceHardwareAddress = localMacAddress; ipv4Packet.UpdateIPChecksum(); tcpPacket.UpdateTcpChecksum(); ethernetPacket.UpdateCalculatedValues(); var newPackage = new RawPacket() { Data = p.Bytes, FilterId = packet.FilterId, Dot1q = packet.Dot1q, NdisFlags = packet.NdisFlags, DeviceFlags = packet.DeviceFlags }; toAdapter.Add(newPackage); } else { toAdapter.Add(packet); } } } if (toMstcp.Count > 0) { // If we have packets to forward upwards the network stack then do it here // RECEIVED SHOULD BE TREATED BY VPN ADAPTER outNdisapi.SendPacketsToMstcp(vpnAdapter.Handle, buffer, toMstcp); toMstcp.Clear(); } if (toAdapter.Count > 0) { // If we have packets to forward downwards the network stack then do it here // SENT SHOULD BE TREATED BY NORMAL ADAPTER outNdisapi.SendPacketsToAdapter(normalAdapter.Handle, buffer, toAdapter); toAdapter.Clear(); } packetList = outNdisapi.ReadPackets(vpnAdapter.Handle, buffer); } ; outPacketEvent.Reset(); } while (!stopCapturing); // // Release driver and associated resources // buffer.Dispose(); outNdisapi.SetPacketEvent(vpnAdapter.Handle, null); outNdisapi.SetAdapterMode(vpnAdapter.Handle, 0); }
static void Main(string[] args) { if (!ndisapi.IsDriverLoaded()) { Console.WriteLine("WinpkFilter driver is not loaded. Exiting."); return; } UInt32 driverVersion = ndisapi.GetVersion(); UInt32 majorVersion = (driverVersion & (0xF000)) >> 12; UInt32 minorVersion1 = (driverVersion & (0xFF000000)) >> 24; UInt32 minorVersion2 = (driverVersion & (0xFF0000)) >> 16; if (ndisapi != null) { Console.WriteLine($"Detected Windows Packet Filter version {majorVersion}.{minorVersion1}.{minorVersion2}"); } Console.WriteLine(); var adapterList = ndisapi.GetTcpipBoundAdaptersInfo(); if (!adapterList.Item1) { Console.WriteLine("WinpkFilter failed to query active interfaces. Exiting."); return; } if (adapterList.Item2.Count > 0) { Console.WriteLine("Available network interfaces: "); } Console.WriteLine(); int counter = 0; foreach (var adapter in adapterList.Item2) { Console.WriteLine($"{++counter}) {adapter.FriendlyName}"); Console.WriteLine($"\t Internal name: {adapter.Name}"); Console.WriteLine($"\t Handle: {adapter.Handle.ToString("x")}"); Console.WriteLine($"\t MAC: {adapter.CurrentAddress}"); Console.WriteLine($"\t Medium: {adapter.Medium}"); Console.WriteLine($"\t MTU: {adapter.Mtu}"); if (adapter.Medium == NDIS_MEDIUM.NdisMediumWan) { var rasLinkInfoList = ndisapi.GetRasLinks(adapter.Handle); if (rasLinkInfoList.Item1 && (rasLinkInfoList.Item2.Count > 0)) { foreach (var e in rasLinkInfoList.Item2) { Console.WriteLine($"----------------------------------------------------------------"); Console.WriteLine($"\t\tLinkSpeed = {e.LinkSpeed}"); Console.WriteLine($"\t\tMTU: {e.MaximumTotalSize}"); Console.WriteLine($"\t\tLocalAddress: {e.LocalAddress}"); Console.WriteLine($"\t\tRemoteAddress: {e.RemoteAddress}"); Byte[] ipAddress = new Byte[4]; Array.Copy(e.ProtocolBuffer, 584, ipAddress, 0, 4); IPAddress ipV4 = new IPAddress(ipAddress); Array.Copy(e.ProtocolBuffer, 588, ipAddress, 0, 4); IPAddress ipMaskV4 = new IPAddress(ipAddress); Console.WriteLine($"\t\tIPv4: {ipV4} Mask: {ipMaskV4}"); Console.WriteLine($"----------------------------------------------------------------"); } } } Console.WriteLine(); } Console.Write("Select network interface: "); int index = Convert.ToInt32(Console.ReadLine()); if (index > adapterList.Item2.Count) { Console.WriteLine($"Wrong interface index {index}"); return; } #region Testing NdisrdRequest API call Console.WriteLine(); Console.WriteLine($"Probing NDIS requests on: {adapterList.Item2[index - 1].FriendlyName}:"); Console.WriteLine(); PacketOidData oidRequest = new PacketOidData(); oidRequest.Adapter = adapterList.Item2[index - 1].Handle; oidRequest.Oid = OID_802_3_CURRENT_ADDRESS; oidRequest.Data = new byte[6]; if (ndisapi.NdisrdRequest(oidRequest, false)) { Console.WriteLine($@"OID_802_3_CURRENT_ADDRESS: Status = OK Value: {new PhysicalAddress(oidRequest.Data)}"); } else { Console.WriteLine($@"OID_802_3_CURRENT_ADDRESS: Status = FAILED"); } oidRequest.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE; oidRequest.Data = new byte[4]; if (ndisapi.NdisrdRequest(oidRequest, false)) { Console.WriteLine($@"OID_GEN_MAXIMUM_TOTAL_SIZE: Status = OK Value: {BitConverter.ToUInt32(oidRequest.Data, 0)}"); } else { Console.WriteLine($@"OID_GEN_MAXIMUM_TOTAL_SIZE: Status = FAILED"); } oidRequest.Oid = OID_GEN_PHYSICAL_MEDIUM; if (ndisapi.NdisrdRequest(oidRequest, false)) { Console.WriteLine($@"OID_GEN_PHYSICAL_MEDIUM: Status = OK Value: {(NdisPhysicalMedium)BitConverter.ToUInt32(oidRequest.Data, 0)}"); } else { Console.WriteLine($@"OID_GEN_PHYSICAL_MEDIUM: Status = FAILED"); } #endregion #region Testing static filters Console.WriteLine(); Console.WriteLine("Please select the static filters set to use:"); Console.WriteLine(); Console.WriteLine(@"1 - IPv4 DNS filter: Redirect and dump only IPv4 DNS packets for processing in user mode."); Console.WriteLine(@"2 - HTTP filter: Redirect and dump only HTTP(TCP port 80) packets for processing in user mode."); Console.WriteLine(@"3 - FQDN filter: Redirect and dump only packets destined to/from selected domain name."); Console.WriteLine(@"4 - Default filter: Redirect and dump all network packets."); Console.WriteLine(@"5 - Silent default: Redirect all network packets. Zero output (performance test option)."); Console.WriteLine(); Console.Write("Select filter option: "); int option = Convert.ToInt32(Console.ReadLine()); if (option > 5) { Console.WriteLine($"Wrong filter option {option}"); return; } bool dumpPackets = true; switch (option) { case 1: LoadIpv4DnsFilter(adapterList.Item2[index - 1].Handle); break; case 2: LoadHttpFilter(adapterList.Item2[index - 1].Handle); break; case 3: Console.Write("Enter FQDN: "); LoadFqdnFilter(adapterList.Item2[index - 1].Handle, Console.ReadLine()); break; case 4: // Do nothing, this is a default behaviour break; case 5: dumpPackets = false; break; default: Console.WriteLine("Wrong filter option. Exiting..."); return; } #endregion // Register a cancel handler that lets us break out of our capture loop Console.CancelKeyPress += HandleCancelKeyPress; ndisapi.SetAdapterMode( adapterList.Item2[index - 1].Handle, MSTCP_FLAGS.MSTCP_FLAG_TUNNEL ); ndisapi.SetPacketEvent(adapterList.Item2[index - 1].Handle, packetEvent); Console.WriteLine($"-- Filtering on {adapterList.Item2[index - 1].FriendlyName}, hit 'ctrl-c' to stop..."); // Lists for re-injecting packets List <RawPacket> toAdapter = new List <RawPacket>(); List <RawPacket> toMstcp = new List <RawPacket>(); // Unmanaged memory resource for sending receiving bulk of packets // Maximum number of packets to send/receive = 64 NdisBufferResource buffer = new NdisBufferResource(64); do { packetEvent.WaitOne(); #region Single packet read/write //RawPacket packet = ndisapi.ReadPacket(adapterList[index - 1].Handle); //while (packet != null) //{ // // use PacketDotNet to parse this packet and print out // // its high level information // Packet p = Packet.ParsePacket(LinkLayers.Ethernet, packet.Data); // try // { // Console.WriteLine(p.ToString()); // } // catch (Exception) // { } // if (packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE) // { // ndisapi.SendPacketToMstcp(adapterList[index - 1].Handle, packet); // } // else // { // ndisapi.SendPacketToAdapter(adapterList[index - 1].Handle, packet); // } // packet = ndisapi.ReadPacket(adapterList[index - 1].Handle); //}; #endregion #region Bulk of packets read/write var packetList = ndisapi.ReadPackets(adapterList.Item2[index - 1].Handle, buffer); while (packetList.Item1) { foreach (var packet in packetList.Item2) { if (dumpPackets) { Console.WriteLine($"Succesfully read {packetList.Item2.Count} packets from {adapterList.Item2[index - 1].FriendlyName}"); try { // Use PacketDotNet to parse this packet and print out // its high level information Packet p = Packet.ParsePacket(LinkLayers.Ethernet, packet.Data); Console.WriteLine(p.ToString()); } catch (Exception ex) { Console.WriteLine($"An exeption {ex.Message} occured while trying to parse network packet."); } } // Depending on the packet direction insert it to the appropriate list if (packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE) { toMstcp.Add(packet); } else { toAdapter.Add(packet); } } if (toMstcp.Count > 0) { // If we have packets to forward upwards the network stack then do it here ndisapi.SendPacketsToMstcp(adapterList.Item2[index - 1].Handle, buffer, toMstcp); toMstcp.Clear(); } if (toAdapter.Count > 0) { // If we have packets to forward downwards the network stack then do it here ndisapi.SendPacketsToAdapter(adapterList.Item2[index - 1].Handle, buffer, toAdapter); toAdapter.Clear(); } packetList = ndisapi.ReadPackets(adapterList.Item2[index - 1].Handle, buffer); } ; #endregion packetEvent.Reset(); } while (!stopCapturing); Console.WriteLine("-- Filtering stopped"); // // Release driver and associated resources // buffer.Dispose(); ndisapi.SetPacketEvent(adapterList.Item2[index - 1].Handle, null); ndisapi.SetAdapterMode( adapterList.Item2[index - 1].Handle, 0 ); // // Display loaded static filters // DumpStaticFilters(); }