namespace WinDivertNet.WinDivertWrapper; using System; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; /// /// WinDivert 高级封装类 /// public class WinDivertController : IDisposable { private IntPtr _handle; private bool _disposed = false; public IntPtr Handle => _handle; /// /// 获取句柄是否有效 /// public bool IsValid => _handle != IntPtr.Zero; /// /// 构造函数 /// public WinDivertController() { _handle = IntPtr.Zero; } /// /// 析构函数 /// ~WinDivertController() { Dispose(false); } /// /// 打开 WinDivert 句柄 /// /// 过滤器表达式 /// 层级 /// 优先级 /// 标志 /// 是否成功 public bool Open(string filter, uint layer = WinDivert.WINDIVERT_LAYER_NETWORK, short priority = WinDivert.WINDIVERT_PRIORITY_DEFAULT, ulong flags = 0) { if (IsValid) { Close(); } _handle = WinDivert.WinDivertOpen(filter, layer, priority, flags); if (_handle == IntPtr.Zero) { int errorCode = Marshal.GetLastWin32Error(); Console.WriteLine($"WinDivert打开失败,错误码: {errorCode}"); } return IsValid; } public bool TryGetPacket(out byte[] packet, out WinDivert.WINDIVERT_ADDRESS address) { packet = null; address = new WinDivert.WINDIVERT_ADDRESS { Reserved = new byte[8] }; if (!IsValid) return false; byte[] buffer = new byte[65535]; // 足够大的缓冲区 // 使用我们的SafeRecv函数处理异常大小问题 return WinDivert.SafeRecv(_handle, buffer, ref address, out packet); } /// /// 关闭 WinDivert 句柄 /// public void Close() { if (IsValid) { WinDivert.Close(_handle); _handle = IntPtr.Zero; } } /// /// 接收数据包 /// /// 数据缓冲区 /// 地址结构 /// 实际读取的字节数,失败返回 0 public uint Receive(byte[] buffer, ref WinDivert.WINDIVERT_ADDRESS addr) { if (!IsValid || buffer == null) { return 0; } uint readLen = 0; if (WinDivert.Recv(_handle, buffer, (uint)buffer.Length, ref addr, ref readLen)) { Console.WriteLine($"Receive: {readLen}"); return readLen; } return 0; } /// /// 异步接收数据包 /// /// 数据缓冲区 /// 地址结构 /// 实际读取的字节数的任务 public Task ReceiveAsync(byte[] buffer, WinDivert.WINDIVERT_ADDRESS addr) { return Task.Run(() => Receive(buffer, ref addr)); } /// /// 发送数据包 /// /// 数据缓冲区 /// 地址结构 /// 实际写入的字节数,失败返回 0 public uint Send(byte[] buffer, ref WinDivert.WINDIVERT_ADDRESS addr) { if (!IsValid || buffer == null) { return 0; } uint writeLen = 0; if (WinDivert.Send(_handle, buffer, (uint)buffer.Length, ref addr, ref writeLen)) { return writeLen; } return 0; } /// /// 异步发送数据包 /// /// 数据缓冲区 /// 地址结构 /// 实际写入的字节数的任务 public Task SendAsync(byte[] buffer, WinDivert.WINDIVERT_ADDRESS addr) { return Task.Run(() => Send(buffer, ref addr)); } /// /// 设置参数 /// /// 参数类型 /// 参数值 /// 是否成功 public bool SetParam(int param, ulong value) { if (!IsValid) { return false; } return WinDivert.SetParam(_handle, param, value); } /// /// 获取参数 /// /// 参数类型 /// 参数值 /// 是否成功 public bool GetParam(int param, ref ulong value) { if (!IsValid) { return false; } return WinDivert.GetParam(_handle, param, ref value); } /// /// 校验包数据的校验和 /// /// 数据缓冲区 /// 地址结构 /// 标志 /// 校验和结果 public uint CalcChecksums(byte[] buffer, ref WinDivert.WINDIVERT_ADDRESS addr, uint flags = 0) { if (buffer == null) { return 0; } return WinDivert.CalcChecksums(buffer, (uint)buffer.Length, ref addr, flags); } /// /// 检查过滤器语法 /// /// 过滤器表达式 /// 层级 /// 检查结果和错误信息 public (bool IsValid, string ErrorMessage) CheckFilter(string filter, uint layer = WinDivert.WINDIVERT_LAYER_NETWORK) { StringBuilder errorStr = new StringBuilder(256); bool isValid = WinDivert.CheckFilter(filter, layer, errorStr, 256); return (isValid, errorStr.ToString()); } /// /// 解析数据包 /// /// 数据包 /// 解析结果 public PacketHeaders ParsePacket(byte[] packet) { if (packet == null) { return new PacketHeaders(); } IntPtr ppIpHdr = IntPtr.Zero; IntPtr ppIpv6Hdr = IntPtr.Zero; IntPtr ppIcmpHdr = IntPtr.Zero; IntPtr ppIcmpv6Hdr = IntPtr.Zero; IntPtr ppTcpHdr = IntPtr.Zero; IntPtr ppUdpHdr = IntPtr.Zero; IntPtr ppData = IntPtr.Zero; ushort pDataLen = 0; bool success = WinDivert.ParsePacket(packet, (uint)packet.Length, ref ppIpHdr, ref ppIpv6Hdr, ref ppIcmpHdr, ref ppIcmpv6Hdr, ref ppTcpHdr, ref ppUdpHdr, ref ppData, ref pDataLen); PacketHeaders headers = new PacketHeaders { Success = success, DataLength = pDataLen }; if (success) { if (ppIpHdr != IntPtr.Zero) { headers.IpHeader = Marshal.PtrToStructure(ppIpHdr); headers.HasIpHeader = true; } if (ppIpv6Hdr != IntPtr.Zero) { headers.Ipv6Header = Marshal.PtrToStructure(ppIpv6Hdr); headers.HasIpv6Header = true; } if (ppTcpHdr != IntPtr.Zero) { headers.TcpHeader = Marshal.PtrToStructure(ppTcpHdr); headers.HasTcpHeader = true; } if (ppUdpHdr != IntPtr.Zero) { headers.UdpHeader = Marshal.PtrToStructure(ppUdpHdr); headers.HasUdpHeader = true; } if (ppIcmpHdr != IntPtr.Zero) { headers.IcmpHeader = Marshal.PtrToStructure(ppIcmpHdr); headers.HasIcmpHeader = true; } if (ppIcmpv6Hdr != IntPtr.Zero) { headers.Icmpv6Header = Marshal.PtrToStructure(ppIcmpv6Hdr); headers.HasIcmpv6Header = true; } if (ppData != IntPtr.Zero && pDataLen > 0) { headers.Data = new byte[pDataLen]; Marshal.Copy(ppData, headers.Data, 0, (int)pDataLen); } } return headers; } /// /// 修改包的源 IP 地址 /// /// 数据包 /// 新的源 IP 地址 /// 是否成功 public bool ModifySourceIpv4Address(byte[] packet, string sourceIp) { if (packet == null || string.IsNullOrEmpty(sourceIp)) { return false; } PacketHeaders headers = ParsePacket(packet); if (!headers.Success || !headers.HasIpHeader) { return false; } uint addr = 0; if (!WinDivert.ParseIPv4Address(sourceIp, ref addr)) { return false; } // 计算 IP 头的偏移量 int ipHdrOffset = Marshal.SizeOf(); // 修改源 IP 地址 byte[] addrBytes = BitConverter.GetBytes(addr); Array.Copy(addrBytes, 0, packet, ipHdrOffset - 8, 4); return true; } /// /// 修改包的目标 IP 地址 /// /// 数据包 /// 新的目标 IP 地址 /// 是否成功 public bool ModifyDestinationIpv4Address(byte[] packet, string destinationIp) { if (packet == null || string.IsNullOrEmpty(destinationIp)) { return false; } PacketHeaders headers = ParsePacket(packet); if (!headers.Success || !headers.HasIpHeader) { return false; } uint addr = 0; if (!WinDivert.ParseIPv4Address(destinationIp, ref addr)) { return false; } // 计算 IP 头的偏移量 int ipHdrOffset = Marshal.SizeOf(); // 修改目标 IP 地址 byte[] addrBytes = BitConverter.GetBytes(addr); Array.Copy(addrBytes, 0, packet, ipHdrOffset - 4, 4); return true; } /// /// 修改包的源端口 /// /// 数据包 /// 新的源端口 /// 是否成功 public bool ModifySourcePort(byte[] packet, ushort sourcePort) { if (packet == null) { return false; } PacketHeaders headers = ParsePacket(packet); if (!headers.Success) { return false; } int offset = -1; if (headers.HasTcpHeader) { // 计算 TCP 头的偏移量(简化计算,实际应该考虑 IP 选项) offset = (headers.HasIpHeader ? 20 : 0) + (headers.HasIpv6Header ? 40 : 0); } else if (headers.HasUdpHeader) { // 计算 UDP 头的偏移量(简化计算,实际应该考虑 IP 选项) offset = (headers.HasIpHeader ? 20 : 0) + (headers.HasIpv6Header ? 40 : 0); } if (offset < 0) { return false; } // 修改源端口 byte[] portBytes = BitConverter.GetBytes(sourcePort); Array.Copy(portBytes, 0, packet, offset, 2); return true; } /// /// 修改包的目标端口 /// /// 数据包 /// 新的目标端口 /// 是否成功 public bool ModifyDestinationPort(byte[] packet, ushort destinationPort) { if (packet == null) { return false; } PacketHeaders headers = ParsePacket(packet); if (!headers.Success) { return false; } int offset = -1; if (headers.HasTcpHeader) { // 计算 TCP 头的偏移量(简化计算,实际应该考虑 IP 选项) offset = (headers.HasIpHeader ? 20 : 0) + (headers.HasIpv6Header ? 40 : 0) + 2; } else if (headers.HasUdpHeader) { // 计算 UDP 头的偏移量(简化计算,实际应该考虑 IP 选项) offset = (headers.HasIpHeader ? 20 : 0) + (headers.HasIpv6Header ? 40 : 0) + 2; } if (offset < 0) { return false; } // 修改目标端口 byte[] portBytes = BitConverter.GetBytes(destinationPort); Array.Copy(portBytes, 0, packet, offset, 2); return true; } /// /// 重新计算包的校验和 /// /// 数据包 /// 地址结构 /// 是否成功 public bool RecalculateChecksums(byte[] packet, ref WinDivert.WINDIVERT_ADDRESS addr) { if (packet == null) { return false; } uint result = WinDivert.CalcChecksums(packet, (uint)packet.Length, ref addr, 0); return result > 0; } /// /// 释放资源 /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// 释放资源 /// /// 是否为显式释放 protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // 释放托管资源 } // 释放非托管资源 Close(); _disposed = true; } } } /// /// 数据包头信息 /// public class PacketHeaders { /// /// 解析是否成功 /// public bool Success { get; set; } /// /// 是否包含 IPv4 头 /// public bool HasIpHeader { get; set; } /// /// 是否包含 IPv6 头 /// public bool HasIpv6Header { get; set; } /// /// 是否包含 TCP 头 /// public bool HasTcpHeader { get; set; } /// /// 是否包含 UDP 头 /// public bool HasUdpHeader { get; set; } /// /// 是否包含 ICMP 头 /// public bool HasIcmpHeader { get; set; } /// /// 是否包含 ICMPv6 头 /// public bool HasIcmpv6Header { get; set; } /// /// IPv4 头 /// public WinDivert.WINDIVERT_IPHDR IpHeader { get; set; } /// /// IPv6 头 /// public WinDivert.WINDIVERT_IPV6HDR Ipv6Header { get; set; } /// /// TCP 头 /// public WinDivert.WINDIVERT_TCPHDR TcpHeader { get; set; } /// /// UDP 头 /// public WinDivert.WINDIVERT_UDPHDR UdpHeader { get; set; } /// /// ICMP 头 /// public WinDivert.WINDIVERT_ICMPHDR IcmpHeader { get; set; } /// /// ICMPv6 头 /// public WinDivert.WINDIVERT_ICMPV6HDR Icmpv6Header { get; set; } /// /// 数据部分 /// public byte[] Data { get; set; } /// /// 数据长度 /// public uint DataLength { get; set; } public override string ToString() { var sb = new StringBuilder(); sb.AppendLine("PacketHeaders {"); sb.AppendLine($" Success: {Success},"); sb.AppendLine($" HasIpHeader: {HasIpHeader},"); sb.AppendLine($" HasIpv6Header: {HasIpv6Header},"); sb.AppendLine($" HasTcpHeader: {HasTcpHeader},"); sb.AppendLine($" HasUdpHeader: {HasUdpHeader},"); sb.AppendLine($" HasIcmpHeader: {HasIcmpHeader},"); sb.AppendLine($" HasIcmpv6Header: {HasIcmpv6Header},"); sb.AppendLine($" IpHeader: {(HasIpHeader ? IpHeader.ToString() : "N/A")},"); sb.AppendLine($" Ipv6Header: {(HasIpv6Header ? Ipv6Header.ToString() : "N/A")},"); sb.AppendLine($" TcpHeader: {(HasTcpHeader ? TcpHeader.ToString() : "N/A")},"); sb.AppendLine($" UdpHeader: {(HasUdpHeader ? UdpHeader.ToString() : "N/A")},"); sb.AppendLine($" IcmpHeader: {(HasIcmpHeader ? IcmpHeader.ToString() : "N/A")},"); sb.AppendLine($" Icmpv6Header: {(HasIcmpv6Header ? Icmpv6Header.ToString() : "N/A")},"); sb.AppendLine($" DataLength: {DataLength},"); sb.AppendLine( $" Data: {(Data != null ? BitConverter.ToString(Data, 0, (int)Math.Min(Data.Length, 32)) + (Data.Length > 32 ? "..." : "") : "null")}"); sb.AppendLine("}"); return sb.ToString(); } }