1 前言WindivertDotnet是面向对象的WinDivert的dotnet异步封装 , 其提供如下的发送数据方法:
ValueTask<int> SendAsync(WinDivertPacket packet,WinDivertAddress addr,CancellationToken cancellationToken)
在修改包的场景,我们通过RecvAsync()
方法获取具有内容的WinDivertPacket
和WinDivertAddress
对象实例 , 简单修改这两个对象的一些值之后 , 就可以发送出去 。
但在注入的场景 , 我们需要无中生成WinDivertPacket
和WinDivertAddress
两个对象,前者是IP包的完整数据,后者主要指示数据要经过的网络适配器的索引、数据是入口还是出口方向、是否为loopback等信息 , 下面我将使用WindivertDotnet来开发一个批量Ping功能的示例来教大家怎么注入数据包 。
2 发出Ping包2.1 路由计算在发Ping的场景中,我们只知道目的地IP地址 , WinDivertRouter对象可以帮们提前算出路由信息 , 得到以下表格的内容:
属性说明IPAddress DstAddress目的地IP地址IPAddress SrcAddress源IP地址int InterfaceIndex经过的网络适配器的索引bool IsOutbound是否为出口方向// 使用dstAddr创建routervar router = new WinDivertRouter(dstAddr);
2.2 创建WinDivertAddressWinDivertAddress的如下属性必须要设置正确 , 它是IP数据包构建链路数据包必须的项:
属性说明WinDivertAddress.NetWork->IfIdx发包的网络适配器的索引WinDivertAddress.Flags.OutboundFlag是否为出口方向WinDivertAddress.Flags.LoopbackFlag是否为回环// 使用router创建WinDivertAddressusing WinDivertAddress addr = router.CreateAddress();
2.3 创建WinDivertPacket因为从router里知道了源IP和目标IP,所以创建ICMP ping功能的WinDivertPacket就比较容易 。
/// <summary>/// 创建icmp的echo包/// </summary>/// <param name="srcAddr"></param>/// <param name="dstAddr"></param>/// <returns></returns>private unsafe WinDivertPacket CreateIPV4EchoPacket(IPAddress srcAddr, IPAddress dstAddr){// ipv4头var ipHeader = new IPV4Header{TTL = 128,Version = 4,DstAddr = dstAddr,SrcAddr = srcAddr,Protocol = ProtocolType.Icmp,HdrLength = (byte)(sizeof(IPV4Header) / 4),Id = ++this.id,Length = (ushort)(sizeof(IPV4Header) + sizeof(IcmpV4Header))};// icmp头var icmpHeader = new IcmpV4Header{Type = IcmpV4MessageType.EchoRequest,Code = default,Identifier = ipHeader.Id,SequenceNumber = ++this.sequenceNumber,};// 将数据写到packet缓冲区var packet = new WinDivertPacket(ipHeader.Length);var writer = packet.GetWriter();writer.Write(ipHeader);writer.Write(icmpHeader);return packet;}
2.4 发出数据包现在我们可使用Windivert对象,将为每个目的地IP创建的WinDivertPacket
和WinDivertAddress
两个对象发送出去:
/// <summary>/// 发送icmp的echo请求包/// </summary>/// <param name="dstAddrs"></param>/// <returns></returns>private async Task SendEchoRequestAsync(IEnumerable<IPAddress> dstAddrs){foreach (var address in dstAddrs){// 使用router计算将进行通讯的本机地址var router = new WinDivertRouter(address);using var addr = router.CreateAddress();using var packet = this.CreateIPV4EchoPacket(router.SrcAddress, router.DstAddress);packet.CalcChecksums(addr);// 计算checksums,因为创建包时没有计算await this.divert.SendAsync(packet, addr);}}
3 接收回复包3.1 Filter我们可以使用过滤器,将接收的内容过滤为icmp,并且数据是入口方向,必要不必要的数据到达我们的应用层而增加了处理负担:
// 只接受进入系统的icmpvar filter = Filter.True.And(f => f.IsIcmp && f.Network.Inbound);this.divert = new WinDivert(filter, WinDivertLayer.Network);
3.2 接收数据接收数据这个就简单了,这是WindivertDotnet最擅长的技能:
/// <summary>/// 监听ping的回复/// </summary>/// <param name="cancellationToken">取消令牌</param>/// <returns></returns>private async Task<HashSet<IPAddress>> RecvEchoReplyAsync(CancellationToken cancellationToken){var results = new HashSet<IPAddress>();using var packet = new WinDivertPacket();using var addr = new WinDivertAddress();while (cancellationToken.IsCancellationRequested == false){try{await this.divert.RecvAsync(packet, addr, cancellationToken);if (TryGetEchoReplyAddr(packet, out var value)){results.Add(value);}// 把packet发出 , 避免系统其它软件此刻也有ping而收不到回复await this.divert.SendAsync(packet, addr, cancellationToken);}catch (OperationCanceledException){break;}}return results;}
3.3 解析回复的IP/// <summary>/// 解析出icmp回复信息/// </summary>/// <param name="packet">数据包</param>/// <param name="value">回复的IP</param>/// <returns></returns>private unsafe static bool TryGetEchoReplyAddr(WinDivertPacket packet, [MaybeNullWhen(false)] out IPAddress value){var result = packet.GetParseResult();if (result.IcmpV4Header != null &&result.IcmpV4Header->Type == IcmpV4MessageType.EchoReply){value = https://www.huyubaike.com/biancheng/result.IPV4Header->SrcAddr;return true;}else if (result.IcmpV6Header != null &&result.IcmpV6Header->Type == IcmpV6MessageType.EchoReply){value = result.IPV6Header->SrcAddr;return true;}value = null;return false;}
推荐阅读
- 三星怎么快速截屏(三星手机怎么录屏)
- 三星截屏快速手势(三星可以敲击背部截屏吗)
- yy怎么创建主频道(yy怎么快速进入私人频道)
- yy如何创建小频道(yy怎么快速进入私人频道)
- 抖音怎么快速设置动态壁纸(抖音动态最火壁纸美女)
- 绝地求生新手如何快速入门(绝地求生新手入门教学怎么跳过)
- 开源WindivertDotnet
- 玩绝地求生,怎样快速上分(pubg快速上分)
- 学生怎样能快速赚钱(学生捡破烂赚钱)
- iphone 12支持多少瓦的快充_iphone12支持30w快充吗