
Набор инструментов для реверс-инжиниринга и фаззинга приложений на основе Protobuf
Protobuf — это формат сериализации, разработанный Google и используемый во всё большем числе Android, веб, настольных и других приложений. Он включает язык для описания структур данных, который затем компилируется в код или другую структуру в зависимости от целевой реализации.
pbtk (Protobuf toolkit) — это полноценный набор скриптов, доступных через единый графический интерфейс, предоставляющий две основные возможности:
Извлечение структур Protobuf из программ, преобразование их обратно в читаемые .proto файлы, с поддержкой различных реализаций:
Редактирование, повторная отправка и фаззинг данных, отправляемых на сетевые конечные точки 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
На большинстве других дистрибутивов лучше запускать напрямую:
# For Ubuntu/Debian testing derivates:
$ sudo apt install python3-pip git openjdk-8-jre python3-qtpy-pyside6
# Then, using UV:
$ sudo snap install --classic astral-uv
$ uv tool install pbtk
$ pbtk
# Or using pipx:
$ sudo apt install pipx
$ pipx install pbtk
$ pbtk
Windows также поддерживается (с теми же требуемыми модулями). После запуска графического интерфейса он предупредит вас о том, чего не хватает, в зависимости от того, что вы пытаетесь сделать.
Графический интерфейс можно запустить через основной скрипт:
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] # Needs update to work as of 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]
Графический интерфейс можно запустить через основной скрипт:
uv sync # Download dependencies to the .venv folder
source .venv/bin/activate # Put the local scripts in $PATH for the current shell session
uv tool install -e . # Put the local scripts in $PATH all time
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] # Needs update to work as of 2026
Предположим, вы занимаетесь обратной разработкой Android-приложения. Вы немного изучили приложение с помощью любимого декомпилятора и поняли, что оно передаёт Protobuf в качестве POST-данных по HTTPS обычным способом.
Вы открываете PBTK, и вас встречают с осмысленным приветствием:

Первый шаг — получить ваши .protos в текстовом формате. Если вы работаете с Android-приложением, просто перетащите APK и подождите — магия произойдет! (если только это не совсем экзотическая реализация)

После этого вы переходите в ~/.pbtk/protos/<имя вашего APK> (либо через командную строку, либо через кнопку внизу экрана приветствия, чтобы открыть файловый менеджер — как вам удобнее). Все .protos приложения действительно здесь.
Вернувшись в декомпилятор, вы наткнулись на класс, который конструирует данные, отправляемые на интересующую вас HTTPS-конечную точку. Он сериализует сообщение Protobuf, вызывая класс, состоящий из сгенерированного кода.

Этот последний класс должен иметь точное соответствие в вашей директории .protos (т.е. com.foo.bar.a.b будет соответствовать com/foo/bar/a/b.proto). В любом случае, поиск по его имени позволит вам сослаться на него.
Отлично: следующий шаг — перейти к Шагу 2, выбрать нужный входной .proto и заполнить информацию о вашей конечной точке.

Вы также можете предоставить образец необработанных данных Protobuf, которые были отправлены на эту конечную точку и перехвачены через mitmproxy или Wireshark, и вставить их в шестнадцатеричном формате.
Шаг 3 — это весёлая часть: нажимать кнопки и смотреть, что происходит! У вас есть древовидное представление, отображающее каждое поле в структуре Protobuf (повторяющиеся поля помечены суффиксом "+", обязательные поля не имеют флажков).

Просто наведите курсор на поле, чтобы сфокусироваться. Если поле целочисленного типа, используйте колёсико мыши для увеличения/уменьшения. Информация о перечислении также появляется при наведении.
Вот и всё! Вы можете определить значение каждого поля с помощью этого. Если вы извлекли .protos из минифицированного кода, вы можете переименовывать поля в соответствии с тем, что, как вы заметили, они означают, щёлкнув по их именам.
Удачного реверсинга! 👌 🎉
PBTK сохраняет извлечённую информацию .proto в ~/.pbtk/protos/ (или %APPDATA%\pbtk\protos на Windows).
Вы можете перемещать, копировать, переименовывать, редактировать или удалять данные из этой директории напрямую через обычный файловый менеджер и текстовый редактор — это предусмотренный способ, и он не повлияет на работу PBTK.
HTTP-конечные точки сохраняются в ~/.pbtk/endpoints/ в виде JSON-объектов. Эти объекты представляют собой массивы пар информации запроса/ответа, которые выглядят так:
[{
"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 внутренне использует два типа подключаемых модулей: экстракторы и транспорты.
Экстракторы определены в src/pbtk/extractors/*.py. Они определяются как метод с декоратором, например:
@register_extractor(name = 'my_extractor',
desc = 'Extract Protobuf structures from Foobar code (*.foo, *.bar)',
depends={'binaries': ['foobar-decompiler']})
def my_extractor(path):
# Load contents of the `path` input file and do your stuff...
# Then, yield extracted .protos using a generator:
for i in do_your_extraction_work():
yield proto_name + '.proto', proto_contents
# Other kinds of information can be yield, such as endpoint information or progress to display.
Транспорты определены в src/pbtk/utils/transports.py. Они определяются как класс с декоратором, например:
@register_transport(
name = 'my_transport',
desc = 'Protobuf as raw POST data',
ui_data_form = 'hex strings'
)
class MyTransport():
def __init__(self, pb_param, url):
self.url = url
def serialize_sample(self, sample):
# We got a sample of input data from the user.
# Verify that it is valid in the form described through "ui_data_form" parameter, fail with an exception or return False otherwise.
# Optionally modify this data prior to returning it.
bytes.fromhex(sample)
return sample
def load_sample(self, sample, pb_msg):
# Parse input data into the provided Protobuf object.
pb_msg.ParseFromString(bytes.fromhex(sample))
def perform_request(self, pb_data, tab_data):
# Perform a request using the provided URL and Protobuf object, and optionally other transport-specific side data.
return post(url, pb_data.SerializeToString(), headers=USER_AGENT)
Следующее может появиться в будущих версиях:
Я постарался сделать код максимально читаемым и с комментариями (за исключением частей, которые в основном говорят сами за себя, например, подключение сигналов GUI) для большинства модулей, чтобы вы могли внести свой вклад.
pbtk выпущен под лицензией GNU GPL (я, настоящим, и т.д.).
Нет формализованного правила для регистра букв в названии проекта, правило просто — следовать своему сердцу ❤