
PXEブートを実行し、過大なICMPエラーを送信することで、ローカルラボ環境でEDK II PxeBcSupportのバッファオーバーフロー(CVE-2026-97631)を再現するヘッドレスQEMU/OVMFハーネスです。
⚠️ ローカルラボ専用。 これらのツールは、自分が管理するファームウェアに対してローカルのQEMU VMを動かすものです。ICMPジェネレーターを、自分が所有していないハードウェアやネットワークに向けないでください。
CVE-2026-97631: TianoCore EDK II(NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c)に16年間存在していたバッファオーバーフロー — PXEネットワークブート中に過大なICMPエラーメッセージが504バイトのEFI_PXE_BASE_CODE_ICMP_ERROR構造体を超えてコピーされ、Secure BootとTPMがロードされる前にリング0のファームウェアメモリを破壊します。PR #13200 / #13302で修正済み。公開報道: Ars Technica。
標準ライブラリのみを使った3つの小さな部品で、ヘッドレスのOVMF/QEMU VMをコールドブートからPXEブート試行まで進めます — DHCPサーバーとICMP攻撃をワイヤ上で実行しながら:
| ファイル | 役割 |
|---|---|
bridge.py | QEMUのワイヤ上で動作する最小限のDHCPサーバー(DISCOVER→OFFER→REQUEST→ACK、TFTP RRQ待機)。その後攻撃を発火: 1200バイトの偽データグラムを引用するICMP type-3 code-1エラーを6回、504バイトの構造体に送り込む。--attackでオン/オフ。 |
router.py | 画面状態ルーター: screendumpのピクセル統計からOVMFの画面を分類し(黒 = UEFI Shell、青 = フロントページ / Boot Manager)、PXEブートオプションが実行されるまでQEMUモニター(sendkey)経由でUIを操作する。 |
drive.py | PPMのハイライトバー検出を備えた、以前のステップバイステップのキーボードドライバー(参照用に保持)。 |
実行形式:
# VM: OVMF pflash, virtio-net on a UDP socket netdev (no mcast flakiness),
# pcap wire tap + CPU-reset logging:
qemu-system-x86_64 -machine q35 -m 512 -display none \
-drive if=pflash,format=raw,readonly=on,file=$FW-code.fd \
-drive if=pflash,format=raw,file=$FW-vars.fd \
-netdev socket,id=n0,udp=127.0.0.1:5555,localaddr=127.0.0.1:6666 \
-device virtio-net-pci,netdev=n0,bootindex=0 \
-object filter-dump,id=f1,netdev=n0,file=dump.pcap \
-monitor unix:qmon.sock,server,nowait -serial none -d cpu_reset -D resets.log &
python3 bridge.py --attack & # DHCP + ICMP overflow trigger
python3 router.py qmon.sock run.log # navigate headlessly to UEFI PXE IPv4
tcpdump -r dump.pcpa # wire truth
grep -c "CPU Reset" resets.log # crash signal (baseline: 2 on clean boot)
PXEブート試行までのすべては再現可能に動作します(画面状態ルーティング、ワイヤタップ、DHCP/攻撃エンジンの準備完了)。私たちがテストしたQEMU同梱のOVMFビルド(IA32とX64、q35とi440fx、TCG)では、ファームウェアはPXEバナーを表示した後、パケットを一切送信しません — DHCP Discoverがファームウェアから出ないため、ICMPトリガーが脆弱なハンドラーに到達することはありません。さらに進めるには、シリアルデバッグ対応のOVMFビルドか実際のラボハードウェアが必要です。このハーネスは意図的にこの正確な境界まで公開されています: 再現性の主張は、実行が止まった場所で止まらなければなりません。
MIT。@slabbdevによる — ブログ記事の補足資料。