marin-m/pbtk

GitHub: marin-m/pbtk

一套用于从多种平台逆向提取 Protobuf 定义并支持可视化编辑、重放与模糊测试的图形化工具集。

Stars: 1631 | Forks: 198

# pbtk - 逆向工程 Protobuf 应用 **[Protobuf](https://developers.google.com/protocol-buffers/) 是一种序列化格式**,由 Google 开发,并被越来越多的 Android、Web、桌面及其他应用程序所使用。它包含一种**用于声明数据结构的语言**,随后根据目标实现将其编译为代码或其他类型的结构。 pbtk (*Protobuf toolkit*) 是一套功能齐全的脚本集合,通过统一的 GUI 访问,提供两个主要功能: - **从程序中提取 Protobuf 结构**,将其转换回可读的 *.proto* 文件,支持多种实现: - 所有主要的 Java 运行时(base、Lite、Nano、Micro、J2ME),完全支持 Proguard, - 包含嵌入式反射元数据的二进制文件(通常是 C++,有时是 Java 和大多数其他绑定), - 使用 JsProtoUrl 运行时的 Web 应用程序。 - **编辑、重放和模糊测试**发送到 Protobuf 网络端点的数据,通过一个方便的图形界面,允许您实时编辑 Protobuf 消息的字段并查看结果。 ![pbtk 编辑器 GUI](https://i.imgur.com/7w6ABqy.png) ## 安装 PBTK 需要 Python ≥ 3.5、PySide 6、Python-Protobuf 3 以及一些可执行程序(chromium、jad、dex2jar...)来运行提取脚本。 Archlinux 用户可以直接通过[软件包](https://aur.archlinux.org/packages/pbtk-git/)安装: ``` $ 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 # Or using 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] ``` ## 命令行用法(本地) 可以通过主脚本启动 GUI: ``` 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] ``` ## 典型工作流程 假设您正在对一个 Android 应用程序进行逆向工程。您使用自己喜欢的反编译器对应用程序进行了一些探索,并发现它以典型的方式通过 HTTPS 传输 Protobuf 作为 POST 数据。 您打开 PBTK,会受到有意义的问候: ![欢迎屏幕](https://i.imgur.com/oVsypWN.png) 第一步是将您的 .protos 转换为文本格式。如果您的目标是 Android 应用程序,放入 APK 并等待应该就能完成神奇的工作!(除非它是一个非常异类的实现) ![完成屏幕](https://i.imgur.com/uC9dnWV.png) 完成后,您跳转到 `~/.pbtk/protos/`(通过命令行,或欢迎屏幕底部的按钮打开文件浏览器,随您喜欢)。应用程序的所有 .protos 确实都在这里。 回到反编译器中,您偶然发现了构建发送到您感兴趣的 HTTPS 端点的数据的类。它通过调用一个由生成的代码组成的类来序列化 Protobuf 消息。 ![您的反编译器](https://i.imgur.com/x9YAChW.png) 后一个类应该在您的 .protos 目录中有一个完美的匹配(即 `com.foo.bar.a.b` 将匹配 `com/foo/bar/a/b.proto`)。无论哪种方式,grep 其名称都应该能让您找到它。 太棒了:下一步是进入 **Step 2**,选择所需的输入 .proto,并填写有关您的端点的一些信息。 ![端点创建表单](https://i.imgur.com/jhu68pG.png) 您还可以提供一些通过 mitmproxy 或 Wireshark 捕获的、发送到此端点的原始 Protobuf 数据样本,您将以十六进制编码的形式粘贴它。 **Step 3** 是有趣的部分,点击按钮看看会发生什么!您有一个树状视图,代表 Protobuf 结构中的每个字段(重复字段以“+”为后缀,必填字段没有复选框)。 ![端点创建表单](https://i.imgur.com/2lVmGoG.png) 只需将鼠标悬停在字段上即可获得焦点。如果字段是整数类型,请使用鼠标滚轮对其进行递增/递减。枚举信息也会在悬停时出现。 就是这样!您可以据此确定每个字段的含义。如果您是从混淆代码中提取的 .protos,您可以根据您注意到的含义重命名字段,方法是单击它们的名称。 祝逆向愉快! 👌 🎉 ## 本地数据存储 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 在内部使用两种类型的可插拔模块:提取器(extractor)和传输器(transport)。 * **extractor** 支持从目标 Protobuf 实现或平台提取 .proto 结构。 提取器在 `src/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. ``` * **transport** 支持一种通过网络反序列化、重新序列化和发送 Protobuf 数据的方式。例如,最常用的传输方式是 HTTP 上的原始 POST 数据。 传输器在 `src/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) ``` ## 未来的改进 以下内容可能会在未来的版本中推出: * 完成自动模糊测试部分。 * 支持从 Java 代码中提取扩展。 * 支持 JSPB(主要的 JavaScript)运行时。 * 如果您希望支持任何其他平台,请提出 issue,我会查看。 我已尽力为大多数模块生成易于阅读和注释完善的代码(除了那些主要是不言自明的部分,如连接 GUI 信号),以便您可以做出贡献。 ## 许可 pbtk 根据 [GNU GPL](https://www.gnu.org/licenses/gpl-3.0.html) 许可证发布(我在此声明,等等)。 对于项目名称的字母大小写没有形式化的规则,规则只是随心所欲 ❤
标签:C++逆向, Fuzzing, GUI工具, Java反编译, Protobuf, Proto文件生成, PySide, Python, TLS抓取, 二进制分析, 云安全运维, 云资产清单, 协议分析, 协议缓冲区, 安卓逆向, 序列化格式, 数据提取, 数据结构还原, 无后门, 权限提升, 系统运维工具, 网络流量分析, 网络端点, 谷歌协议缓冲区, 软件安全, 逆向工具, 逆向工程