dotpcap / sharppcap

Official repository - Fully managed, cross platform (Windows, Mac, Linux) .NET library for capturing packets
1.29k stars 266 forks source link

Example of WinDivert packet modification #251

Open brendanosborne opened 3 years ago

brendanosborne commented 3 years ago

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

kayoub5 commented 3 years ago
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
brendanosborne commented 3 years ago

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

kayoub5 commented 3 years ago

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

brendanosborne commented 3 years ago

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 commented 3 years ago

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();
        }
    }
}
kayoub5 commented 3 years ago

@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:

Tornadocraver commented 7 months ago

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:

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.

kayoub5 commented 7 months ago

@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.