230 lines
8.7 KiB
C#
230 lines
8.7 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|