diff --git a/README.md b/README.md index a2b4809..1563a7a 100644 --- a/README.md +++ b/README.md @@ -8,94 +8,100 @@ ``` ### 2 功能介绍 -* Filter对象支持Lambda构建filter language,脱离字符串的苦海; -* 内存安全的WinDivert对象,基于IOCP的ValueTask异步发送与接收方法; -* 内存安全的WinDivertPacket对象,提供获取包有效数据长度、解包、重构chucksums等; -* WinDivertParseResult提供对解包的数据进行精细修改,修改后对WinDivertPacket直接生效; - -### 3 Api表 -#### 3.1 WinDivert -| Api | 描述 | 原Api | -| -------------------------------------------------------------------------------- | ------------------ | ----------------- | -| WinDivert(Filter, WinDivertLayer, short , WinDivertFlag) | 构造器 | WinDivertOpen | -| int Recv(WinDivertPacket, WinDivertAddress) | 同步阻塞读取数据包 | RecvEx | -| int Recv(WinDivertPacket, WinDivertAddress, CancellationToken) | 同步阻塞读取数据包 | RecvEx | -| `ValueTask` RecvAsync(WinDivertPacket, WinDivertAddress) | 异步IO读取数据包 | RecvEx | -| `ValueTask` RecvAsync(WinDivertPacket, WinDivertAddress, CancellationToken) | 异步IO读取数据包 | RecvEx | -| int Send(WinDivertPacket, WinDivertAddress) | 同步阻塞发送数据包 | SendEx | -| int Send(WinDivertPacket, WinDivertAddress, CancellationToken) | 同步阻塞发送数据包 | SendEx | -| `ValueTask` SendAsync(WinDivertPacket, WinDivertAddress) | 异步IO发送数据包 | SendEx | -| `ValueTask` SendAsync(WinDivertPacket, WinDivertAddress, CancellationToken) | 异步IO发送数据包 | SendEx | -| bool Shutdown(WinDivertShutdown) | 关闭 | WinDivertShutdown | -| void Dispose() | 关闭并释放资源 | WinDivertClose | - -#### 3.2 Filter -| Api | 描述 | 原Api | -| --------------------------------------------- | ------------------------- | ---------------------------- | -| static string Format(string, WinDivertLayer) | 格式化filter | WinDivertHelperFormatFilter | -| static string Compile(string, WinDivertLayer) | 编译filter | WinDivertHelperCompileFilter | -| static Filter True { get; } | 获取值为true的filter | 无 | -| static Filter False { get; } | 获取值为false的filter | 无 | -| Filter And(Expression>) | 使用and逻辑创建新的fitler | 无 | -| Filter And(Filter) | 使用and逻辑创建新的fitler | 无 | -| Filter Or(Expression>) | 使用or逻辑创建新的fitler | 无 | -| Filter Or(Filter) | 使用or逻辑创建新的fitler | 无 | - -#### 3.3 WinDivertPacket -| Api | 描述 | 原Api | -| --------------------------------------------------- | --------------------------------------------------------------- | ---------------------------- | -| int Capacity { get; } | 获取缓冲区容量 | 无 | -| int Length { get; set;} | 获取或设置有效数据的长度 | 无 | -| Span Span { get; } | 获取有效数据视图 | 无 | -| void Clear() | 将有效数据清0 | 无 | -| `Span` GetSpan(int, int) | 获取缓冲区的Span | 无 | -| WindivertBufferWriter GetWriter(int) | 获取缓冲区的Writer对象 | 无 | -| bool CalcChecksums(WinDivertAddress, ChecksumsFlag) | 重新计算和修改相关的Checksums | WinDivertHelperCalcChecksums | -| bool CalcNetworkIfIdx(WinDivertAddress ) | 根据IP地址重新计算和修改addr的Network->IfIdx | 无 | -| bool CalcOutboundFlag(WinDivertAddress) | 根据IP地址和addr.Network->IfIdx重新计算和修改addr的Outbound标记 | 无 | -| bool CalcLoopbackFlag(WinDivertAddress) | 根据IP地址重新计算和修改addr的Loopback标记 | 无 | -| bool DecrementTTL() | ttl减1 | WinDivertHelperDecrementTTL | -| int GetHashCode() | 获取包的哈希 | WinDivertHelperHashPacket | -| int GetHashCode(long) | 获取包的哈希 | WinDivertHelperHashPacket | -| WinDivertParseResult GetParseResult() | 获取包的解析结果 | WinDivertHelperParsePacket | - -#### 3.4 WinDivertRouter -| Api | 描述 | -| ------------------------------------------ | ------------------ | -| IPAddress DstAddress { get; } | 获取目标地址 | -| IPAddress SrcAddress { get; } | 获取源地址 | -| int InterfaceIndex { get; } | 获取网络接口索引 | -| bool IsOutbound { get; } | 获取是否为出口方向 | -| WinDivertRouter(IPAddress) | 构造器 | -| WinDivertRouter(IPAddress, IPAddress) | 构造器 | -| WinDivertRouter(IPAddress, IPAddress, int) | 构造器 | - - -### 4 如何使用 -``` +* 抓取网络数据包 +* 过滤或丢弃网络数据包 +* 嗅探网络数据包 +* 注入网络数据包 +* 修改网络数据包 + + +### 3 如何使用 +#### 3.1 抓包改包 +```c# var filter = Filter.True .And(f => f.Network.Loopback) .And(f => f.Tcp.DstPort == 443) .And(f => f.Tcp.Ack == true); - + using var divert = new WinDivert(filter, WinDivertLayer.Network); using var packet = new WinDivertPacket(); using var addr = new WinDivertAddress(); -while(true) +while (true) { // 读包 await divert.RecvAsync(packet, addr); + ProcessPacket(packet, addr); + + // 修改后发出 + await divert.SendAsync(packet, addr); +} + +static unsafe void ProcessPacket(WinDivertPacket packet, WinDivertAddress addr) +{ // 解包 var result = packet.GetParseResult(); // 改包 - result.TcpHeader->DstPort = 443; + result.TcpHeader->DstPort = 443; // 重算checksums packet.CalcChecksums(addr); +} +``` - // 修改后发出 - await divert.SendAsync(packet, addr); +#### 3.2 注入数据包 +```c# +private async Task SendEchoRequestAsync(IPAddress dstAddr) +{ + // 使用router计算将进行通讯的本机地址 + var router = new WinDivertRouter(dstAddr); + using var addr = router.CreateAddress(); + using var packet = this.CreateIPV4EchoPacket(router.SrcAddress, router.DstAddress); + + packet.CalcChecksums(addr); // 计算checksums,因为创建包时没有计算 + + await this.divert.SendAsync(packet, addr); +} + +/// +/// 创建icmp的echo包 +/// +/// +/// +/// +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; } +``` \ No newline at end of file