sharppcap icon indicating copy to clipboard operation
sharppcap copied to clipboard

Example of WinDivert packet modification

Open brendanosborne opened this issue 3 years ago • 8 comments

Would it be possible to get an example of modifying packets using the new WinDivert implementation?

brendanosborne avatar Feb 26 '21 04:02 brendanosborne

var device = new WinDivertDevice();
// WINDIVERT_FLAG_DROP will cause the original packet to be dropped
// you can inject it back (after modifications) using `device.SendPacket()`
device.Flags = WINDIVERT_FLAG_DROP;
device.Open();
// You can use any Libpcap example as reference for receiving

kayoub5 avatar Feb 26 '21 17:02 kayoub5

Thank you. I'm still having a bit of trouble getting this up and running. I'm new to C# so hopefully the below isn't a rookie error. I copied the test code for sending a test packet from here: https://github.com/chmorgan/sharppcap/blob/master/Test/WinDivert/WinDivertDeviceTest.cs

        public void TestSend()
        {
            var dst = IPAddress.Parse("8.8.8.8");
            var nic = IpHelper.GetBestInterface(dst);
            Assert.NotNull(nic, "No internet connected interface found");
            var src = nic.GetIPProperties().UnicastAddresses
                .Select(addr => addr.Address)
                .FirstOrDefault(addr => addr.AddressFamily == AddressFamily.InterNetwork);
            var ifIndex = nic.GetIPProperties().GetIPv4Properties().Index;
            Console.WriteLine($"Using NIC {nic.Name} [{ifIndex}]");
            Console.WriteLine($"Sending from {src} to {dst}");
            using var device = new WinDivertDevice();
            device.Open();
            var udp = new UdpPacket(5000, 5000);
            udp.PayloadData = new byte[100];
            var ip = IPv4Packet.RandomPacket();
            ip.PayloadPacket = udp;

            ip.SourceAddress = src;
            ip.DestinationAddress = dst;

            device.SendPacket(ip);
        }

I receive this error: image

So I changed using var device = new WinDivertDevice(); to var device = new WinDivertDevice(); as you specified which doesn't throw up any errors.

But when I run the code it throws the following:

image

brendanosborne avatar Mar 04 '21 03:03 brendanosborne

you have the 32bit driver and the application is 64 bit or the other way around.

kayoub5 avatar Mar 04 '21 20:03 kayoub5

Thank you. After setting the Debug CPU option to x64 it helped. I also had to launch Visual Studio Code as Administrator and ensure WinDivert.lib and WinDivert64.sys are in the apps base directory as well as the WinDivert.dll

brendanosborne avatar Mar 05 '21 04:03 brendanosborne

I'm still having trouble with this. My end goal is to modify the packet interface index number and source IP address but I don't seem to be able to re-inject a packet. Below is what I've cobbled together. It drops the packets but the device.SendPacket does not seem to be reinserting them. I assume that's how it's supposed to work? If I get it working I'll put a PR in with the example to save others time down the track.

using System;
using SharpPcap;
using SharpPcap.WinDivert;

namespace ConsoleApp1
{
    /// <summary>
    /// Example showing packet manipulation with WinDivert
    /// </summary>
    public class Program
    {
        public static ulong WINDIVERT_FLAG_DROP { get; private set; }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main() {
            // 1. Make sure Visual Studio Code has been launched as Administrator
            // 2. Make sure WinDivert.dll, WinDivert.lib and WinDivert64.sys are in the base folder of the build
            // To get base folder of the build uncomment the below line:
            // Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
            // 3. Debug mode CPU needs to be set to x64

            var device = new WinDivertDevice();

            device.Flags = WINDIVERT_FLAG_DROP;
            device.Open();

            device.OnPacketArrival += (s, e) =>
            {
                var packet = PacketDotNet.Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);

                // Eventually I'll modify the packet source IP address and interface index number here somehow

                device.SendPacket(packet);
            };

            device.StartCapture();

            Console.WriteLine("-- Listening on {0}, hit 'Enter' to stop...", device.Description);

            // Wait for 'Enter' from the user.
            Console.ReadLine();

            device.StopCapture();
        }
    }
}

brendanosborne avatar Mar 06 '21 05:03 brendanosborne

@brendanosborne sharppcap 5.4.0 auto detects the interface index and the direction from the destination IP, using GetBestInterfaceEx.

Current master of sharppcap allows setting the interface index and packet flags using WinDivertCapture class.

Some things to consider:

  • You have to update the IP and TCP/UDP checksum if you change the IP or port number, or set the correct WinDivertPacketFlags in WinDivertCapture
  • You have to indicate if you are rerouting the packet to another interface with InterfaceIndex, you also have to change it to an Outbound packet using WinDivertPacketFlags in WinDivertCapture
  • WinDivert will fail to send packet on an interface if the ARP/NDP lookup fails.

kayoub5 avatar Mar 06 '21 12:03 kayoub5

I was having a similar issue until I explicitly cleared the flags as mentioned here: https://github.com/dotpcap/sharppcap/issues/289#issuecomment-864414718

Apparently there is base behavior when no flags are set, which, oddly, is not the default:

  • device.Flags = 0;
    • Matching packets: dropped and diverted
    • Non-matching packets: continue as normal
  • device.Flags = 1; // WINDIVERT_FLAG_SNIFF (default)
    • All packets: copied and diverted
  • device.Flags = 2; // WINDIVERT_FLAG_DROP
    • All packets: dropped

The first behavior is what I was looking for...not sure if that's what OP wanted, but hopefully this helps someone in my situation.

Tornadocraver avatar Dec 05 '23 19:12 Tornadocraver

@Tornadocraver the default behavior of sharppcap is intentionally different, we opted to make the default behavior of all devices to sniff-only regardless of the driver.

kayoub5 avatar Dec 05 '23 20:12 kayoub5