
🕵️ Инструмент для обратного проектирования Protocol Buffers с неизвестным определением
Простая программа, которая может разбирать закодированные большие двоичные объекты Google Protobuf (версии 2 или 3) без знания их сопровождающего определения. Она выведет красивое, цветное представление их содержимого. Пример:

Как видите, имена полей, очевидно, теряются, вместе с некоторыми высокоуровневыми деталями, такими как:
Но protobuf-inspector в большинстве случаев способен правильно угадать структуру сообщения. Когда он находит встроенные двоичные данные в поле, он сначала попытается разобрать их как сообщение. Если это не удается, он отобразит данные как строку или hexdump. Он может ошибаться, особенно с небольшими фрагментами.
Он показывает поля именно в том порядке, в котором они закодированы в проводе, поэтому может быть полезен для тех, кто хочет ознакомиться с [форматом провода][] или разработчикам парсеров, в дополнение к обратной разработке.
Вы можете установить с помощью pip:
pip install protobuf-inspector
Это устанавливает команду protobuf_inspector. Запустите её, подав большой двоичный объект protobuf на stdin:
protobuf_inspector < my-protobuf-blob
После чтения первого (слепого) анализа большого двоичного объекта вы обычно начинаете определять некоторые из полей, чтобы protobuf-inspector мог лучше разбирать ваши объекты, пока не дойдете до точки, где у вас есть полное определение protobuf и парсеру больше не нужно ничего угадывать.
Читайте о задании полей здесь.
Если обнаружена ошибка разбора, разбор остановится внутри этого поля, но продолжится без изменений вне иерархии. Трассировка стека будет напечатана там, где должно было быть содержимое поля, вместе с hexdump, указывающим, где разбор был остановлен в этом фрагменте, если применимо.
Итак, если вы указали uint32, а найдена большая varint, вы получите примерно следующее:

Если вы указали, что некоторое поле содержит встроенное сообщение, но там обнаружены недопустимые данные, вы получите:

Обратите внимание, что main.py завершится с ненулевым статусом, если произошла одна или несколько ошибок разбора.
Существуют некоторые хитрости, которые вы можете использовать для экономии времени при работе с большим двоичным объектом:
Если вы уверены, что varint не использует zig-zag кодирование, но все еще не уверены в знаковости, оставьте его как varint. Если он использует zig-zag кодирование, используйте sint64, если вы не уверены, что он 32-битный, а не 64-битный.
Если фрагмент ошибочно распознается как packed chunk или встроенное сообщение, или вы видите что-то странное в разобранном сообщении и хотите увидеть сырые байты, укажите тип bytes. И наоборот, если по какой-то причине он не обнаруживается как встроенное сообщение, а должен, принудительно укажите message, чтобы увидеть причину.
Если вы хотите извлечь сырые данные фрагмента в файл для более тщательного анализа, укажите тип dump, и protobuf-inspector будет создавать dump.0, dump.1 и т.д. каждый раз, когда находит соответствующий большой двоичный объект.
protobuf-inspector разбирает большой двоичный объект как сообщение типа root, но это всего лишь значение по умолчанию. Если у вас определено много типов сообщений, вы можете передать имя типа в качестве необязательного аргумента, и protobuf-inspector будет использовать его вместо root:
Простой пример:
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.
protobuf_inspector request < my-protobuf-blob