【JS 逆向百例】steam 登录 Protobuf 协议详解
字数 1248 2025-08-18 11:36:53
Steam登录Protobuf协议逆向分析教程
1. 目标分析
目标网站:Steam登录页面(已脱敏处理)
主要接口:
GetPasswordRSAPublicKey/v1- 获取RSA公钥信息BeginAuthSessionViaCredentials/v1- 登录接口
2. Protobuf协议基础
Protocol Buffers (Protobuf) 是Google开发的一种数据序列化协议,特点:
- 根据特定语法定义数据结构
- 发送和接收数据需要预先约定数据字段
- 体积小、解析速度快
常见数据类型:
| 数据类型 | 描述 |
|---|---|
| int32/int64 | 有符号整数 |
| uint32/uint64 | 无符号整数 |
| float/double | 浮点数 |
| bool | 布尔值 |
| string | 字符串 |
| bytes | 二进制数据 |
| enum | 枚举类型 |
| message | 消息类型(可嵌套) |
| map | 键值对映射 |
| repeated | 数组/列表 |
3. 第一个接口:GetPasswordRSAPublicKey/v1
3.1 请求参数分析
请求参数为 input_protobuf_encoded,其生成过程:
- 构造包含账号信息的对象
- 序列化为Protobuf二进制格式
- Base64编码
JavaScript关键代码:
o = n.SerializeBody();
a = r.JQ(o); // Base64编码
3.2 Protobuf消息定义
账号请求消息结构:
syntax = "proto3";
message CAuthenticationGetPasswordRsaPublicKeyRequest {
string account_name = 1;
}
3.3 Python实现
生成Python代码:
protoc --python_out=. steam.proto
请求示例:
import base64
from steam_pb2 import CAuthenticationGetPasswordRsaPublicKeyRequest
message = CAuthenticationGetPasswordRsaPublicKeyRequest(
account_name="a123456789"
)
protobuf = base64.b64encode(message.SerializeToString()).decode()
3.4 响应解析
响应消息结构:
message CAuthenticationGetPasswordRsaPublicKeyResponse {
string publickey_mod = 1; // RSA模数
string publickey_exp = 2; // RSA指数
uint64 timestamp = 3; // 时间戳
}
Python解析响应:
from steam_pb2 import CAuthenticationGetPasswordRsaPublicKeyResponse
response = CAuthenticationGetPasswordRsaPublicKeyResponse.FromString(response.content)
print(response.publickey_mod)
print(response.publickey_exp)
print(response.timestamp)
4. 第二个接口:BeginAuthSessionViaCredentials/v1
4.1 请求参数分析
请求消息结构:
message CAuthenticationBeginAuthSessionViaCredentialsRequest {
string device_friendly_name = 1;
string account_name = 2;
string encrypted_password = 3; // RSA加密后的密码
uint64 encryption_timestamp = 4; // 时间戳
bool remember_login = 5;
int32 platform_type = 6;
int32 persistence = 7;
string website_id = 8;
DeviceDetails device_details = 9; // 自定义类型
string guard_data = 10;
uint32 language = 11;
int32 qos_level = 12;
}
message DeviceDetails {
// 设备详情字段定义
// 根据实际JS代码补充具体字段
}
4.2 密码加密过程
使用第一个接口返回的公钥信息进行RSA加密:
- 使用
publickey_mod和publickey_exp构造公钥 - 对密码进行RSA加密
- 将加密结果作为
encrypted_password字段
JavaScript加密代码:
h.IC(a, t) // a为密码明文,t为公钥信息
5. 完整Python实现
5.1 获取RSA公钥
import base64
import requests
from steam_pb2 import CAuthenticationGetPasswordRsaPublicKeyRequest
def get_rsa_public_key(username):
origin = 'https://steamcommunity.com'
message = CAuthenticationGetPasswordRsaPublicKeyRequest(
account_name=username
)
protobuf = base64.b64encode(message.SerializeToString()).decode()
url = 'https://api.steampowered.com/IAuthenticationService/GetPasswordRSAPublicKey/v1'
params = {
"origin": origin,
"input_protobuf_encoded": protobuf
}
response = requests.get(url, params=params, headers=headers)
return response.content
5.2 登录请求
from steam_pb2 import CAuthenticationBeginAuthSessionViaCredentialsRequest
def login(username, encrypted_pwd, timestamp):
message = CAuthenticationBeginAuthSessionViaCredentialsRequest(
account_name=username,
encrypted_password=encrypted_pwd,
encryption_timestamp=timestamp,
# 其他必填字段...
)
protobuf = base64.b64encode(message.SerializeToString()).decode()
url = 'https://api.steampowered.com/IAuthenticationService/BeginAuthSessionViaCredentials/v1'
params = {
"input_protobuf_encoded": protobuf
}
response = requests.get(url, params=params, headers=headers)
return response.content
6. 关键点总结
- Protobuf消息定义:必须严格按照JS代码中的字段定义
- 序列化与编码:Protobuf序列化后需要Base64编码
- RSA加密:使用第一个接口返回的模数和指数构造公钥
- 设备信息:
device_details是自定义类型,需要根据实际情况定义 - 响应解析:使用对应的Protobuf消息类解析响应内容
7. 注意事项
- 本教程仅供学习交流使用
- 严禁用于商业用途和非法用途
- 实际实现时需要补充完整的字段定义
- 网站接口可能随时变更,需要动态调整
通过以上步骤,可以完整实现Steam登录的Protobuf协议逆向分析。实际应用中还需要处理加密、会话管理等其他细节。