fuzzing-obstacles
チェックサムやグローバル状態などの障壁によってファジングの進行が阻まれる場合に、コードにパッチを当てて障害を克服するためのテクニック集。ファザーが先に進めなくなっている状況で活用してください。
description の原文を見る
> Techniques for patching code to overcome fuzzing obstacles. Use when checksums, global state, or other barriers block fuzzer progress.
SKILL.md 本文
ファジング障害物の克服
コードベースには、効果的なカバレッジを防ぐアンチファジングパターンが含まれていることがよくあります。チェックサム、グローバル状態(時間シードの PRNG など)、および検証チェックはファザーが深いコードパスを探索することをブロックできます。このテクニックでは、ファジング中に、本番動作を保持しながら、これらの障害物をバイパスするために、テスト対象システム(SUT)にパッチを適用する方法を示します。
概要
多くの実世界のプログラムはファジングを念頭に置いて設計されていません。それらは以下のことができます:
- 入力を処理する前にチェックサムまたは暗号ハッシュを検証する
- グローバル状態(システム時刻、環境変数など)に依存する
- 非決定的乱数生成器を使用する
- ファザーが有効な入力を生成することを困難にする複雑な検証を実行する
これらのパターンはファジングを難しくします。なぜなら:
- チェックサム: ファザーは正しいハッシュ値を推測する必要があります(天文学的にありえません)
- グローバル状態: 同じ入力が実行全体で異なる動作を生成します(決定性を破ります)
- 複雑な検証: ファザーは深いコード探索の代わりに検証失敗をヒットするために労力を費やします
解決策は条件付きコンパイルです:本番コードを変更しないまま、ファジングビルド中にコード動作を変更します。
キー概念
| 概念 | 説明 |
|---|---|
| SUT パッチング | テスト対象システムをファジング対応にするための変更 |
| 条件付きコンパイル | コンパイル時フラグに基づいて動作が異なるコード |
| ファジングビルドモード | ファジング固有のパッチを有効にする特別なビルド設定 |
| 偽陽性 | ファジング中に見つかるが本番環境では発生できないクラッシュ |
| 決定性 | 同じ入力が常に同じ動作を生成します(ファジングに重要) |
適用タイミング
このテクニックを適用する場合:
- ファザーがチェックサムまたはハッシュ検証で詰まっている
- カバレッジレポートが検証の背後にある大きなコードブロックが到達不可能であることを示す
- コードが時間ベースのシードまたは他の非決定的グローバル状態を使用する
- 複雑な検証により有効な入力を生成することがほぼ不可能になる
- ファザーが繰り返し同じ検証失敗にヒットするのが見える
このテクニックをスキップする場合:
- 障害物は優れたシードコーパスまたは辞書で克服できます
- 検証が十分に単純でファザーが学習できます(例:マジックバイト)
- 検証を処理するために文法ベースまたは構造認識ファジングを行っている
- チェックをスキップすると偽陽性が多すぎる
- コードは既にファジング対応です
クイックリファレンス
| タスク | C/C++ | Rust |
|---|---|---|
| ファジングビルドの確認 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | cfg!(fuzzing) |
| ファジング中チェックをスキップ | #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION return -1; #endif | if !cfg!(fuzzing) { return Err(...) } |
| 一般的な障害物 | チェックサム、PRNG、時間ベースロジック | チェックサム、PRNG、時間ベースロジック |
| サポートされるファザー | libFuzzer、AFL++、LibAFL、honggfuzz | cargo-fuzz、libFuzzer |
ステップバイステップ
ステップ 1: 障害物を特定する
ファザーを実行し、カバレッジを分析して到達不可能なコードを見つけます。一般的なパターン:
- チェックサム/ハッシュ検証がより深い処理の前に行われていないかを見つける
rand()、time()、またはシステムシードを持つsrand()への呼び出しを確認する- ほとんどの入力を拒否する検証関数を探す
- 実行全体で異なるグローバル状態の初期化を特定する
ヘルプツール:
- カバレッジレポート(カバレッジ分析テクニックを参照)
-fprofile-instr-generateによるプロファイリング- エントリポイントの手動コード検査
ステップ 2: 条件付きコンパイルを追加する
障害物を変更してファジングビルド中にバイパスします。
C/C++ の例:
// 前:難しい障害物
if (checksum != expected_hash) {
return -1; // ファザーはここを通過しません
}
// 後:条件付きバイパス
if (checksum != expected_hash) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return -1; // 本番環境でのみ実装
#endif
}
// ファザーはこのチェック後のコードを探索できるようになります
Rust の例:
// 前:難しい障害物
if checksum != expected_hash {
return Err(MyError::Hash); // ファザーはここを通過しません
}
// 後:条件付きバイパス
if checksum != expected_hash {
if !cfg!(fuzzing) {
return Err(MyError::Hash); // 本番環境でのみ実装
}
}
// ファザーはこのチェック後のコードを探索できるようになります
ステップ 3: カバレッジ改善を検証する
パッチ適用後:
- ファジング計測でリビルドします
- ファザーを短時間実行します
- パッチなしバージョンとカバレッジを比較します
- 新しいコードパスが探索されていることを確認します
ステップ 4: 偽陽性リスクを評価する
チェックをスキップすることで不可能なプログラム状態が導入されるかどうかを検討します:
- チェック後のコードは検証済みプロパティを想定していますか?
- 検証をスキップすると本番環境では発生できないクラッシュが発生する可能性がありますか?
- 暗黙の状態依存性がありますか?
偽陽性が可能性が高い場合は、より的を絞ったパッチを検討します(以下の一般的なパターンを参照)。
一般的なパターン
パターン:チェックサム検証をバイパスする
ユースケース: ハッシュ/チェックサムがすべてのファザー進行をブロックする
前:
uint32_t computed = hash_function(data, size);
if (computed != expected_checksum) {
return ERROR_INVALID_HASH;
}
process_data(data, size);
後:
uint32_t computed = hash_function(data, size);
if (computed != expected_checksum) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return ERROR_INVALID_HASH;
#endif
}
process_data(data, size);
偽陽性リスク: 低 - データ処理がチェックサムの正確性に依存しない場合
パターン:決定的 PRNG シーディング
ユースケース: 非決定的ランダム状態は再現性を防ぎます
前:
void initialize() {
srand(time(NULL)); // 実行ごとに異なるシード
}
後:
void initialize() {
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
srand(12345); // ファジング用の固定シード
#else
srand(time(NULL));
#endif
}
偽陽性リスク: 低 - ファザーは固定シードですべてのコードパスを探索できます
パターン:慎重な検証スキップ
ユースケース: 検証はスキップする必要がありますが、下流コードは仮定を持っています
前(危険):
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (!validate_config(&config)) {
return -1; // config.x != 0 を保証
}
#endif
int32_t result = 100 / config.x; // クラッシュ:ファジングでゼロ除算!
後(安全):
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (!validate_config(&config)) {
return -1;
}
#else
// ファジング中は、検証失敗時に安全なデフォルトを使用
if (!validate_config(&config)) {
config.x = 1; // ゼロ除算を防ぐ
config.y = 1;
}
#endif
int32_t result = 100 / config.x; // 両方のビルドで安全
偽陽性リスク: 軽減 - スキップの代わりに安全なデフォルトを提供します
パターン:複雑フォーマット検証をバイパスする
ユースケース: 複数ステップの検証により有効な入力生成がほぼ不可能になります
Rust の例:
// 前:複数の検証ステージ
pub fn parse_message(data: &[u8]) -> Result<Message, Error> {
validate_magic_bytes(data)?;
validate_structure(data)?;
validate_checksums(data)?;
validate_crypto_signature(data)?;
deserialize_message(data)
}
// 後:ファジング中は高価な検証をスキップ
pub fn parse_message(data: &[u8]) -> Result<Message, Error> {
validate_magic_bytes(data)?; // 安いチェックは保持
if !cfg!(fuzzing) {
validate_structure(data)?;
validate_checksums(data)?;
validate_crypto_signature(data)?;
}
deserialize_message(data)
}
偽陽性リスク: 中程度 - 逆シリアル化は不正なデータを適切に処理する必要があります
高度な使用法
ヒントとコツ
| ヒント | 理由 |
|---|---|
| 安い検証を保持 | マジックバイトとサイズチェックは多くのコストなくファザーをガイド |
| PRNG には固定シードを使用 | コストなくすべてのコードパスを探索しながら動作を決定的にします |
| 段階的にパッチを適用 | 一度に 1 つの障害物をスキップしてカバレッジ影響を測定 |
| 防御的なデフォルトを追加 | 検証をスキップするときは安全なフォールバック値を提供 |
| すべてのパッチをドキュメント化 | 将来のメンテナーはファジングと本番環境の違いを理解する必要があります |
実世界の例
OpenSSL: FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION を使用して暗号化アルゴリズム動作を変更します。例えば、crypto/cmp/cmp_vfy.c では、特定の署名チェックはファジング中に緩和され、証明書検証ロジックの深い探索を許可します。
ogg crate(Rust): cfg!(fuzzing) を使用して、ファジング中にチェックサム検証をスキップします。これにより、ファザーは正しいチェックサムを推測するために労力を費やすことなくオーディオ処理コードを探索できます。
パッチ効果の測定
パッチを適用した後、改善を定量化します:
- ライン カバレッジ:
llvm-covまたはcargo-covを使用して新しく到達可能なラインを表示します - 基本ブロック カバレッジ: ラインカバレッジより細粒度
- 関数カバレッジ: 現在到達可能な関数はいくつ増えましたか?
- コーパスサイズ: ファザーはより多くの多様な入力を生成していますか?
効果的なパッチは通常、カバレッジを 10~50% 以上増やします。
他のテクニックとの組み合わせ
障害物パッチングは以下と組み合わせうまく機能します:
- コーパスシーディング: 初期解析を通過する有効な入力を提供
- 辞書: ファザーがマジックバイトと一般的な値を学ぶのに役立つ
- 構造認識ファジング: 複雑なフォーマット用に protobuf または文法定義を使用
- ハーネス改善: より良いハーネスは完全に障害物を回避できる場合があります
アンチパターン
| アンチパターン | 問題 | 正しいアプローチ |
|---|---|---|
| すべての検証を大掛かりにスキップ | 偽陽性を作成し、不安定なファジング | カバレッジをブロックする特定の障害物のみをスキップ |
| リスク評価なし | 偽陽性は時間を浪費し、実際のバグを隠す | 仮定について下流コードを分析 |
| パッチをドキュメント化するのを忘れ | 将来のメンテナーは違いを理解しません | パッチが安全な理由を説明するコメントを追加 |
| 測定なしにパッチを適用 | 役に立ったかどうか不明 | 前後のカバレッジを比較 |
| 過度なパッチング | ファジングビルドが本番環境から大きく異なる | ビルド間の差異を最小化 |
ツール固有のガイダンス
libFuzzer
libFuzzer はコンパイル中に自動的に FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION を定義します。
# C++ コンパイル
clang++ -g -fsanitize=fuzzer,address -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION \
harness.cc target.cc -o fuzzer
# マクロは通常 -fsanitize=fuzzer によって自動的に定義されます
clang++ -g -fsanitize=fuzzer,address harness.cc target.cc -o fuzzer
統合のヒント:
- マクロは自動的に定義されます。手動定義は通常不要です
#ifdefを使用してマクロをチェック- サニタイザーと組み合わせて新しく到達可能なコードのバグを検出
AFL++
AFL++ は、コンパイララッパーを使用するときも FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION を定義します。
# AFL++ ラッパーでのコンパイル
afl-clang-fast++ -g -fsanitize=address target.cc harness.cc -o fuzzer
# マクロは afl-clang-fast によって自動的に定義されます
統合のヒント:
- 自動マクロ定義には
afl-clang-fastまたはafl-clang-ltoを使用 - 永続的モードハーネスは障害物パッチングから最も利益を得ます
- 追加の入力からの状態変換には
AFL_LLVM_LAF_ALLを使用検討
honggfuzz
honggfuzz もターゲットを構築するときマクロをサポート
# コンパイル
hfuzz-clang++ -g -fsanitize=address target.cc harness.cc -o fuzzer
統合のヒント:
hfuzz-clangまたはhfuzz-clang++ラッパーを使用- マクロは条件付きコンパイルで利用可能
- honggfuzz のフィードバック駆動型ファジングと組み合わせ
cargo-fuzz(Rust)
cargo-fuzz はビルド中に自動的に fuzzing cfg オプションを設定します。
# ファズターゲットをビルド(cfg!(fuzzing) は自動的に設定)
cargo fuzz build fuzz_target_name
# ファズターゲットを実行
cargo fuzz run fuzz_target_name
統合のヒント:
- 本番ビルドの実行時チェックには
cfg!(fuzzing)を使用 - コンパイル時条件付きコンパイルには
#[cfg(fuzzing)]を使用 - fuzzing cfg は
cargo fuzzビルド中のみ設定され、通常のcargo buildでは設定されません - テストには
RUSTFLAGS="--cfg fuzzing"で手動で有効化できます
LibAFL
LibAFL は C/C++ で書かれたターゲットの C/C++ マクロをサポート
# コンパイル
clang++ -g -fsanitize=address -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION \
target.cc -c -o target.o
統合のヒント:
- マクロを手動で定義するか、コンパイラフラグを使用
- libFuzzer と同じに機能します
- カスタム LibAFL ベースのファザー構築時に便利
トラブルシューティング
| 問題 | 原因 | ソリューション |
|---|---|---|
| パッチ後カバレッジが改善しない | 間違った障害物が特定された | 実際のボトルネックを見つけるために実行をプロファイル |
| 偽陽性クラッシュが多い | 下流コードに仮定がある | 防御的なデフォルトまたは部分検証を追加 |
| コードが異なるコンパイル方法 | マクロがすべてのビルド設定で定義されていない | すべてのソースファイルと依存関係でマクロを確認 |
| ファザーはパッチ済みコードのバグを検出 | パッチが無効な状態を導入した | パッチを状態不変式で確認。より安全なアプローチを検討 |
| 本番バグが再現できない | ビルド差異が大きすぎる | パッチを最小化。状態重要なチェックは検証を保持 |
関連スキル
このテクニックを使用するツール
| スキル | 適用方法 |
|---|---|
| libfuzzer | FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION を自動定義 |
| aflpp | コンパイララッパー経由でマクロをサポート |
| honggfuzz | 条件付きコンパイル用マクロを使用 |
| cargo-fuzz | Rust 条件付きコンパイル用に cfg!(fuzzing) を設定 |
関連テクニック
| スキル | 関係性 |
|---|---|
| fuzz-harness-writing | より良いハーネスは障害物を回避する可能性があります。パッチングはより深い探索を有効にします |
| coverage-analysis | カバレッジを使用して障害物を特定し、パッチ効果を測定 |
| corpus-seeding | シードコーパスはパッチなしで障害物を克服するのに役立つ |
| dictionary-generation | 辞書はマジックバイトを助けますが、チェックサムや複雑な検証は助けません |
リソース
キー外部リソース
OpenSSL ファジングドキュメント
OpenSSL のファジングインフラストラクチャは FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION の大規模使用を示します。プロジェクトはこのマクロを使用して、暗号化検証、証明書解析、およびその他のセキュリティ重要コードパスを変更し、本番環境の正確性を維持しながらより深いファジングを有効にします。
LibFuzzer フラグドキュメント libFuzzer 用の公式 LLVM ドキュメント。ファザーがコンパイラマクロを定義する方法および効果的に使用する方法を含みます。サニタイザーとカバレッジ計測の統合をカバー。
Rust cfg 属性リファレンス
Rust 条件付きコンパイルの完全なリファレンス。cfg!(fuzzing) および cfg!(test) を含みます。コンパイル時と実行時条件付きコンパイルとベストプラクティスについて説明します。
ライセンス: CC-BY-SA-4.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- trailofbits
- リポジトリ
- trailofbits/skills
- ライセンス
- CC-BY-SA-4.0
- 最終更新
- 不明
Source: https://github.com/trailofbits/skills / ライセンス: CC-BY-SA-4.0
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。