U:调整结构性目录

This commit is contained in:
jimmy committed 2025-06-18 09:19:25 +08:00
1 parent 693b390df0
commit c255419412
172 files changed
+839 -18898

No files matched your search

@@ -0,0 +1,98 @@
using System.Text;
using Common.Logger;
using WinDivertNet.WinDivertWrapper;
namespace WinDivertNet;
class Program
{
static void Main(string[] args)
{
Log.Information("WinDivert 捕获启动...");
PacketSniffer.Start();
}
static void Main1(string[] args)
{
// 创建 WinDivert 控制器
using (WinDivertController controller = new WinDivertController())
{
// 检查过滤器语法
var checkResult = controller.CheckFilter("tcp.DstPort == 80");
if (!checkResult.IsValid)
{
Log.Information($"过滤器语法错误: {checkResult.ErrorMessage}");
return;
}
// 打开 WinDivert 句柄
bool success = controller.Open(
"tcp.DstPort == 80", // 过滤器
WinDivert.WINDIVERT_LAYER_NETWORK, // 网络层
0, // 优先级
WinDivert.WINDIVERT_FLAG_SNIFF // 嗅探模式
);
if (!success)
{
Log.Information("打开 WinDivert 失败!");
return;
}
Log.Information("开始监听 HTTP 流量...");
Log.Information("按 ESC 键退出");
// 设置队列长度
controller.SetParam(WinDivert.WINDIVERT_PARAM_QUEUE_LENGTH, 8192);
byte[] packet = new byte[65535];
WinDivert.WINDIVERT_ADDRESS addr = new WinDivert.WINDIVERT_ADDRESS();
// 创建线程处理数据包
Thread thread = new Thread(() =>
{
while (controller.IsValid)
{
uint readLen = controller.Receive(packet, ref addr);
if (readLen > 0)
{
// 解析数据包
PacketHeaders headers = controller.ParsePacket(packet);
if (headers.Success)
{
if (headers.HasTcpHeader && headers.HasIpHeader)
{
string srcIp = WinDivert.FormatIPv4Address(headers.IpHeader.SrcAddr);
string dstIp = WinDivert.FormatIPv4Address(headers.IpHeader.DstAddr);
ushort srcPort = headers.TcpHeader.SrcPort;
ushort dstPort = headers.TcpHeader.DstPort;
Log.Information($"捕获到 TCP 数据包: {srcIp}:{srcPort} -> {dstIp}:{dstPort}");
// 如果有数据,则尝试输出前 100 个字节
if (headers.Data != null && headers.DataLength > 0)
{
int len = (int)Math.Min(headers.DataLength, 100);
string data = Encoding.ASCII.GetString(headers.Data, 0, len);
Log.Information($"数据内容: {data}");
}
}
}
}
}
});
thread.IsBackground = true;
thread.Start();
// 等待 ESC 键退出
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
{
}
// 关闭 WinDivert
controller.Close();
Log.Information("监听结束!");
}
}
}
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<None Remove="WinDivert\WinDivert.dll" />
<None Remove="WinDivert\WinDivert64.sys" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,229 @@
using Common.Logger;
namespace WinDivertNet.WinDivertWrapper;
using System;
using System.Runtime.InteropServices;
public static class PacketSniffer
{
public static void Start1()
{
Log.Information($"进入 12313 ");
var handle = WinDivert.Open("true", WinDivert.WINDIVERT_LAYER_NETWORK, 0, WinDivert.WINDIVERT_FLAG_SNIFF);
byte[] buffer = new byte[65535];
WinDivert.WINDIVERT_ADDRESS addr = default;
uint readLen = 0;
while (true)
{
try
{
if (WinDivert.Recv(handle, buffer, (uint)buffer.Length, ref addr, ref readLen))
{
ParsePacketAndLog(buffer, readLen, addr);
}
}
catch (Exception ex)
{
Log.Information($"接收数据包时出错: {ex.Message}");
}
}
void ParsePacketAndLog(byte[] buffer, uint length, WinDivert.WINDIVERT_ADDRESS addr)
{
Log.Information($"length: {length}");
if (buffer == null || length == 0)
return;
try
{
// IPv4 数据包的最小长度为 20 字节
if (length >= 20)
{
// 检查版本 (IPv4 = 4, 位于第一个字节的高 4 位)
int version = (buffer[0] >> 4) & 0xF;
if (version == 4) // IPv4
{
int headerLength = (buffer[0] & 0xF) * 4; // IHL * 4 = 字节数
byte protocol = buffer[9]; // 协议字段
// 源 IP 和目标 IP
uint srcIp = (uint)((buffer[12]) | (buffer[13] << 8) | (buffer[14] << 16) | (buffer[15] << 24));
uint dstIp = (uint)((buffer[16]) | (buffer[17] << 8) | (buffer[18] << 16) | (buffer[19] << 24));
string srcIpStr = $"{buffer[12]}.{buffer[13]}.{buffer[14]}.{buffer[15]}";
string dstIpStr = $"{buffer[16]}.{buffer[17]}.{buffer[18]}.{buffer[19]}";
Log.Information($"IPv4: Src={srcIpStr}, Dst={dstIpStr}, Protocol={protocol}");
// 如果有足够的数据,解析 TCP 或 UDP
if (length >= (uint)(headerLength + 4) && (protocol == 6 || protocol == 17))
{
// 获取端口 (TCP 和 UDP 的前 4 字节都是源端口和目标端口)
int offset = headerLength;
ushort srcPort = (ushort)((buffer[offset] << 8) | buffer[offset + 1]);
ushort dstPort = (ushort)((buffer[offset + 2] << 8) | buffer[offset + 3]);
if (protocol == 6) // TCP
{
Log.Information($"TCP: SrcPort={srcPort}, DstPort={dstPort}");
}
else if (protocol == 17) // UDP
{
Log.Information($"UDP: SrcPort={srcPort}, DstPort={dstPort}");
}
}
}
else if (version == 6 && length >= 40) // IPv6 (头部固定 40 字节)
{
// IPv6 解析代码...
// 这里略过,需要时可以添加
}
}
}
catch (Exception ex)
{
Log.Information($"解析数据包时出错: {ex.Message}");
}
}
}
public static void Start()
{
Log.Information("WinDivert调试工具启动...");
// 检查是否以管理员身份运行
bool isAdmin = new System.Security.Principal.WindowsPrincipal(
System.Security.Principal.WindowsIdentity.GetCurrent()
).IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
if (!isAdmin)
{
Log.Information("错误: 此程序需要管理员权限才能使用WinDivert!");
Log.Information("请右键点击程序,选择'以管理员身份运行'然后重试。");
return;
}
Log.Information("步骤1: 尝试打开WinDivert...");
// 最简单的过滤器
string filter = "true";
IntPtr handle =
WinDivert.WinDivertOpen(filter, WinDivert.WINDIVERT_LAYER_NETWORK, 0, WinDivert.WINDIVERT_FLAG_SNIFF);
// 检查句柄是否有效
if (handle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
Log.Information($"错误: 无法打开WinDivert,错误码: {errorCode}");
PrintWin32Error(errorCode);
return;
}
Log.Information("成功: WinDivert句柄已打开");
// 尝试接收一个数据包
Log.Information("\n步骤2: 尝试接收数据包...");
// 为数据包分配缓冲区
byte[] buffer = new byte[65535]; // 最大以太网帧大小
// 设置接收地址结构
WinDivert.WINDIVERT_ADDRESS addr = new WinDivert.WINDIVERT_ADDRESS
{
Reserved = new byte[8] // 确保Reserved被初始化
};
// 接收数据包
uint readLen = 0;
// 尝试直接使用基本的Recv函数
Log.Information("尝试WinDivertRecv...");
bool recvResult = WinDivert.WinDivertRecv(handle, buffer, (uint)buffer.Length, ref addr, ref readLen);
if (!recvResult)
{
int errorCode = Marshal.GetLastWin32Error();
Log.Information($"错误: WinDivertRecv失败,错误码: {errorCode}");
PrintWin32Error(errorCode);
}
else
{
Log.Information($"成功: 接收到数据包,大小: {readLen} 字节");
// 打印数据包的前16个字节
string hexData = BitConverter.ToString(buffer, 0, Math.Min((int)readLen, 16));
Log.Information($"数据包前16字节: {hexData}");
}
// 重置并尝试使用Ex版本
readLen = 0;
addr = new WinDivert.WINDIVERT_ADDRESS { Reserved = new byte[8] };
Log.Information("\n尝试WinDivertRecvEx...");
bool recvExResult =
WinDivert.WinDivertRecvEx(handle, buffer, (uint)buffer.Length, 0, ref addr, ref readLen, IntPtr.Zero);
if (!recvExResult)
{
int errorCode = Marshal.GetLastWin32Error();
Log.Information($"错误: WinDivertRecvEx失败,错误码: {errorCode}");
PrintWin32Error(errorCode);
}
else
{
Log.Information($"成功: 接收到数据包,大小: {readLen} 字节");
// 打印数据包的前16个字节
string hexData = BitConverter.ToString(buffer, 0, Math.Min((int)readLen, 16));
Log.Information($"数据包前16字节: {hexData}");
}
// 最后关闭句柄
WinDivert.WinDivertClose(handle);
Log.Information("\nWinDivert句柄已关闭");
Log.Information("\n调试信息收集完成。请检查以上输出以确定问题所在。");
}
// 辅助函数:打印Win32错误信息
private static void PrintWin32Error(int errorCode)
{
switch (errorCode)
{
case 5:
Log.Information("访问被拒绝。请确认程序以管理员权限运行。");
break;
case 87:
Log.Information("参数错误。过滤器语法可能不正确。");
break;
case 123:
Log.Information("文件名、目录名或卷标语法不正确。请检查WinDivert.dll是否位于正确的路径。");
break;
case 126:
Log.Information("找不到指定的模块。无法找到WinDivert.dll文件。");
break;
case 193:
Log.Information("不是有效的Win32应用程序。WinDivert.dll可能是错误的版本(32位/64位)。");
break;
case 997:
Log.Information("正在进行重叠操作。WinDivert可能需要异步调用。");
break;
case 995:
Log.Information("由于线程退出或应用程序请求,已中止I/O操作。");
break;
case 998:
Log.Information("无效访问WinDivert。请检查是否有另一个进程正在使用相同的过滤器。");
break;
case 1450:
Log.Information("系统资源不足,无法完成请求的服务。");
break;
default:
Log.Information($"未知错误。Windows错误码: {errorCode}");
break;
}
}
}
@@ -0,0 +1,662 @@
namespace WinDivertNet.WinDivertWrapper;
using System;
using System.Runtime.InteropServices;
using System.Text;
/// <summary>
/// WinDivert 的 C# 封装类
/// </summary>
public static class WinDivert
{
#region 常量定义
// 层级常量
public const uint WINDIVERT_LAYER_NETWORK = 0;
public const uint WINDIVERT_LAYER_NETWORK_FORWARD = 1;
public const uint WINDIVERT_LAYER_FLOW = 2;
public const uint WINDIVERT_LAYER_SOCKET = 3;
public const uint WINDIVERT_LAYER_REFLECT = 4;
// 标志常量
public const ulong WINDIVERT_FLAG_SNIFF = 1;
public const ulong WINDIVERT_FLAG_DROP = 2;
public const ulong WINDIVERT_FLAG_RECV_ONLY = 4;
public const ulong WINDIVERT_FLAG_SEND_ONLY = 8;
public const ulong WINDIVERT_FLAG_NO_INSTALL = 16;
public const ulong WINDIVERT_FLAG_FRAGMENTS = 32;
public const ulong WINDIVERT_FLAG_RECV_PARTIAL = 64;
public const ulong WINDIVERT_FLAG_SEND_PARTIAL = 128;
// 事件常量
public const byte WINDIVERT_EVENT_NETWORK_PACKET = 0;
public const byte WINDIVERT_EVENT_FLOW_ESTABLISHED = 1;
public const byte WINDIVERT_EVENT_FLOW_DELETED = 2;
public const byte WINDIVERT_EVENT_SOCKET_BIND = 3;
public const byte WINDIVERT_EVENT_SOCKET_CONNECT = 4;
public const byte WINDIVERT_EVENT_SOCKET_LISTEN = 5;
public const byte WINDIVERT_EVENT_SOCKET_ACCEPT = 6;
public const byte WINDIVERT_EVENT_REFLECT_OPEN = 7;
public const byte WINDIVERT_EVENT_REFLECT_CLOSE = 8;
// 方向常量
public const byte WINDIVERT_DIRECTION_OUTBOUND = 0;
public const byte WINDIVERT_DIRECTION_INBOUND = 1;
// 参数常量
public const int WINDIVERT_PARAM_QUEUE_LENGTH = 0;
public const int WINDIVERT_PARAM_QUEUE_TIME = 1;
public const int WINDIVERT_PARAM_QUEUE_SIZE = 2;
public const int WINDIVERT_PARAM_VERSION_MAJOR = 3;
public const int WINDIVERT_PARAM_VERSION_MINOR = 4;
// 校验和常量
public const uint WINDIVERT_HELPER_NO_REPLACE = 0;
public const uint WINDIVERT_HELPER_NO_ICMPV6 = 0;
public const uint WINDIVERT_HELPER_NO_ICMP = 0;
public const uint WINDIVERT_HELPER_NO_TCP = 0;
public const uint WINDIVERT_HELPER_NO_UDP = 0;
public const uint WINDIVERT_HELPER_NO_IP = 0;
public const uint WINDIVERT_HELPER_NO_IPV6 = 0;
// 优先级范围
public const short WINDIVERT_PRIORITY_HIGHEST = 30000;
public const short WINDIVERT_PRIORITY_LOWEST = -30000;
public const short WINDIVERT_PRIORITY_DEFAULT = 0;
#endregion
#region 结构体定义
/// <summary>
/// WinDivert 地址结构
/// </summary>
// [StructLayout(LayoutKind.Sequential)]
// public struct WINDIVERT_ADDRESS
// {
// public long Timestamp; // 时间戳
// public byte Layer; // 层级
// public byte Event; // 事件
// public byte Flags; // 标志
// public byte Reserved1; // 保留
// public uint IfIdx; // 接口索引
// public uint SubIfIdx; // 子接口索引
// public byte Direction; // 方向
// public byte Reserved2; // 保留
// public ulong Reserved3; // 保留
// }
// 确保结构体布局正确 - 使用StructLayout和FieldOffset
// 完全匹配WinDivert 2.0版本的结构体定义
[StructLayout(LayoutKind.Sequential)]
public struct WINDIVERT_ADDRESS
{
public long Timestamp;
public byte Layer;
public byte Event;
public ushort Flags;
public uint IfIdx;
public uint SubIfIdx;
// 注意:在WinDivert 2.0中,Reserved字段是64位(8字节)对齐的
// 所以我们使用固定大小的字节数组
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Reserved;
}
/// <summary>
/// IPv4 头结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct WINDIVERT_IPHDR
{
public byte HdrLength4; // 组合字段: 版本 (4 bits) + 头长度 (4 bits)
public byte TOS; // 服务类型
public ushort Length; // 总长度
public ushort Id; // 标识
public ushort FragOff0; // 组合字段: 标志 (3 bits) + 分片偏移 (13 bits)
public byte TTL; // 生存时间
public byte Protocol; // 协议
public ushort Checksum; // 检验和
public uint SrcAddr; // 源地址
public uint DstAddr; // 目标地址
}
/// <summary>
/// IPv6 头结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct WINDIVERT_IPV6HDR
{
public uint FlowLabel0; // 组合字段: 版本 (4 bits) + 通信类 (8 bits) + 流标签 (20 bits)
public ushort Length; // 有效载荷长度
public byte NextHdr; // 下一个头
public byte HopLimit; // 跳数限制
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] SrcAddr; // 源地址
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] DstAddr; // 目标地址
}
/// <summary>
/// TCP 头结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct WINDIVERT_TCPHDR
{
public ushort SrcPort; // 源端口
public ushort DstPort; // 目标端口
public uint SeqNum; // 序列号
public uint AckNum; // 确认号
public ushort Reserved10; // 组合字段: 数据偏移 (4 bits) + 保留 (6 bits) + 标志 (6 bits)
public ushort Window; // 窗口大小
public ushort Checksum; // 检验和
public ushort UrgPtr; // 紧急指针
}
/// <summary>
/// UDP 头结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct WINDIVERT_UDPHDR
{
public ushort SrcPort; // 源端口
public ushort DstPort; // 目标端口
public ushort Length; // 长度
public ushort Checksum; // 检验和
}
/// <summary>
/// ICMP 头结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct WINDIVERT_ICMPHDR
{
public byte Type; // 类型
public byte Code; // 代码
public ushort Checksum; // 检验和
public uint Body; // 消息体
}
/// <summary>
/// ICMPv6 头结构
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct WINDIVERT_ICMPV6HDR
{
public byte Type; // 类型
public byte Code; // 代码
public ushort Checksum; // 检验和
public uint Body; // 消息体
}
#endregion
#region 原生 API 导入
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern IntPtr WinDivertOpen(
[MarshalAs(UnmanagedType.LPStr)] string filter,
uint layer,
short priority,
ulong flags);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern bool WinDivertRecv(
IntPtr handle,
[Out] byte[] pPacket,
uint packetLen,
ref WINDIVERT_ADDRESS pAddr,
ref uint readLen);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern bool WinDivertRecvEx(
IntPtr handle,
[Out] byte[] pPacket,
uint packetLen,
uint recvFlags,
[In, Out] ref WINDIVERT_ADDRESS pAddr,
[In, Out] ref uint readLen,
IntPtr lpOverlapped);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertSend(
IntPtr handle,
byte[] pPacket,
uint packetLen,
ref WINDIVERT_ADDRESS pAddr,
ref uint writeLen);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertSendEx(
IntPtr handle,
byte[] pPacket,
uint packetLen,
uint flags,
ref WINDIVERT_ADDRESS pAddr,
ref uint writeLen,
IntPtr overlapped);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern bool WinDivertClose(
IntPtr handle);
// 获取错误信息的帮助函数
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern uint WinDivertHelperNtohs(ushort value);
// 获取WinDivert特定错误
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr WinDivertHelperFormatFilter(
[MarshalAs(UnmanagedType.LPStr)] string filter,
WinDivertFormatFlags formatFlags,
IntPtr buffer,
uint bufferLen);
// 用于格式化过滤器的标志
[Flags]
public enum WinDivertFormatFlags : uint
{
Normal = 0,
NoNumbers = 1,
Aliases = 2,
}
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertSetParam(
IntPtr handle,
int param,
ulong value);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertGetParam(
IntPtr handle,
int param,
ref ulong value);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern uint WinDivertHelperCalcChecksums(
byte[] pPacket,
uint packetLen,
ref WINDIVERT_ADDRESS pAddr,
uint flags);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertHelperParsePacket(
byte[] pPacket,
uint packetLen,
out IntPtr ppIpHdr,
out IntPtr ppIpv6Hdr,
out IntPtr ppIcmpHdr,
out IntPtr ppIcmpv6Hdr,
out IntPtr ppTcpHdr,
out IntPtr ppUdpHdr,
out IntPtr ppData,
out ushort pDataLen
);
// 安全包装 - 处理异常大小问题
public static bool SafeRecv(IntPtr handle, byte[] buffer, ref WINDIVERT_ADDRESS addr, out byte[] packet)
{
packet = null;
// 确保结构体正确初始化
if (addr.Reserved == null)
{
addr.Reserved = new byte[8];
}
uint readLen = 0;
// 使用基础函数调用
bool result = WinDivertRecv(handle, buffer, (uint)buffer.Length, ref addr, ref readLen);
if (!result) return false;
// *** 关键修复:处理异常大小 ***
// 通过数据包的第一个字节验证它是IPv4还是IPv6数据包
if (buffer.Length > 0)
{
byte version = (byte)(buffer[0] >> 4);
// IPv4数据包版本是4,IPv6是6
if (version == 4 || version == 6)
{
// 检查IP头部中的长度字段
// 对于IPv4,长度在字节3-4中;对于IPv6,长度在字节5-6中
ushort ipLength;
if (version == 4 && buffer.Length >= 4)
{
ipLength = (ushort)((buffer[2] << 8) | buffer[3]);
// IPv4报头最小20字节,最大65535字节
if (ipLength >= 20 && ipLength <= 65535)
{
readLen = ipLength;
}
else if (buffer.Length >= 20) // 如果长度字段无效,至少读取IPv4头
{
readLen = 1500; // 使用标准以太网MTU大小
}
}
else if (version == 6 && buffer.Length >= 6)
{
ipLength = (ushort)((buffer[4] << 8) | buffer[5]);
// IPv6报头固定40字节,加上有效载荷
if (ipLength + 40 <= 65535)
{
readLen = (uint)(ipLength + 40);
}
else if (buffer.Length >= 40) // 如果长度字段无效,至少读取IPv6头
{
readLen = 1500; // 使用标准以太网MTU大小
}
}
}
// 如果仍然出现异常大小,强制使用安全值
if (readLen > 9000 || readLen == 0)
{
// 设置为安全的默认值(标准以太网MTU)
readLen = 1500;
}
}
// 只提取有效数据
packet = new byte[readLen];
Array.Copy(buffer, packet, readLen);
return true;
}
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertHelperParseIPv4Address(
[MarshalAs(UnmanagedType.LPStr)] string str,
ref uint pAddr);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertHelperParseIPv6Address(
[MarshalAs(UnmanagedType.LPStr)] string str,
byte[] pAddr);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertHelperFormatIPv4Address(
uint addr,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer,
uint bufLen);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertHelperFormatIPv6Address(
byte[] addr,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer,
uint bufLen);
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertHelperCheckFilter(
[MarshalAs(UnmanagedType.LPStr)] string filter,
uint layer,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder errorStr,
uint errorStrLen);
#endregion
#region 辅助方法
/// <summary>
/// 打开 WinDivert 句柄
/// </summary>
/// <param name="filter">过滤器表达式</param>
/// <param name="layer">层级</param>
/// <param name="priority">优先级</param>
/// <param name="flags">标志</param>
/// <returns>WinDivert 句柄</returns>
public static IntPtr Open(string filter, uint layer, short priority, ulong flags) =>
WinDivertOpen(filter, layer, priority, flags);
/// <summary>
/// 接收数据包
/// </summary>
/// <param name="handle">WinDivert 句柄</param>
/// <param name="buffer">数据缓冲区</param>
/// <param name="len">缓冲区长度</param>
/// <param name="addr">地址结构</param>
/// <param name="readLen">实际读取长度</param>
/// <returns>是否成功</returns>
public static bool Recv(IntPtr handle, byte[] buffer, uint bufferLength, ref WINDIVERT_ADDRESS addr,
ref uint readLen)
{
// 明确初始化readLen为0
readLen = 0;
// 确保WINDIVERT_ADDRESS结构体初始化正确
if (addr.Reserved == null)
{
addr.Reserved = new byte[8];
}
return WinDivertRecv(handle, buffer, bufferLength, ref addr, ref readLen);
}
/// <summary>
/// 扩展接收数据包
/// </summary>
/// <param name="handle">WinDivert 句柄</param>
/// <param name="buffer">数据缓冲区</param>
/// <param name="len">缓冲区长度</param>
/// <param name="flags">标志</param>
/// <param name="addr">地址结构</param>
/// <param name="readLen">实际读取长度</param>
/// <param name="overlapped">重叠 I/O 结构</param>
/// <returns>是否成功</returns>
// 更安全的Recv包装
public static bool RecvEx(IntPtr handle, byte[] buffer, ref WINDIVERT_ADDRESS addr, ref uint readLen)
{
// 确保结构体正确初始化
if (addr.Reserved == null)
addr.Reserved = new byte[8];
// 清零readLen
readLen = 0;
// 使用Ex版本,提供更多控制和稳定性
return WinDivertRecvEx(
handle,
buffer,
(uint)buffer.Length,
0, // 默认接收标志
ref addr,
ref readLen,
IntPtr.Zero // 非异步调用
);
}
/// <summary>
/// 发送数据包
/// </summary>
/// <param name="handle">WinDivert 句柄</param>
/// <param name="buffer">数据缓冲区</param>
/// <param name="len">缓冲区长度</param>
/// <param name="addr">地址结构</param>
/// <param name="writeLen">实际写入长度</param>
/// <returns>是否成功</returns>
public static bool Send(IntPtr handle, byte[] buffer, uint len, ref WINDIVERT_ADDRESS addr, ref uint writeLen) =>
WinDivertSend(handle, buffer, len, ref addr, ref writeLen);
/// <summary>
/// 扩展发送数据包
/// </summary>
/// <param name="handle">WinDivert 句柄</param>
/// <param name="buffer">数据缓冲区</param>
/// <param name="len">缓冲区长度</param>
/// <param name="flags">标志</param>
/// <param name="addr">地址结构</param>
/// <param name="writeLen">实际写入长度</param>
/// <param name="overlapped">重叠 I/O 结构</param>
/// <returns>是否成功</returns>
public static bool SendEx(IntPtr handle, byte[] buffer, uint len, uint flags, ref WINDIVERT_ADDRESS addr,
ref uint writeLen, IntPtr overlapped) =>
WinDivertSendEx(handle, buffer, len, flags, ref addr, ref writeLen, overlapped);
/// <summary>
/// 关闭 WinDivert 句柄
/// </summary>
/// <param name="handle">WinDivert 句柄</param>
/// <returns>是否成功</returns>
public static bool Close(IntPtr handle) =>
WinDivertClose(handle);
/// <summary>
/// 设置参数
/// </summary>
/// <param name="handle">WinDivert 句柄</param>
/// <param name="param">参数类型</param>
/// <param name="value">参数值</param>
/// <returns>是否成功</returns>
public static bool SetParam(IntPtr handle, int param, ulong value) =>
WinDivertSetParam(handle, param, value);
/// <summary>
/// 获取参数
/// </summary>
/// <param name="handle">WinDivert 句柄</param>
/// <param name="param">参数类型</param>
/// <param name="value">参数值</param>
/// <returns>是否成功</returns>
public static bool GetParam(IntPtr handle, int param, ref ulong value) =>
WinDivertGetParam(handle, param, ref value);
/// <summary>
/// 计算校验和
/// </summary>
/// <param name="buffer">数据缓冲区</param>
/// <param name="len">缓冲区长度</param>
/// <param name="addr">地址结构</param>
/// <param name="flags">标志</param>
/// <returns>校验和结果</returns>
public static uint CalcChecksums(byte[] buffer, uint len, ref WINDIVERT_ADDRESS addr, uint flags) =>
WinDivertHelperCalcChecksums(buffer, len, ref addr, flags);
/// <summary>
/// 解析数据包【传递至此的 buffer 必须是新的!必须是空的!不能是用过的!】
/// </summary>
/// <param name="buffer">数据缓冲区</param>
/// <param name="len">缓冲区长度</param>
/// <param name="ppIpHdr">IPv4 头指针</param>
/// <param name="ppIpv6Hdr">IPv6 头指针</param>
/// <param name="ppIcmpHdr">ICMP 头指针</param>
/// <param name="ppIcmpv6Hdr">ICMPv6 头指针</param>
/// <param name="ppTcpHdr">TCP 头指针</param>
/// <param name="ppUdpHdr">UDP 头指针</param>
/// <param name="ppData">数据指针</param>
/// <param name="pDataLen">数据长度</param>
/// <returns>是否成功</returns>
public static bool ParsePacket(
byte[] buffer,
uint len,
ref IntPtr ppIpHdr,
ref IntPtr ppIpv6Hdr,
ref IntPtr ppIcmpHdr,
ref IntPtr ppIcmpv6Hdr,
ref IntPtr ppTcpHdr,
ref IntPtr ppUdpHdr,
ref IntPtr ppData,
ref ushort pDataLen
)
{
return WinDivertHelperParsePacket(
buffer,
len,
out ppIpHdr,
out ppIpv6Hdr,
out ppIcmpHdr,
out ppIcmpv6Hdr,
out ppTcpHdr,
out ppUdpHdr,
out ppData,
out pDataLen
);
}
/// <summary>
/// 解析 IPv4 地址
/// </summary>
/// <param name="str">IP 地址字符串</param>
/// <param name="pAddr">地址结果</param>
/// <returns>是否成功</returns>
public static bool ParseIPv4Address(string str, ref uint pAddr) =>
WinDivertHelperParseIPv4Address(str, ref pAddr);
/// <summary>
/// 解析 IPv6 地址
/// </summary>
/// <param name="str">IP 地址字符串</param>
/// <param name="pAddr">地址结果</param>
/// <returns>是否成功</returns>
public static bool ParseIPv6Address(string str, byte[] pAddr) =>
WinDivertHelperParseIPv6Address(str, pAddr);
/// <summary>
/// 格式化 IPv4 地址
/// </summary>
/// <param name="addr">IP 地址</param>
/// <returns>格式化后的字符串</returns>
public static string FormatIPv4Address(uint addr)
{
StringBuilder buffer = new StringBuilder(16);
if (WinDivertHelperFormatIPv4Address(addr, buffer, 16))
{
return buffer.ToString();
}
return string.Empty;
}
/// <summary>
/// 格式化 IPv6 地址
/// </summary>
/// <param name="addr">IP 地址</param>
/// <returns>格式化后的字符串</returns>
public static string FormatIPv6Address(byte[] addr)
{
StringBuilder buffer = new StringBuilder(46);
if (WinDivertHelperFormatIPv6Address(addr, buffer, 46))
{
return buffer.ToString();
}
return string.Empty;
}
/// <summary>
/// 检查过滤器语法
/// </summary>
/// <param name="filter">过滤器表达式</param>
/// <param name="layer">层级</param>
/// <param name="errorStr">错误信息</param>
/// <param name="errorStrLen">错误信息长度</param>
/// <returns>是否有效</returns>
public static bool CheckFilter(string filter, uint layer, StringBuilder errorStr, uint errorStrLen) =>
WinDivertHelperCheckFilter(filter, layer, errorStr, errorStrLen);
#endregion
[StructLayout(LayoutKind.Sequential)]
public struct PacketHeaders
{
public IntPtr IpHdr;
public IntPtr Ipv6Hdr;
public IntPtr IcmpHdr;
public IntPtr Icmpv6Hdr;
public IntPtr TcpHdr;
public IntPtr UdpHdr;
public IntPtr Data;
public uint DataLen;
}
[DllImport("WinDivert.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool WinDivertHelperParsePacketEx(
[In] byte[] pPacket,
uint packetLen,
ref PacketHeaders headers);
}
@@ -0,0 +1,609 @@
using Common.Logger;
namespace WinDivertNet.WinDivertWrapper;
using System;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
/// <summary>
/// WinDivert 高级封装类
/// </summary>
public class WinDivertController : IDisposable
{
private IntPtr _handle;
private bool _disposed = false;
public IntPtr Handle => _handle;
/// <summary>
/// 获取句柄是否有效
/// </summary>
public bool IsValid => _handle != IntPtr.Zero;
/// <summary>
/// 构造函数
/// </summary>
public WinDivertController()
{
_handle = IntPtr.Zero;
}
/// <summary>
/// 析构函数
/// </summary>
~WinDivertController()
{
Dispose(false);
}
/// <summary>
/// 打开 WinDivert 句柄
/// </summary>
/// <param name="filter">过滤器表达式</param>
/// <param name="layer">层级</param>
/// <param name="priority">优先级</param>
/// <param name="flags">标志</param>
/// <returns>是否成功</returns>
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();
Log.Information($"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);
}
/// <summary>
/// 关闭 WinDivert 句柄
/// </summary>
public void Close()
{
if (IsValid)
{
WinDivert.Close(_handle);
_handle = IntPtr.Zero;
}
}
/// <summary>
/// 接收数据包
/// </summary>
/// <param name="buffer">数据缓冲区</param>
/// <param name="addr">地址结构</param>
/// <returns>实际读取的字节数,失败返回 0</returns>
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))
{
Log.Information($"Receive: {readLen}");
return readLen;
}
return 0;
}
/// <summary>
/// 异步接收数据包
/// </summary>
/// <param name="buffer">数据缓冲区</param>
/// <param name="addr">地址结构</param>
/// <returns>实际读取的字节数的任务</returns>
public Task<uint> ReceiveAsync(byte[] buffer, WinDivert.WINDIVERT_ADDRESS addr)
{
return Task.Run(() => Receive(buffer, ref addr));
}
/// <summary>
/// 发送数据包
/// </summary>
/// <param name="buffer">数据缓冲区</param>
/// <param name="addr">地址结构</param>
/// <returns>实际写入的字节数,失败返回 0</returns>
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;
}
/// <summary>
/// 异步发送数据包
/// </summary>
/// <param name="buffer">数据缓冲区</param>
/// <param name="addr">地址结构</param>
/// <returns>实际写入的字节数的任务</returns>
public Task<uint> SendAsync(byte[] buffer, WinDivert.WINDIVERT_ADDRESS addr)
{
return Task.Run(() => Send(buffer, ref addr));
}
/// <summary>
/// 设置参数
/// </summary>
/// <param name="param">参数类型</param>
/// <param name="value">参数值</param>
/// <returns>是否成功</returns>
public bool SetParam(int param, ulong value)
{
if (!IsValid)
{
return false;
}
return WinDivert.SetParam(_handle, param, value);
}
/// <summary>
/// 获取参数
/// </summary>
/// <param name="param">参数类型</param>
/// <param name="value">参数值</param>
/// <returns>是否成功</returns>
public bool GetParam(int param, ref ulong value)
{
if (!IsValid)
{
return false;
}
return WinDivert.GetParam(_handle, param, ref value);
}
/// <summary>
/// 校验包数据的校验和
/// </summary>
/// <param name="buffer">数据缓冲区</param>
/// <param name="addr">地址结构</param>
/// <param name="flags">标志</param>
/// <returns>校验和结果</returns>
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);
}
/// <summary>
/// 检查过滤器语法
/// </summary>
/// <param name="filter">过滤器表达式</param>
/// <param name="layer">层级</param>
/// <returns>检查结果和错误信息</returns>
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());
}
/// <summary>
/// 解析数据包
/// </summary>
/// <param name="packet">数据包</param>
/// <returns>解析结果</returns>
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<WinDivert.WINDIVERT_IPHDR>(ppIpHdr);
headers.HasIpHeader = true;
}
if (ppIpv6Hdr != IntPtr.Zero)
{
headers.Ipv6Header = Marshal.PtrToStructure<WinDivert.WINDIVERT_IPV6HDR>(ppIpv6Hdr);
headers.HasIpv6Header = true;
}
if (ppTcpHdr != IntPtr.Zero)
{
headers.TcpHeader = Marshal.PtrToStructure<WinDivert.WINDIVERT_TCPHDR>(ppTcpHdr);
headers.HasTcpHeader = true;
}
if (ppUdpHdr != IntPtr.Zero)
{
headers.UdpHeader = Marshal.PtrToStructure<WinDivert.WINDIVERT_UDPHDR>(ppUdpHdr);
headers.HasUdpHeader = true;
}
if (ppIcmpHdr != IntPtr.Zero)
{
headers.IcmpHeader = Marshal.PtrToStructure<WinDivert.WINDIVERT_ICMPHDR>(ppIcmpHdr);
headers.HasIcmpHeader = true;
}
if (ppIcmpv6Hdr != IntPtr.Zero)
{
headers.Icmpv6Header = Marshal.PtrToStructure<WinDivert.WINDIVERT_ICMPV6HDR>(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;
}
/// <summary>
/// 修改包的源 IP 地址
/// </summary>
/// <param name="packet">数据包</param>
/// <param name="sourceIp">新的源 IP 地址</param>
/// <returns>是否成功</returns>
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<WinDivert.WINDIVERT_IPHDR>();
// 修改源 IP 地址
byte[] addrBytes = BitConverter.GetBytes(addr);
Array.Copy(addrBytes, 0, packet, ipHdrOffset - 8, 4);
return true;
}
/// <summary>
/// 修改包的目标 IP 地址
/// </summary>
/// <param name="packet">数据包</param>
/// <param name="destinationIp">新的目标 IP 地址</param>
/// <returns>是否成功</returns>
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<WinDivert.WINDIVERT_IPHDR>();
// 修改目标 IP 地址
byte[] addrBytes = BitConverter.GetBytes(addr);
Array.Copy(addrBytes, 0, packet, ipHdrOffset - 4, 4);
return true;
}
/// <summary>
/// 修改包的源端口
/// </summary>
/// <param name="packet">数据包</param>
/// <param name="sourcePort">新的源端口</param>
/// <returns>是否成功</returns>
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;
}
/// <summary>
/// 修改包的目标端口
/// </summary>
/// <param name="packet">数据包</param>
/// <param name="destinationPort">新的目标端口</param>
/// <returns>是否成功</returns>
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;
}
/// <summary>
/// 重新计算包的校验和
/// </summary>
/// <param name="packet">数据包</param>
/// <param name="addr">地址结构</param>
/// <returns>是否成功</returns>
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;
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 释放资源
/// </summary>
/// <param name="disposing">是否为显式释放</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// 释放托管资源
}
// 释放非托管资源
Close();
_disposed = true;
}
}
}
/// <summary>
/// 数据包头信息
/// </summary>
public class PacketHeaders
{
/// <summary>
/// 解析是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 是否包含 IPv4 头
/// </summary>
public bool HasIpHeader { get; set; }
/// <summary>
/// 是否包含 IPv6 头
/// </summary>
public bool HasIpv6Header { get; set; }
/// <summary>
/// 是否包含 TCP 头
/// </summary>
public bool HasTcpHeader { get; set; }
/// <summary>
/// 是否包含 UDP 头
/// </summary>
public bool HasUdpHeader { get; set; }
/// <summary>
/// 是否包含 ICMP 头
/// </summary>
public bool HasIcmpHeader { get; set; }
/// <summary>
/// 是否包含 ICMPv6 头
/// </summary>
public bool HasIcmpv6Header { get; set; }
/// <summary>
/// IPv4 头
/// </summary>
public WinDivert.WINDIVERT_IPHDR IpHeader { get; set; }
/// <summary>
/// IPv6 头
/// </summary>
public WinDivert.WINDIVERT_IPV6HDR Ipv6Header { get; set; }
/// <summary>
/// TCP 头
/// </summary>
public WinDivert.WINDIVERT_TCPHDR TcpHeader { get; set; }
/// <summary>
/// UDP 头
/// </summary>
public WinDivert.WINDIVERT_UDPHDR UdpHeader { get; set; }
/// <summary>
/// ICMP 头
/// </summary>
public WinDivert.WINDIVERT_ICMPHDR IcmpHeader { get; set; }
/// <summary>
/// ICMPv6 头
/// </summary>
public WinDivert.WINDIVERT_ICMPV6HDR Icmpv6Header { get; set; }
/// <summary>
/// 数据部分
/// </summary>
public byte[] Data { get; set; }
/// <summary>
/// 数据长度
/// </summary>
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();
}
}