Python 工具包,用于逆向工程 Berkeley Packet Filter (BPF) 字节码。给定原始的 BPF 指令——这些指令可能来自恶意软件样本、数据包捕获过滤器或网络设备——filterforge 将其反汇编为人类可读的形式,使用 Z3 求解满足接受路径的数据包约束,然后利用 Scapy 构建一个具体的网络数据包,使其能够通过该过滤器。
简而言之:向其提供一个 BPF 程序,它将返回一个完整的数据包(Ethernet、IPv4/IPv6、TCP/UDP/SCTP 等),该数据包可被过滤器接受——随时可以检查、保存为 PCAP 或在网络上发送。
建议安装 uv 来运行此工具。
请参考下面的示例来了解该工具的用法,随着时间的推移可能会增加更多功能。
要快速获取给定 BPF 的结果,最简单的方法是使用命令行。由于某些逆向工程工具返回数据的方式不同,您可以提供原始十六进制字符串或十六进制值数组,使用 -d 标志仅显示给定 BPF 的反汇编:
# 十六进制字符串
uv run ff -d -b "280000000c00000015002900060800001500000bdd860000300000001400000015000027110000002800000038000000150024003500000015002300e91400001500220043000000150021009c690000150020006c07000015001f0089000000280000003600000015001d0fe91400001500001d0008000030000000170000001500000f11000000280000001400000045001900ff1f0000b10000000e0000004800000010000000150015003500000015001400e91400001500130043000000150012009c690000150011006c0700001500100089000000480000000e00000015000e00e914000015000d009c69000015000c006c07000015000b0c890000001500000b06000000280000001400000045000900ff1f0000b10000000e000000500000001a000000740000000400000024000000040000000c000000000000000700000000000000400000000e000000150000012054454706000000000004000600000000000000"
# 十六进制值数组
uv run ff -d -b "[0x28,0x0,0x0,0xc,0x15,0x0,0x1b,0x800,0x30,0x0,0x0,0x17,0x15,0x0,0x5,0x11,0x28,0x0,0x0,0x14,0x45,0x17,0x0,0x1fff,0xb1,0x0,0x0,0xe,0x48,0x0,0x0,0x16,0x15,0x13,0x14,0x7255,0x15,0x0,0x7,0x1,0x28,0x0,0x0,0x14,0x45,0x11,0x0,0x1fff,0xb1,0x0,0x0,0xe,0x48,0x0,0x0,0x16,0x15,0x0,0xe,0x7255,0x50,0x0,0x0,0xe,0x15,0xb,0xc,0x8,0x15,0x0,0xb,0x6,0x28,0x0,0x0,0x14,0x45,0x9,0x0,0x1fff,0xb1,0x0,0x0,0xe,0x50,0x0,0x0,0x1a,0x54,0x0,0x0,0xf0,0x74,0x0,0x0,0x2,0xc,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x48,0x0,0x0,0xe,0x15,0x0,0x1,0x5293,0x6,0x0,0x0,0xffff,0x6,0x0,0x0,0x0]"
要了解根据给定的 BPF 字节码构建的网络数据包的大致外观,可以使用 -c 标志:
uv run ff -c -b "280000000c0000001500000fdd8600003000000014000000150002008400000015000100060000001500002611000000280000003600000015002300fad5000015002200f6e500001500210012e90000150020005fd6000015001f0083e2000015001e0042fb000015001d006db2000015001c00fbf60000280000003800000015001a13fad500001500001a000800003000000017000000150002008400000015000100060000001500001611000000280000001400000045001400ff1f0000b10000000e000000480000000e00000015001000fad5000015000f00f6e5000015000e0012e9000015000d005fd6000015000c0083e2000015000b0042fb000015000a006db2000015000900fbf60000480000001000000015000700fad5000015000600f6e500001500050012e90000150004005fd600001500030083e200001500020042fb0000150001006db2000015000001fbf6000006000000ffff00000600000000000000"
2026-02-09 12:06:23,342 - INFO - Loaded 45 instructions
2026-02-09 12:06:23,342 - DEBUG - Found 50 accepting path(s)
2026-02-09 12:06:23,346 - DEBUG - Path 1 is satisfiable
2026-02-09 12:06:23,347 - INFO - Hexdump:
0000 00 00 00 00 00 00 00 00 00 00 00 00 86 DD 60 00 ..............`.
0010 00 00 00 00 84 00 00 00 00 00 00 00 00 00 00 00 ................
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0030 00 00 00 00 00 00 D5 FA 00 00 00 00 00 00 00 00 ................
0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2026-02-09 12:06:23,347 - INFO - Packet summary:
###[ Ethernet ]###
dst = 00:00:00:00:00:00
src = 00:00:00:00:00:00
type = IPv6
###[ IPv6 ]###
version = 6
tc = 0
fl = 0
plen = 0
nh = SCTP
hlim = 0
src = ::
dst = ::
###[ SCTP ]###
sport = 54778
dport = 0
tag = 0x0
chksum = 0x0
###[ Raw ]###
load = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
某些 BPF 可能使用原始 IP 层,为此你可以指定链路类型 -l raw(默认为 ethernet):