EF/CF はスマートコントラクトファジングへの新しいアプローチです。新しい カスタムファザーを使う代わりに、C/C++ コードの既存のファジング基盤を スマートコントラクト向けに再利用します。現在、AFL++ が主にサポートされているファザーですが、 libfuzzer と honggfuzz の非常に基本的なサポートもいくつかあります。
なぜ既存のファジング基盤を使うのか?
途中で遭遇する問題は何でしょうか?
./src/ethmutator/./src/evm2cpp/このリポジトリは EF/CF プロジェクトの主要なエントリポイントです。関連するすべての
コードが ./src/ 内のサブプロジェクトとして含まれており、インストール用の便利なスクリプト、
ファジングキャンペーンを開始するためのスクリプト、およびファザーをテストする(他のツールと比較する)ためのさまざまなデータセットが含まれています。
./src/ - EF/CF のビルドと実行に必要なすべてのソースが含まれています。
再現性のため、すべての直接依存関係は git サブモジュールとして追加されています。./data/ - 評価で使用されたデータセットが含まれています./scripts - 実験の実行、インストールなどのスクリプトが含まれています./docker - コンテナベースのワークフロー用の Dockerfile
./docker/tools/ には、EF/CF を評価したツールの dockerfile が含まれています。
論文で評価したバージョンを dockerfile に固定するよう最善を尽くしました。./EXPERIMENTS.md - 論文の実験を再現するための
ガイドが含まれています。./examples - EF/CF によって生成された出力例が含まれていますEF/CF のアーキテクチャ、実装、および評価結果の概要は、論文で説明しています: arxiv.org preprint
学術研究で EF/CF を参照する場合は、引用に以下の bibtex エントリを使用してください。```bibtex @InProceedings{efcf2023, author = "Michael Rodler and David Paaßen and Wenting Li and Lukas Bernhard and Thorsten Holz and Ghassan Karame and Lucas Davi", title = "EF/CF: High Performance Smart Contract Fuzzing for Exploit Generation", booktitle = "{IEEE} European Symposium on Security and Privacy ({EuroS&P})", publisher = "{IEEE}", year = "2023", }
## クイックスタート
推奨される方法は、EF/CFをインタラクティブなDockerコンテナとして実行することです。
1. シェルでコンテナに入る ```
docker run --rm -it ghcr.io/uni-due-syssec/efcf-framework
または、クローンしたリポジトリからコンテナをビルドする ``` make gitmodules # to fetch the git submodules make container-enter
1. solidityコントラクトをコンパイルしてから、最初のクラッシュ/バグが
発見されるまでファズする: ```
efcfuzz --until-crash --out ./baby_bank_results/ --source ./data/examples/baby_bank.sol
git をお持ちでない場合? tarball/docker リリースを使用する場合は、これは無視してください。
git submodule update --init を実行して、既にクローン済みのリポジトリで最新のサブモジュールコミットを取得してください。
./src/eEVM 内でもこれを実行することを忘れないでください。```
git submodule update --init; cd src/eEVM/; git submodule update --init; cd ../../
*警告:* `git clone --recursive $repo` を実行するか、`--recursive` 引数を `git sumbodule (update|init)` に渡すと、git が AFL++ リポジトリのサブモジュールを再帰的に取得しますが、これらはこのプロジェクトには必要ありません。スペースを節約するため、再帰的なサブモジュールのチェックアウトは避けることをお勧めします。
### コンテナ
コンテナベースのワークフロー向けに、以下の便利な make ターゲットを提供しています。```sh
make container-build # build default efcf container
make container-enter # enter default efcf container in current working dir
クリーンビルドを確実にしたい場合は、以下のコマンドを使用できます。```sh make container-build CLEAN_CHECKOUT=1
あるいは、コンテナは以下のdockerコマンドで構築できます:```sh
docker build \
-f docker/ubuntu.Dockerfile \
-t efcf:latest \
.
Archlinux と Fedora ベースの Dockerfile もあることに注意してください。これらは 同様に動作するはずですが、あまりテストされていません。
Docker イメージを手動で配布する場合(例: ローカルの変更を含める場合)、次を使用します:``` make container-release docker load -i ./efcf*.tar
以下を推奨するDocker起動オプションです:
* `--security-opt seccomp=unconfined` - ファジングパフォーマンスの向上
* `--net=host` - ローカルのEthereumノードに簡単にアクセスするため
* `--tmpfs "/tmp/efcf/":exec,size=6g` - 可能であればEF/CFの一時ファイルをRAMディスクに置く(ディスクの摩耗を軽減)
* `--privileged` - `afl-system-config` または `efcfuzz --configure-system` を実行するため
* `-v` - EF/CFの出力データを永続化するため
### VM / ベアメタル
VM またはベアメタルベースのワークフローの場合:```sh
make system-install # install efcf to current system (requires root or sudo rights)
なお、スクリプトの多くは相対ディレクトリ構造で動作するため、
これは主に依存関係と、自身の
PATH にあると便利ないくつかのツールをインストールします。EF/CF は以下の Linux ディストリビューションでテストしています:
(ディストリビューションはあまり重要ではありません。LLVM 13 と 14 でテストしており、14 が
推奨の選択肢です。LLVM 11 や 12 もまだ動作するかもしれません。しかし、いつものように、新しい方が
良いです。重要なのは、AFL++ のフォークと互換性のある LLVM が存在することです。)
EF/CF は Mac OS 上ではネイティブにテストしていません。おそらく動作しないでしょう (例: Mac OS 上の afl-clang-lto は動作しないようです)。最良の選択肢は docker を利用することです。```sh
make gitmodules
docker pull ubuntu:jammy --platform linux/amd64
docker build -t efcf:latest -f docker/ubuntu.Dockerfile --platform linux/amd64 .
docker run --tmpfs "/tmp/efcf/":exec,size=8g --platform linux/amd64 --rm -it -v $(pwd):$(pwd) -w $(pwd) efcf:latest
docker desktop v4.21.1 と基本的な EF/CF の使用でテストしましたが、問題なく動作します。ただし、以下に注意してください。
* ビルド中にセグメンテーション違反が発生した場合は、Mac OS で docker が使用する VM のメモリ制限を増やしてみてください。
* docker で rosetta を使ったアクセラレーションを有効にしてみてください。うまくいけば少し速くなるはずです。
### 開発環境のセットアップ
これらのツールは通常インストールする必要はありません。必要な依存関係は、
`system-install.sh` スクリプトまたはDockerfileに記載されているとおりにインストールしてください。
便宜上、`PATH` を更新するスクリプトをいくつか用意しています。```sh
# POSIX-like shells (i.e., bash, ...)
source ./scripts/env.sh
# for the fish shell
source ./scripts/env.fish
一部のスクリプトは、Etherscan サービスからメタデータ(例:ABI)を取得するために API キーを必要とします。API キーをお持ちの場合は、ETHERSCAN_API_KEY 環境変数を設定してスクリプトに渡す必要があります。docker ベースのワークフローでは、--env フラグを指定して docker コンテナを起動するか、.etherscan_api_key ファイルに API キーを入れることで、API キーを docker コンテナに組み込むことができます。
便利なように、EF/CF ファザーを起動する際にすべての詳細を処理するラッパースクリプト efcfuzz を利用しています。
ビルドおよびファジングプロセスに関するファザーの動作を設定するために、多くのコマンドラインオプションを設定できます。オプションの一覧は efcfuzz --help を参照してください。
例
Solidity のソースコードを EF/CF ネイティブコードにコンパイルし、5 分間(つまり 300 秒間)ファジングを開始します。```bash efcfuzz --timeout 300 --source ./data/examples/baby_bank.sol
あるいは、ファジング出力を抑えて起動する(`--quiet` はベースファザーの出力を抑制し、
`--print-progress` はファジングの進捗の短い要約を表示する)、そしてファザーを
4コアで起動する。```bash
efcfuzz --quiet --print-progress --cores 4 --timeout 300 --source ./data/examples/baby_bank.sol
既にコンパイル済みのバイトコードを使用し、そのバイトコードをEF/CFネイティブコードにコンパイルして、ファジングを開始します。```bash
pushd ./data/examples/; make baby_bank.combined.json; popd efcfuzz --timeout 300 --bin-runtime ./data/examples/baby_bank.combined.json
pushd ./data/examples/; make baby_bank; popd
efcfuzz --timeout 300
--bin-runtime ./data/examples/baby_bank.bin-runtime
--bin-deploy ./data/examples/baby_bank.bin
--abi ./data/examples/baby_bank.abi
ラッパーは go-ethereum/erigon ノードからコントラクトの状態をエクスポートし、そこから
ファジングを開始できます。```bash
$ efcfuzz --timeout 300 --live-state 0xfffF8D17CB019E0825c478c666B251A7099df3FD
さらに、--include-address-deps=y を渡すと、エクスポートされたコントラクトのストレージ内にある他のアカウントのアドレスを再帰的に検索し、それらもステートエクスポートに含めることができます。ただし、これには Solidity の mapping 型に格納された他のコントラクトは含まれません。実際にステート全体を再帰的にエクスポートするには、--include-mapping-deps=y フラグも渡してください。