Skip to content

Commit

Permalink
update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
xljiulang committed Oct 19, 2022
1 parent 0021b04 commit a38115c
Showing 1 changed file with 76 additions and 70 deletions.
146 changes: 76 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>` RecvAsync(WinDivertPacket, WinDivertAddress) | 异步IO读取数据包 | RecvEx |
| `ValueTask<int>` RecvAsync(WinDivertPacket, WinDivertAddress, CancellationToken) | 异步IO读取数据包 | RecvEx |
| int Send(WinDivertPacket, WinDivertAddress) | 同步阻塞发送数据包 | SendEx |
| int Send(WinDivertPacket, WinDivertAddress, CancellationToken) | 同步阻塞发送数据包 | SendEx |
| `ValueTask<int>` SendAsync(WinDivertPacket, WinDivertAddress) | 异步IO发送数据包 | SendEx |
| `ValueTask<int>` 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<Func<IFilter, bool>>) | 使用and逻辑创建新的fitler ||
| Filter And(Filter) | 使用and逻辑创建新的fitler ||
| Filter Or(Expression<Func<IFilter, bool>>) | 使用or逻辑创建新的fitler ||
| Filter Or(Filter) | 使用or逻辑创建新的fitler ||

#### 3.3 WinDivertPacket
| Api | 描述 | 原Api |
| --------------------------------------------------- | --------------------------------------------------------------- | ---------------------------- |
| int Capacity { get; } | 获取缓冲区容量 ||
| int Length { get; set;} | 获取或设置有效数据的长度 ||
| Span<byte> Span { get; } | 获取有效数据视图 ||
| void Clear() | 将有效数据清0 ||
| `Span<byte>` 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);
}

/// <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;
}
```

0 comments on commit a38115c

Please sign in to comment.