用于探测 Linux IPv4 校验和卸载漏洞(称为 PwnEscape)的 Go 探针。它附加到你已准备好的 TAP 接口上,检查主机的分片器是否信任由 skb_checksum_help 重写过的 IPv4 头部。
该探针负责数据包注入和捕获。scripts/setup.sh 在 pwnesc 网络命名空间内准备实验接口、sysctl 设置和 nftables 规则。scripts/teardown.sh 负责清理实验环境。
在仍会在读取 ihl 之前完成部分校验和的内核上(此处于 6.18.54 复现;已在 6.18.57 修复):
csum_start=22 的 virtio 校验和头部。随后两个 VID-0 标签被剥离(14+4+4),因此校验和写入落在 IPv4 的版本/IHL 字节上。0x45 变为 0x4f。分片器使用 60 字节的头部。-head 8 的情况下,线性头部为 28 字节,因此 60 字节的头部拷贝会越过 skb_headlen 读取 32 字节,进入输出分片的 IPv4 选项区域。这验证了 PWN.AI 的 PwnEscape 文章 中描述的信息泄露原语。在启用 CONFIG_INIT_ON_ALLOC_DEFAULT_ON 时,新分配的 slab 尾部空间在被拷贝的字节中可能显示为零。
ihl 之前完成部分校验和ip、nft、sysctlnf_conntrack 和 nf_defrag_ipv4/dev/net/tun在主机上的仓库目录中执行:
go build -o poc .
sudo ./scripts/setup.sh
sudo ip netns exec pwnesc ./poc
探针以 IFF_TAP|IFF_NO_PI|IFF_VNET_HDR 打开 pwntap,并在 pwnv1 上捕获输出。请将 pwntap 专用于该探针。nftables 的 ct 规则会启用 conntrack 重组,而 pwnv0 使用 MTU 200,以便在输出时再次对重组后的数据报进行分片。
头部检查成功时会打印 verify: first byte 0x4f ihl=15。随后探针会报告输出分片、它们的 IPv4 选项,以及越过线性头部拷贝的字节。
-head(默认 8):偏移 0 分片的载荷字节数;取值为 8 到 40 之间 8 的倍数。预期越过线性头部拷贝的字节数为 40 - head。-rest(默认 400):完成分片的载荷字节数;至少为 16。-spray(默认 0):在偏移 0 分片之前立即分配的相同大小帧的数量。-spray-fill(默认 0xee):用于填充这些帧的字节。-page:使用 page_frag 头部,其尾部可能包含 skb 元数据。默认为 slab 头部。-skip-verify:直接进行分片数据报检查。PWN_TAP 选择 TAP 接口(默认 pwntap)。PWN_CAP 选择捕获接口(默认 pwnv1)。安装脚本使用这些默认名称。
探针结束后,退出 pwnesc 中的所有 shell,并在主机上运行:
sudo ./scripts/teardown.sh
这会删除 pwnesc 及其接口、ip pwn nftables 表以及命名空间本地的 sysctl 设置。