Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of WinDivert packet modification #251

Open
brendanosborne opened this issue Feb 26, 2021 · 8 comments
Open

Example of WinDivert packet modification #251

brendanosborne opened this issue Feb 26, 2021 · 8 comments

Comments

@brendanosborne
Copy link

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

@kayoub5
Copy link
Collaborator

kayoub5 commented Feb 26, 2021

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
Copy link
Author

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
Copy link
Collaborator

kayoub5 commented Mar 4, 2021

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

@brendanosborne
Copy link
Author

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
Copy link
Author

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
Copy link
Collaborator

kayoub5 commented Mar 6, 2021

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

@Tornadocraver
Copy link

I was having a similar issue until I explicitly cleared the flags as mentioned here: #289 (comment)

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.

@kayoub5
Copy link
Collaborator

kayoub5 commented Dec 5, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants