js逆向-protobuf专题-基础知识
目录
前言
TIP
简单理解: 谷歌浏览器快速传输协议
内容不是明文的,没办法解析数据,常见的对数据加密有三种情况:
第一种是,用诸如AES这类加密算法对数据加密,然后在APP里用key进行解密,这类的数据解密的难度不是很大,弄清楚是用的什么加密算法就能反解。
第二种是,用“私有”协议把数据序列化,只有了解该协议的细节才有可能把数据反序列化出来。这个的难度较大,没有功底,头发撸白都不一定撸出来。游戏和大厂APP盛行搞一个自己的私有协议来交换数据。
第三种是,用第三方厂商的协议来数据序列化,自己搞不出来私有协议的就选用第三方厂商的。比如用 Google 的 Protobuf ,来做数据序列化,也就是数据“加密”。
先来看一个🌰:
加密前
加密后
介绍
protobuf简介 Protobuf是Protocol Buffers的简称,它是Google开发的数据序列化协议,是一种轻便高效的结构化数据存储格式,它通过将数据转换为二进制格式进行传输,可以用于结构化数据串行化,或者说序列化,不仅减小了数据体积、提高了传输效率 。它很适合做数据存储或 RPC 数据交换格式。
与JSON或XML等文本格式不同,Protobuf将数据序列化为二进制格式,因此肉眼难以直接解读,常被视为“乱码”。这种特性使其常被网站或APP用作数据反爬的一种手段
protobuf的优劣势
1)优势:
序列化后体积相比Json和XML很小,适合网络传输
序列化反序列化速度很快,快于Json的处理速度
消息格式升级和兼容性还不错
支持跨平台多语言
2)劣势:
应用不够广(相比xml和json)
二进制格式导致可读性差
缺乏自描述
特征识别
在进行爬虫逆向时,可以通过以下特征识别Protobuf:
网络请求(Network)特征:
- 请求头 (Request Headers):Content-Type可能为 application/grpc-webproto, application/protobuf, application/x-protobuf等。
- 请求参数或响应体 (Payload):在开发者工具的“预览”或“响应”面板中看到完全不可读的乱码,或者在Hex视图中看到大量的十六进制数字。
Protobuf的“正向”工作流程
引用 "平哥" 文章 Protobuf协议逆向解析-APP爬虫
先了解下 Protobuf 序列化和反序列化的整个流程:
1.1. 先定义一个 Protobuf 语法文件(.proto 文件)
该语法文件用来说明要传输哪些字段、字段的数据类型、数据间的嵌套关系这些。 比如一个 APP 要返回的数据有电话号码,姓名,年龄这三个字段,你就需要把这三个字段定义在 .proto 文件里,并且指明他们的数据类型,比如姓名和电话是字符串,年龄是整型。
1.2. 使用 Protobuf 提供的工具编译该语法文件
用工具编译 .proto 文件的目的是,把 .proto 文件编译成代码,工具会根据该 .proto 文件自动生产代码。这个代码就是用来做数据序列化和反序列化的。
1.3. 服务端用第2步中的代码,把"明文"数据序列化,变成"密文"后,返回给 APP
1.4. APP 客户端用第2步中的代码,把"密文"数据反序列化,就"解密"成明文拉
正向开发流程
1. 先配置 Protobuf
环境https://github.com/protocolbuffers/protobuf/releases/

配置环境变量 
2. 写一个 .proto 语法文件语法文件怎么写,要根据具体的传输数据来定制,
比如按照 example 里的示例,如果要传输的数据是如下格式:
那么定义的 .proto 语法文件就如下:
syntax = "proto3";
package authentication;
// 请求消息格式
message ChallengeRequest {
int32 page = 1; // 请求的页码
string challengetype = 2; // 挑战类型
int64 timestamp = 3; // 时间戳,防止重放攻击
string signature = 4; // 请求签名
}
// 响应消息格式
message ChallengeResponse {
repeated NumberData numbers = 1; // 数字列表
int32 total_pages = 2; // 总页数
int32 current_page = 3; // 当前页码
int64 timestamp = 4; // 响应时间戳
string signature = 5; // 响应签名
}
// 单个数字数据
message NumberData {
int32 id = 1; // 数字ID
int32 value = 2; // 数字值
}3.使用第一步中下载的 protoc 编译器来编译 .proto 文件
确保在包含 challenge.proto 的目录中执行
D:\soft\protoc\protoc-3.20.1-win64\bin\protoc --python_out=. challenge.proto4."加密"与"解密"
# 使用生成的代码
import challenge_pb2
# 创建对象
challenge = challenge_pb2.ChallengeRequest()
challenge.page = 2
challenge.challengetype = "aaaa"
challenge.timestamp = 25123123123
challenge.signature = "asdasdasdasdasdasd"
# 序列化(明文 → 密文)
binary_data = challenge.SerializeToString()
print(f"序列化后: {binary_data}") # 二进制数据
# 反序列化(密文 → 明文)
new_challenge = challenge_pb2.ChallengeRequest()
new_challenge.ParseFromString(binary_data)
print(f"page: {new_challenge.page}")
print(f"challengetype: {new_challenge.challengetype}")
print(f"timestamp: {new_challenge.timestamp}")
print(f"signature: {new_challenge.signature}")import challenge_pb2
challenge = challenge_pb2.ChallengeRequest()
challenge.page = 2
challenge.challengetype = "aaaa"
challenge.timestamp = 25123123123
challenge.signature = "asdasdasdasdasdasd"
binary_data = challenge.SerializeToString()
print(f"序列化后: {binary_data}") # 二进制数据
with open("challenge.bin", "wb") as f:
f.write(binary_data)
# 解密
new_challenge = challenge_pb2.ChallengeRequest()
with open("challenge.bin", "rb") as f:
new_challenge.ParseFromString(f.read())
print(f"page: {new_challenge.page}")
print(f"challengetype: {new_challenge.challengetype}")
print(f"timestamp: {new_challenge.timestamp}")
print(f"signature: {new_challenge.signature}")逆向解析 Protobuf
当确认数据使用Protobuf后,主要有以下两种解析思路:
使用 blackboxprotobuf库(推荐入门)
这是一个Python第三方库,可以在没有 .proto文件的情况下直接进行反序列化,非常适合快速探索。
import blackboxprotobuf
import requests
# 假设 response.content 是Protobuf二进制响应
response = requests.post(url, headers=headers, data=data)
# 将二进制数据反序列化为JSON格式的字典和消息类型描述
deserialized_data, message_type = blackboxprotobuf.protobuf_to_json(response.content)
print("反序列化后的数据:", deserialized_data)
print("推断出的消息类型:", message_type)- 优点:快速便捷,无需深入分析JS代码。
- 缺点:可能无法完美解析所有复杂或嵌套的消息类型,消息类型推断可能不准确。
逆向JS,还原 .proto文件(彻底解决)
这是最根本的方法,目的是还原出网站使用的原始 .proto定义,然后自己编译成Python包使用。
正向过程比较轻松,因为对方即有 .proto 文件,也有序列化代码,也知道要传输的数据样式。
但是逆向这个过程,APP里是没有 .proto文件的,APP里是有反序列化的代码,但是看得也头晕。那该怎么办呢?
借助工具,我们使用上面下载的protoc编译工具,这个工具提供反解析参数
cmd
D:\soft\protoc\protoc-3.20.1-win64\bin\protoc –decode_raw < challenge.bin
powshell
cmd.exe /c "D:\soft\protoc\protoc-3.20.1-win64\bin\protoc --decode_raw < challenge.bin"
