この記事は、Defensics®ソフトウェア開発キット(SDK)を利用してビットコインソフトウェアのファジングを行う方法を説明する2部構成の記事の第1部です。具体的には、ビットコインネットワークのプロトコルメッセージをモデル化し、Defensics SDKを用いてbitcoindプロセスに対してファジングを実行する方法を説明します。
内容は上級者向けのチュートリアルなので、ひととおり次のような技術知識が必要になります。
この記事では、ビットコインのバイナリとWiresharkを用いてテストベッドを設定する方法について説明します。次回の記事では、Defensics SDKを用いてビットコイン・プロトコル・メッセージをモデル化し、最終的にDefensics SDKでビットコインのファジングを実行する方法を説明します。
Defensicsは、さまざまなネットワークプロトコルやファイル形式に対応する250を超えるテスト製品群を備えたファジングプラットフォームです。
Defensics SDKを使用すれば、独自のテストスイートを作成し、あらゆるプロトコルやファイル形式に対してDefensicsの機能をフルに発揮させることができます。必要な作業はデータモデルの指定だけです。その後は、本格的なDefensicsテストスイートを作成して、高性能なジェネレーショナル・テストケース・エンジンやDefensicsプラットフォームが提供するその他のすべての機能を活用できます。
ビットコインは数学の暗号理論によってサポートされている暗号通貨です。暗号通貨は、政府が発行する通貨のように一元管理されるのではなく、ピアツーピア・ネットワークを利用してコミュニティによって管理されます。ビットコインなどの暗号通貨は、すべてのトランザクションのリストを暗号化によって保護したブロックチェーンを基盤にしています。ネットワーク上の各ピア(ノード)は、暗号によって改ざんから保護されたブロックチェーンのコピーを保持します。ネットワーク上のピアが使用しているアルゴリズムでは、新しいトランザクションが生じると、ブロックチェーンに追加することに合意しています。これによりネットワーク全体としても、ピア同士が互いに信用する処理を省略してトランザクションを行うことが可能になりました。
暗号通貨は比較的新しい技術です。その最初は2007年に導入されたビットコインでした。やや実験的な性質があるにもかかわらず、この通貨には巨額が投じられています。この記事の執筆時点でビットコインの時価総額は3,500億ドルを超えています。
この記事を読むに際して、ビットコインやその他のプロトコルに関する詳細を知っている必要はありません。ビットコインのピア間でbitcoindと呼ばれるプロセスを実行するということさえ知っておけば十分です。ネットワーク上のピア同士がビットコイン・ネットワーク・プロトコルを使用して情報を交換します。
bitcoindを実行するだけなら仮想マシンとDockerコンテナは不要です。以下で概要を説明します。Bitcoinパッケージをダウンロードし、bitcoind -regtestを実行するだけです。
以下のテストベッドを設定すると、いくつかの利点があります。
bitcoindのファジングの最初のステップは、テストベッド(危害なくファジングを実行できる安全な場所)を作成することです。ファジングは、実稼働システムで実行すると障害を引き起こしたり、セキュリティアラームをトリガーする可能性が高いため、実稼働システムでは実行しないでください。
Bitcoinは本番ネットワーク(mainnet)、テストネットワーク(testnet)、回帰テストネットワーク(regtest)をサポートしています。私は、ファジングに最適な非公開の隔離されたビットコインネットワークを設定できるという点から、regtestネットワークを使用してファジングを行いました。
まず、regtest用のピア、fleurとviktorを保持する仮想マシンを作成することから始めました。私はUbuntu 20.04を使用しましたが、任意のLinuxを使用できます。この手順は厳密には必要ではなく、ホストOS上でDockerインスタンスを直接作成するだけで済むのですが、私は隔離のレイヤーを追加したいと思いました。
Dockerの素晴らしい機能によって、仮想マシンのポートはfleurコンテナとviktorコンテナのポートに割り当てられます。起動が完了すると、次のようになります。
次の記事では、Defensics SDKを使用してbitcoindインスタンスのファジングを行います。Defensicsは同じ仮想マシン上、別の仮想マシン上、またはホストOS上のいずれでも実行できます。
私はLinuxを新規にインストールしたコンピューターに、まずgitとdockerをインストールしました。
$ sudo apt-get install -y git docker.io
最新のビットコインプロトコルのディセクタを取得するため、次のようにWiresharkをインストールしました。
$ sudo add-apt-repository ppa:wireshark-dev/stable
...
$ sudo apt-get update
...
$ sudo apt-get install -y wireshark
...
これで、私のスクリプトを利用して、bitcoindを実行するDockerコンテナを作成し、使用することができるようになります (この方法のヒントを与えてくれたGerald Kaszubaに感謝します)。
最初に私のリポジトリのクローンを作成します。
$ git clone https://github.com/jknudsen-synopsys/bitcoinzz-testbed.git
build.shを実行してDockerイメージをビルドします。
$ cd bitcoinzz-testbed
$ ./build.sh
コンテナイメージは、ほとんどUbuntuのベースイメージとBitcoinバイナリだけの単純なものです。このスクリプトを実行すると、本稿執筆時点で最新バージョンのBitcoin 0.20.1がダウンロードされます。バージョンを変更する場合は、bitcoinzz.dockerを編集して任意のバージョンを指定します。
2つの別々のターミナルウィンドウを使用すると、run_fleur.shとrun_viktor.shでコンテナイメージの2つのインスタンスをスピンアップできます。
ビットコインデーモンbitcoindはコンテナ内で自動的に起動され、bitcoin-cli -regtestのエイリアスrtが生成されます。これで、エイリアスを使用してコマンドをbitcoindに渡し、情報を取得できます。
$ ./run-fleur.sh
Bitcoin Core starting
root@fleur:~# rt -getinfo
{
"version": 200100,
"blocks": 0,
"headers": 0,
"verificationprogress": 1,
"timeoffset": 0,
"connections": 0,
"proxy": "",
"difficulty": 4.656542373906925e-10,
"chain": "regtest",
"balance": 0.00000000,
"keypoolsize": 1000,
"paytxfee": 0.00000000,
"relayfee": 0.00001000,
"warnings": ""
}
root@fleur:~#
実行されている2つのbitcoindインスタンスは、互いに他方のインスタンスについての情報を知りません。
両者が連携していることを実証したい場合は、Wiresharkを実行し、docker0インターフェイスをリッスンします。次に、IPアドレスを使用して、一方のbitcoindインスタンスで他方のインスタンスを指定します。
私はhostnameを使用してfleurのIPアドレスを見つけました。
root@fleur:~# hostname -I
172.17.0.3
次に、viktorのbitcoindにfleurの情報を次のように通知しました。
root@viktor:~# rt addnode 172.17.0.3 onetry
これによってfleurとviktorのbitcoindプロセスの間で交換されたビットコインメッセージが次々と返ってきました。
おめでとうございます!これで独自のプライベート・ビットコイン・ネットワークが出来上がりました。
次回は、ビットコイン・ネットワーク・プロトコルのモデルを構築し、そのモデルをDefensics SDKで使用してbitcoindに対してファジングを実行します。