
أداة لحل مرشحات BPF وإنشاء الحزم بناءً عليها.
مجموعة أدوات بلغة بايثون لهندسة عكسية لبايت كود Berkeley Packet Filter (BPF). بالنظر إلى تعليمات BPF الأولية — النوع الذي قد تستخرجه من عينة برمجية خبيثة، أو مرشح التقاط حزم، أو جهاز شبكة — يقوم filterforge بفك تجميعها إلى شكل قابل للقراءة البشرية، ويستخدم Z3 لحل مجموعة قيود الحزمة التي تحقق مسار قبول، ثم يستخدم Scapy لصياغة حزمة شبكة ملموسة قادرة على اجتياز الفلتر.
باختصار: أعطه برنامج BPF وسيعيد لك حزمة مكتملة التكوين (إيثرنت، IPv4/IPv6، TCP/UDP/SCTP وما بعدها) يقبلها الفلتر — جاهزة للفحص، أو الحفظ في ملف PCAP، أو الإرسال على الشبكة.
يُوصى بتثبيت uv لتشغيل هذه الأداة.
يُرجى الرجوع إلى الأمثلة أدناه لاستخدام الأداة، ومن المحتمل إضافة المزيد من الميزات بمرور الوقت.
للحصول على نتائج سريعة لـ BPF معين، من الأسهل استخدام سطر الأوامر. نظرًا لكيفية إعادة بعض أدوات الهندسة العكسية للبيانات المنسوخة، يمكنك إما إعطاء سلسلة سداسية عشرية خام، أو مصفوفة من القيم السداسية العشرية، باستخدام العلم -d لعرض تفكيك BPF المعطى ببساطة؛
# hex-string
uv run ff -d -b "280000000c00000015002900060800001500000bdd860000300000001400000015000027110000002800000038000000150024003500000015002300e91400001500220043000000150021009c690000150020006c07000015001f0089000000280000003600000015001d0fe91400001500001d0008000030000000170000001500000f11000000280000001400000045001900ff1f0000b10000000e0000004800000010000000150015003500000015001400e91400001500130043000000150012009c690000150011006c0700001500100089000000480000000e00000015000e00e914000015000d009c69000015000c006c07000015000b0c890000001500000b06000000280000001400000045000900ff1f0000b10000000e000000500000001a000000740000000400000024000000040000000c000000000000000700000000000000400000000e000000150000012054454706000000000004000600000000000000"
# array of hex values
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)؛
uv run ff -c -b 300000000000000054000000f00000001500001e40000000300000000000000054000000f00000001500000660000000300000000600000015000900110000003000000006000000150000022c00000030000000280000001500050011000000300000000000000054000000f0000000150000124000000030000000090000001500001011000000280000000600000045000e00ff1f000000000000080000000200000000000000b10000000000000060000000000000000c0000000000000007000000000000004800000000000000020000000100000000000000557200000200000002000000610000000200000060000000010000001c000000000000001500c20000000000300000000000000054000000f00000001500002d40000000300000000000000054000000f00000001500002a4000000030000000090000001500002801000000280000000600000045002600ff1f000000000000080000000200000002000000b10000000000000060000000020000000c0000000000000007000000000000004800000000000000020000000300000000000000557200000200000004000000610000000400000060000000030000001c000000000000001500001800000000300000000000000054000000f00000001500001540000000300000000000000054000000f0000000150000124000000030000000090000001500001001000000280000000600000045000e00ff1f000000000000000000000200000004000000b10000000000000060000000040000000c0000000000000007000000000000005000000000000000020000000500000000000000080000000200000006000000610000000600000060000000050000001c000000000000001500920000000000300000000000000054000000f00000001500004340000000300000000000000054000000f00000001500004040000000300000000000000054000000f00000001500000660000000300000000600000015000900060000003000000006000000150000022c00000030000000280000001500050006000000300000000000000054000000f0000000150000344000000030000000090000001500003206000000280000000600000045003000ff1f0000300000000000000054000000f00000001500000660000000300000000600000015000900060000003000000006000000150000022c00000030000000280000001500050006000000300000000000000054000000f0000000150000244000000030000000090000001500002206000000280000000600000045002000ff1f0000000000000c0000000200000006000000b10000000000000060000000060000000c0000000000000007000000000000005000000000000000020000000700000000000000f00000000200000008000000610000000800000060000000070000005c00000000000000020000000800000000000000020000000200000009000000610000000900000060000000080000007c000000000000000200000009000000b10000000000000060000000090000000c0000000000000007000000000000004800000000000000020000000a0000000000000093520000020000000b000000610000000b000000600000000a0000001c0000000000000015004c0000000000300000000000000054000000f00000001500004a40000000300000000000000054000000f00000001500004740000000300000000000000054000000f00000001500000660000000300000000600000015000900060000003000000006000000150000022c00000030000000280000001500050006000000300000000000000054000000f00000001500003b4000000030000000090000001500003906000000280000000600000045003700ff1f0000300000000000000054000000f00000001500000660000000300000000600000015000900060000003000000006000000150000022c00000030000000280000001500050006000000300000000000000054000000f00000001500002b4000000030000000090000001500002906000000280000000600000045002700ff1f0000000000000c000000020000000b000000b100000000000000600000000b0000000c0000000000000007000000000000005000000000000000020000000c00000000000000f0000000020000000d000000610000000d000000600000000c0000005c00000000000000020000000d0000000000000002000000020000000e000000610000000e000000600000000d0000007c00000000000000020000000e000000000000001a000000020000000f000000610000000f000000600000000e0000000c00000000000000020000000f000000b100000000000000600000000f0000000c0000000000000007000000000000004000000000000000020000000000000000000000393939390200000001000000610000000100000060000000000000001c00000000000000150000010000000006000000ffff00000600000000000000 -l raw
2026-02-09 12:06:46,064 - INFO - Loaded 229 instructions
2026-02-09 12:06:46,717 - DEBUG - Found 50 accepting path(s)
2026-02-09 12:06:46,725 - DEBUG - Path 1 unsatisfiable
2026-02-09 12:06:46,730 - DEBUG - Path 2 is satisfiable
2026-02-09 12:06:46,731 - INFO - Hexdump:
0000 45 00 00 00 00 00 00 00 00 11 00 00 00 00 00 00 E...............
0010 00 00 00 00 00 00 00 00 00 00 00 00 72 55 00 00 ............rU..
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0030 00 00 00 00 00 00 00 00 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:46,731 - INFO - Packet summary:
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 0
id = 0
flags =
frag = 0
ttl = 0
proto = udp
chksum = 0x0
src = 0.0.0.0
dst = 0.0.0.0
\options \
###[ UDP ]###
sport = 0
dport = 0
len = 0
chksum = 0x0
###[ Raw ]###
load = b'rU\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\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'
لغرض استخدام الأداة بطريقة أكثر قابلية للبرمجة، أنشأنا واجهة API سهلة الاستخدام نسبيًا يمكن تطبيقها بعدة طرق مختلفة، يُرجى الرجوع إلى بعض الأمثلة أدناه للإلهام:
from ff import BPFSolver
# Create a solver with BPF bytecode
solver = BPFSolver("280000000c00000015001b00...")
# Solve and craft a packet
result = solver.solve()
if result:
result.hexdump()
result.show()
print(result.summary())
from ff import BPFSolver
solver = BPFSolver("280000000c00000015001b00...")
# Get human-readable disassembly
print(solver.disassemble())
# Access parsed instructions
print(f"Instruction count: {solver.instruction_count}")
for insn in solver.instructions:
print(insn)
from ff import BPFSolver, PacketOverrides
solver = BPFSolver("280000000c00000015001b00...")
# Override specific packet fields
overrides = PacketOverrides(
src_ip="192.168.1.100",
dst_ip="10.0.0.1",
src_port=12345,
dst_port=80,
src_mac="00:11:22:33:44:55",
dst_mac="aa:bb:cc:dd:ee:ff"
)
result = solver.solve(overrides=overrides)
if result:
result.show()
from ff import BPFSolver
solver = BPFSolver("280000000c00000015001b00...")
result = solver.solve()
if result:
# Save to PCAP file
solver.to_pcap("output.pcap")
# Or save a specific result
solver.to_pcap("output.pcap", result=result)
from ff import BPFSolver
# Use link_type="raw" for DLT_RAW (no Ethernet header)
solver = BPFSolver("280000000c00000015001b00...", link_type="raw")
result = solver.solve()
from ff import BPFSolver
solver = BPFSolver("280000000c00000015001b00...")
# Find all paths that lead to packet acceptance
paths = solver.find_paths()
print(f"Found {len(paths)} accepting path(s)")
for i, path in enumerate(paths):
print(f"Path {i+1}: {path}")
from ff import BPFSolver
solver = BPFSolver("280000000c00000015001b00...")
result = solver.solve()
if result:
# Raw bytes
raw_bytes = result.raw
# Scapy packet object for advanced manipulation
scapy_pkt = result.scapy_packet
scapy_pkt[0].dst = "192.168.1.1" # Modify directly
# Execution path taken
print(f"Path: {result.path}")
print(f"Link type: {result.link_type}")
from ff import BPFSolver
solver = BPFSolver("280000000c00000015001b00...")
result = solver.solve()
if result:
# Send packet (requires root/sudo)
solver.send(iface="eth0", count=1)
# Or send a specific result
solver.send(result=result, iface="eth0")
أحيانًا لا يحتوي BPF على تعليمتي ret اللتين نتوقعهما (واحدة لقبول حزمة، والأخرى لإسقاط حزمة). خذ على سبيل المثال هذا المثال من Symbiote (dcfbd5054bb6ea61b8f5a352a482e0cf7e8c5545bd88915d3e67f7ba01c2b3d4):
uv run ff -d -b "280000000c0000001500000fdd8600003000000014000000150002008400000015000100060000001500002611000000280000003600000015002300fad5000015002200f6e500001500210012e90000150020005fd6000015001f0083e2000015001e0042fb000015001d006db2000015001c00fbf60000280000003800000015001a13fad500001500001a000800003000000017000000150002008400000015000100060000001500001611000000280000001400000045001400ff1f0000b10000000e000000480000000e00000015001000fad5000015000f00f6e5000015000e0012e9000015000d005fd6000015000c0083e2000015000b0042fb000015000a006db2000015000900fbf60000480000001000000015000700fad5000015000600f6e500001500050012e90000150004005fd600001500030083e200001500020042fb0000150001006db2000015000001fbf600000600000000000000"
2026-02-09 12:08:32,009 - INFO - Loaded 44 instructions
(000) ldh [12]
(001) jeq #0x86dd, jt 2, jf 17
(002) ldb [20]
<SNIPPED>
(026) jeq #0xd5fa, jt 43, jf 27
(027) jeq #0xe5f6, jt 43, jf 28
(028) jeq #0xe912, jt 43, jf 29
(029) jeq #0xd65f, jt 43, jf 30
(030) jeq #0xe283, jt 43, jf 31
(031) jeq #0xfb42, jt 43, jf 32
(032) jeq #0xb26d, jt 43, jf 33
(033) jeq #0xf6fb, jt 43, jf 34
(034) ldh [x + 16]
(035) jeq #0xd5fa, jt 43, jf 36
(036) jeq #0xe5f6, jt 43, jf 37
(037) jeq #0xe912, jt 43, jf 38
(038) jeq #0xd65f, jt 43, jf 39
(039) jeq #0xe283, jt 43, jf 40
(040) jeq #0xfb42, jt 43, jf 41
(041) jeq #0xb26d, jt 43, jf 42
(042) jeq #0xf6fb, jt 43, jf 44
(043) ret #0 (DROP)
يمكننا أن نرى هنا أنه لدينا تعليمة ret واحدة فقط من المتوقع، مما يتسبب في فشل محلل Z3 الخاص بنا؛
2025-12-16 12:09:31,123 - ERROR - No satisfiable paths found, failed to craft packet
يمكننا إضافة تعليمتنا الخاصة هنا بقفزة ناجحة من خلال النظر إلى ما يفعله BPF. في المقتطف أعلاه يمكننا رؤية الكثير من الشروط المتعلقة بأرقام المنافذ، كل منها إما يتحقق من الشرط التالي أو يقفز إلى التعليمات 43، التي اعتبرناها DROP بسبب طريقة تفكيكنا لـ BPF. في هذه الحالة ليست DROP بالضبط، بل هي تعليمة إرجاع صالحة. هذا يعني أنه إذا أضفنا تعليمة ret ناجحة وهمية خاصة بنا، فسيتم تحليلها بشكل صحيح، على سبيل المثال؛
ret الحالية: 06 00 00 00 00 00 00 0006 00 00 00 ff ff 00 00 06 00 00 00 00 00 00 00ينتج عن ذلك:
uv run ff -d -b "280000000c0000001500000fdd8600003000000014000000150002008400000015000100060000001500002611000000280000003600000015002300fad5000015002200f6e500001500210012e90000150020005fd6000015001f0083e2000015001e0042fb000015001d006db2000015001c00fbf60000280000003800000015001a13fad500001500001a000800003000000017000000150002008400000015000100060000001500001611000000280000001400000045001400ff1f0000b10000000e000000480000000e00000015001000fad5000015000f00f6e5000015000e0012e9000015000d005fd6000015000c0083e2000015000b0042fb000015000a006db2000015000900fbf60000480000001000000015000700fad5000015000600f6e500001500050012e90000150004005fd600001500030083e200001500020042fb0000150001006db2000015000001fbf6000006000000ffff00000600000000000000"
2025-12-16 12:12:04,346 - INFO - Loaded 45 instructions
(000) ldh [12]
(001) jeq #0x86dd, jt 2, jf 17
(002) ldb [20]
<SNIPPED>
(026) jeq #0xd5fa, jt 43, jf 27
(027) jeq #0xe5f6, jt 43, jf 28
(028) jeq #0xe912, jt 43, jf 29
(029) jeq #0xd65f, jt 43, jf 30
(030) jeq #0xe283, jt 43, jf 31
(031) jeq #0xfb42, jt 43, jf 32
(032) jeq #0xb26d, jt 43, jf 33
(033) jeq #0xf6fb, jt 43, jf 34
(034) ldh [x + 16]
(035) jeq #0xd5fa, jt 43, jf 36
(036) jeq #0xe5f6, jt 43, jf 37
(037) jeq #0xe912, jt 43, jf 38
(038) jeq #0xd65f, jt 43, jf 39
(039) jeq #0xe283, jt 43, jf 40
(040) jeq #0xfb42, jt 43, jf 41
(041) jeq #0xb26d, jt 43, jf 42
(042) jeq #0xf6fb, jt 43, jf 44
(043) ret #0xffff (ACCEPT)
(044) ret #0 (DROP)
إذا قمنا بتشغيل -c الآن لصياغة حزمة، فسيتم الترحيب بنا بحزمة السحر الجديدة:
uv run ff -c -b "280000000c0000001500000fdd8600003000000014000000150002008400000015000100060000001500002611000000280000003600000015002300fad5000015002200f6e500001500210012e90000150020005fd6000015001f0083e2000015001e0042fb000015001d006db2000015001c00fbf60000280000003800000015001a13fad500001500001a000800003000000017000000150002008400000015000100060000001500001611000000280000001400000045001400ff1f0000b10000000e000000480000000e00000015001000fad5000015000f00f6e5000015000e0012e9000015000d005fd6000015000c0083e2000015000b0042fb000015000a006db2000015000900fbf60000480000001000000015000700fad5000015000600f6e500001500050012e90000150004005fd600001500030083e200001500020042fb0000150001006db2000015000001fbf6000006000000ffff00000600000000000000"
2026-02-09 12:07:47,247 - INFO - Loaded 45 instructions
2026-02-09 12:07:47,247 - DEBUG - Found 50 accepting path(s)
2026-02-09 12:07:47,251 - DEBUG - Path 1 is satisfiable
2026-02-09 12:07:47,251 - 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:07:47,252 - 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'
لتشغيل الاختبارات محليًا:
uv run --extra dev pytest tests/ -v