
pbtk v1.1.3
Protobufベースのアプリケーション向けのリバースエンジニアリングおよびファジングツールセット
pbtk - Protobufアプリのリバースエンジニアリングツール
Protobufは、Googleが開発したシリアル化フォーマットであり、Android、Web、デスクトップなど、ますます多くのアプリケーションで使用されています。これは、データ構造を宣言するための言語で構成され、ターゲット実装に応じてコードや他の種類の構造にコンパイルされます。
pbtk(Protobufツールキット)は、統合GUIを通じてアクセスできる本格的なスクリプト群であり、2つの主要機能を提供します。
-
プログラムからProtobuf構造を抽出し、読み取り可能な*.proto*ファイルに戻す。さまざまな実装に対応:
- 主要なJavaランタイム(ベース、Lite、Nano、Micro、J2ME)すべて、Proguard完全対応。(2026年:現在も問題なく動作しますが、主に古いAPK向けです)
- 埋め込みリフレクションメタデータを含むバイナリ(通常はC++、時にはJavaや他のバインディング)。(2026年:現在も問題なく動作します)
- JsProtoUrlランタイムを使用するWebアプリケーション。(2026年:アップデートが必要です)
-
Protobufネットワークエンドポイントに送信されるデータの編集、再生、ファジング。便利なグラフィカルインターフェースにより、Protobufメッセージのフィールドをリアルタイムに編集し、結果を表示できます。
インストール
PBTKにはPython ≥ 3.5、PySide 6、Python-Protobuf 3、および抽出スクリプトを実行するためのいくつかの実行可能プログラム(chromium、jad、dex2jar...)が必要です。
Ubuntuユーザーはsnapを使用してインストールできます。
$ sudo snap install pbtk
$ pbtk
Archlinuxユーザーはパッケージから直接インストールできます。
$ yay -S pbtk-git
$ pbtk
他のほとんどのディストリビューションでは、直接実行することをお勧めします。
# Ubuntu/Debian testing派生の場合:
$ sudo apt install python3-pip git openjdk-8-jre python3-qtpy-pyside6
# 次に、UVを使用:
$ sudo snap install --classic astral-uv
$ uv tool install pbtk
$ pbtk
# またはpipxを使用:
$ sudo apt install pipx
$ pipx install pbtk
$ pbtk
Windowsもサポートされています(同じモジュールが必要です)。GUIを実行すると、何が不足しているか、試みる操作に応じて警告が表示されます。
コマンドラインでの使用(パッケージマネージャー経由でインストール)
GUIはメインスクリプトから起動できます。
pbtk
以下のスクリプトは、GUIなしで単独でも使用できます。
pbtk-jar-extract [-h] input_file [output_dir]
pbtk-from-binary [-h] input_file [output_dir]
pbtk-web-extract [-h] input_url [output_dir] # 2026年時点で動作させるにはアップデートが必要
snapからインストールした場合、正確なコマンドは異なります。
pbtk.jar-extract [-h] input_file [output_dir]
pbtk.from-binary [-h] input_file [output_dir]
pbtk.web-extract [-h] input_url [output_dir]
コマンドラインでの使用(ローカル)
GUIはメインスクリプトから起動できます。
uv sync # 依存関係を.venvフォルダにダウンロード
source .venv/bin/activate # ローカルスクリプトを現在のシェルセッションの$PATHに追加
uv tool install -e . # ローカルスクリプトを常に$PATHに追加
pbtk
以下のスクリプトは、GUIなしで単独でも使用できます。
pbtk-jar-extract [-h] input_file [output_dir]
pbtk-from-binary [-h] input_file [output_dir]
pbtk-web-extract [-h] input_url [output_dir] # 2026年時点で動作させるにはアップデートが必要
一般的なワークフロー
あなたがAndroidアプリケーションをリバースエンジニアリングしているとします。お気に入りのデコンパイラでアプリケーションを少し調査し、Protobufが典型的な方法でHTTPS経由でPOSTデータとして転送されていることを特定しました。
PBTKを開くと、わかりやすい画面が表示されます。

最初のステップは、.protoファイルをテキスト形式にすることです。Androidアプリを対象としている場合、APKをドロップして待つだけで魔法が起こるはずです!(非常に特殊な実装でない限り)

これが完了したら、~/.pbtk/protos/<あなたのAPK名>に移動します(コマンドラインから、またはウェルカム画面下部のボタンからファイルブラウザを開くなど、好きな方法で)。アプリのすべての.protoファイルがここにあります。
デコンパイラに戻ると、あなたが関心のあるHTTPSエンドポイントに送信されるデータを構築するクラスを見つけたとします。そのクラスは、生成されたコードからなるクラスを呼び出してProtobufメッセージをシリアル化します。

この後者のクラスは、.protoディレクトリ内のクラスと完全に一致するはずです(例:com.foo.bar.a.bはcom/foo/bar/a/b.protoに一致します)。いずれにせよ、その名前をgrepすれば参照できるはずです。
素晴らしい!次のステップはステップ2に進み、目的の入力.protoを選択し、エンドポイントに関する情報を入力します。

