
🕵️ 不明な定義を持つProtocol Buffersをリバースエンジニアリングするツール
定義が不明な状態で Google Protobuf エンコードされたブロブ(バージョン 2 または 3)を解析できるシンプルなプログラムです。内容の見やすく色付けされた表現を出力します。例:

ご覧の通り、フィールド名は当然失われ、以下のような高レベルの詳細も失われます:
しかし、protobuf-inspector はほとんどの場合、メッセージ構造を正しく推測できます。フィールドに埋め込みバイナリデータが見つかると、まずそれをメッセージとして解析しようと試みます。それが失敗すると、データを文字列または hexdump として表示します。特に小さなチャンクでは誤る可能性があります。
フィールドはワイヤー上でエンコードされた順序で表示されるため、リバースエンジニアリングに加えて、ワイヤーフォーマット に詳しくなりたい人やパーサー開発者にとっても有用です。
pip でインストールできます:
pip install protobuf-inspector
これにより protobuf_inspector コマンドがインストールされます。実行し、protobuf ブロブを標準入力から読み込ませます:
protobuf_inspector < my-protobuf-blob
ブロブの最初の(ブラインド)分析を読んだ後、通常は一部のフィールドを定義し始めて、protobuf-inspector がブロブをより適切に解析できるようにし、最終的に完全な protobuf 定義が得られてパーサーが推測する必要がなくなるまで続けます。
解析エラーが見つかった場合、そのフィールド内での解析は停止しますが、階層の外部には影響なく続行されます。フィールドの内容が表示されるべき場所にスタックトレースが出力され、該当する場合はそのチャンクで解析が停止した位置を示す hexdump も表示されます。
つまり、uint32 を指定したのにそれより大きな varint が見つかった場合、次のような出力が得られます:

あるフィールドに埋め込みメッセージが含まれると指定したが、そこに不正なデータが見つかった場合:

1つ以上の解析エラーが発生した場合、main.py は非ゼロのステータスで終了することに注意してください。
ブロブに取り組む際に時間を節約できるテクニックがいくつかあります:
varint が zig-zag エンコーディングを使用していないことが確実だが、符号の有無がまだ不明な場合は、varint のままにしておきます。zig-zag エンコーディングを使用している場合は、32ビットで 64ビットでないことが確実でない限り sint64 を使用してください。
チャンクが誤って packed chunk または埋め込みメッセージとして認識されている場合、または解析されたメッセージに何かおかしな点があり生のバイトを見たい場合は、bytes 型を指定します。逆に、何らかの理由で埋め込みメッセージとして検出されないのにそうあるべき場合は、message に強制して理由を確認します。
チャンクの生データをファイルに抽出してより詳細に分析したい場合は、dump 型を指定すると、一致するブロブが見つかるたびに protobuf-inspector が dump.0、dump.1 などを作成します。
protobuf-inspector はブロブを root 型のメッセージとして解析しますが、これはデフォルトに過ぎません。多くのメッセージ型が定義されている場合は、オプションの引数として型名を渡すことができ、protobuf-inspector は root の代わりにその型を使用します:
protobuf_inspector request < my-protobuf-blob
簡単な例:
from protobuf_inspector.types import StandardParser
parser = StandardParser()
with open('my-blob', 'rb') as fh:
output = parser.parse_message(fh, "message")
print(output)
このプロジェクトは当初ライブラリとしての使用を想定して設計されていなかったため、API は変更される可能性があります。より複雑な例については、protobuf_inspector/__main__.py を参照してください。