また、このエンドポイントに送信されたサンプルの生のProtobufデータ(mitmproxyやWiresharkでキャプチャしたもの)を16進数エンコード形式で貼り付けることもできます。
ステップ3は、ボタンをクリックして何が起こるかを見る楽しい部分です!Protobuf構造のすべてのフィールドを表すツリービューが表示されます(繰り返しフィールドには「+」が付き、必須フィールドにはチェックボックスがありません)。

フィールドにカーソルを合わせるとフォーカスが当たります。整数型のフィールドの場合は、マウスホイールを使用して値を増減できます。ホバー時に列挙型の情報も表示されます。
これで完了です!これを使ってすべてのフィールドの意味を特定できます。難読化されたコードから.protoを抽出した場合、フィールド名をクリックして、意味に応じて名前を変更できます。
では、リバースエンジニアリングをお楽しみください!👌 🎉
ローカルデータ保存
PBTKは抽出した.proto情報を~/.pbtk/protos/(Windowsの場合は%APPDATA%\pbtk\protos)に保存します。
このディレクトリ内のデータは、通常のファイルブラウザやテキストエディタを使用して直接移動、削除、名前変更、編集できます。これが期待される方法であり、PBTKの動作に影響しません。
HTTPベースのエンドポイントは、JSONオブジェクトとして~/.pbtk/endpoints/に保存されます。これらのオブジェクトは、リクエストとレスポンスの情報のペアの配列であり、次のようになります。
[{
"request": {
"transport": "pburl",
"proto": "www.google.com/VectorTown.proto",
"url": "https://www.google.com/VectorTown",
"pb_param": "pb",
"samples": [{
"pb": "!....",
"hl": "fr"
}]
},
"response": {
"format": "other"
}
}]
ソースコード構造
PBTKは内部で2種類のプラグイン可能なモジュールを使用します。抽出器(extractor)とトランスポート(transport)です。
- 抽出器は、ターゲットのProtobuf実装またはプラットフォームから.proto構造を抽出することをサポートします。
抽出器はsrc/pbtk/extractors/*.pyで定義されます。次のようなデコレータを前に付けたメソッドとして定義されます。
@register_extractor(name = 'my_extractor',
desc = 'Protobuf構造をFoobarコード(*.foo, *.bar)から抽出します',
depends={'binaries': ['foobar-decompiler']})
def my_extractor(path):
# `path`入力ファイルの内容を読み込み、必要な処理を行います...
# 次に、ジェネレータを使用して抽出した.protoをyieldします:
for i in do_your_extraction_work():
yield proto_name + '.proto', proto_contents
# エンドポイント情報や表示する進捗状況など、他の種類の情報もyieldできます。
- トランスポートは、Protobufデータをネットワーク経由で逆シリアル化、再シリアル化、送信する方法をサポートします。例えば、最も一般的に使用されるトランスポートは、HTTP経由の生のPOSTデータです。
トランスポートはsrc/pbtk/utils/transports.pyで定義されます。次のようなデコレータを前に付けたクラスとして定義されます。
@register_transport(
name = 'my_transport',
desc = '生のPOSTデータとしてのProtobuf',
ui_data_form = 'hex strings'
)
class MyTransport():
def __init__(self, pb_param, url):
self.url = url
def serialize_sample(self, sample):
# ユーザーから入力データのサンプルを受け取りました。
# "ui_data_form"パラメータで記述された形式で有効かどうかを検証し、無効な場合は例外またはFalseを返します。
# 必要に応じて、返す前にこのデータを変更します。
bytes.fromhex(sample)
return sample
def load_sample(self, sample, pb_msg):
# 入力データを、提供されたProtobufオブジェクトにパースします。
pb_msg.ParseFromString(bytes.fromhex(sample))
def perform_request(self, pb_data, tab_data):
# 提供されたURLとProtobufオブジェクトを使用してリクエストを実行し、オプションでトランスポート固有のサイドデータを使用します。
return post(url, pb_data.SerializeToString(), headers=USER_AGENT)
今後の改良点
今後のリリースで以下の機能が追加される可能性があります。
- 自動ファジング部分の完成。
- Javaコードから拡張を抽出するサポート。
- JSPB(メインJavaScript)ランタイムのサポート。
- 他にサポートしてほしいプラットフォームがあれば、issueを送ってください。検討します。
私は、ほとんどのモジュール(GUIシグナルの接続など、ほとんど自己記述的な部分は除く)について、読みやすくコメントされたコードを提供するよう最善を尽くしました。コントリビュートも歓迎します。
ライセンス
pbtkはGNU GPLライセンスの下でリリースされています(以下、著者による宣言があります)。
プロジェクト名の大文字小文字に関する正式なルールはありません。ルールはあなたの心に従うことだけです❤