当前位置: 首页 > news >正文

【万方数据】protobuf 逆向

在这里插入图片描述

1. 定位分析

在这里插入图片描述
可以看到 proto.SearchService.SearchRequest 是一个 Protocol Buffers (protobuf) 定义的对象。我们搜索的关键词,也就是请求体里面的“中药”在里面
在这里插入图片描述

  1. proto:通常表示这是一个 Protocol Buffers 的定义文件(.proto 文件)中的对象。
  2. SearchService:这是一个服务名称,定义在 .proto 文件中。服务定义通常包含一组 RPC(Remote Procedure Call)方法。
  3. SearchRequest:这是 SearchService 服务中的一个请求消息类型。它定义了客户端发送给服务端的数据结构。

2. 代码分析

e = (0, n.a)(e.getRequestMessage())
// 调用 n.a 方法处理 e.getRequestMessage() 的结果,得到一个新的字节数组
// 这里的e是长度为26的Uint8Arrayn = e.length
// 获取字节数组 e 的长度 这里等于26f = [0, 0, 0, 0]
// 初始化一个长度为 4 的数组 f,用于存储长度前缀。a = new Uint8Array(5 + n)
// 创建一个长度为 5 + n 的字节数组 a,其中前 5 个字节用于存储长度前缀。
// 这里的a是长度为31的Uint8Array数组,里面全是0// 然后f经过运算变为了[0, 0, 0, 26]
a.set(new Uint8Array(f), 1)
// 将 f 数组的内容复制到 a 的第 1 个位置开始的位置。
// 所以 a就变成了[0, 0, 0, 0, 26, 0, 0, ... , 0]a.set(e, 5)
// 将原始字节数组 e 的内容复制到 a 的第 5 个位置开始的位置
// 所以 a就变成了[0, 0, 0, 0, 26, 前面生成的e](e = a)
// 将 a 赋值给 e

这是前面的得到的26位Uint8Array
[10, 22, 10, 5, 112, 97, 112, 101, 114, 18, 6, 228, 184, 173, 232, 141, 175, 40, 1, 48, 20, 66, 1, 0, 16, 1]

在这里插入图片描述
这是请求体的hex
前面分析了前面4个都是0,第五个1A是其长度26
后面的hex字符串就是请求体参数
“0A 16 0A 05 70 61 70 65 72 12 06 E4 B8 AD E8 8D AF 28 01 30 14 42 01 00 10 01”

hex_str = "0A 16 0A 05 70 61 70 65 72 12 06 E4 B8 AD E8 8D AF 28 01 30 14 42 01 00 10 01"
e = [int(hex_value, 16) for hex_value in hex_str.split()]
print(e)
# 运行结果:[10, 22, 10, 5, 112, 97, 112, 101, 114, 18, 6, 228, 184, 173, 232, 141, 175, 40, 1, 48, 20, 66, 1, 0, 16, 1]

3. blackboxprotobuf解析

3.1 反序列化

import blackboxprotobuf# 给定的十六进制字符串
hex_string = "0A 16 0A 05 70 61 70 65 72 12 06 E4 B8 AD E8 8D AF 28 01 30 14 42 01 00 10 01"# 移除空格并将十六进制字符串转换为字节串
byte_string = bytes.fromhex(hex_string.replace(" ", ""))
print(byte_string)# 解析得到原始数据和消息类型
original_data, message_type = blackboxprotobuf.protobuf_to_json(byte_string)
print(original_data) # str类型
print(message_type) # dict类型

在这里插入图片描述

3.2 序列化

如何进行序列化呢?

import blackboxprotobuf# 给定的十六进制字符串
hex_string = "0A 16 0A 05 70 61 70 65 72 12 06 E4 B8 AD E8 8D AF 28 01 30 14 42 01 00 10 01"# 移除空格并将十六进制字符串转换为字节串
byte_string = bytes.fromhex(hex_string.replace(" ", ""))
print(byte_string)# 解析得到原始数据和消息类型
original_data, message_type = blackboxprotobuf.protobuf_to_json(byte_string)
print(original_data) # str类型
print(message_type) # dict类型# 序列化数据
form_data = bytes(blackboxprotobuf.encode_message(original_data, message_type))
print("序列化数据-->", form_data)

在这里插入图片描述
如果直接进行序列化,这样是会报错的,因为没有将数据和消息类型一一对应

{"1": {"1": "paper","2": "中药","5": "1","6": "20","8": "\u0000"},"2": "1"
}

这是反序列化之后的原始数据,其类型是str

{"1": {"type": "message","message_typedef": {"1": {"type": "bytes","name": ""},"2": {"type": "bytes","name": ""},"5": {"type": "int","name": ""},"6": {"type": "int","name": ""},"8": {"type": "bytes","name": ""}},"name": ""},"2": {"type": "int","name": ""}
}

这是其对应的消息类型

在这里插入图片描述

# 修改消息类型之后的数据
original_data = {"1": {"1": "paper","2": "中药","5": 1,"6": 20,"8": "\u0000"},"2": 1
}form_data = bytes(blackboxprotobuf.encode_message(original_data, message_type))
print("序列化数据-->", form_data)
print(len(form_data)) # 长度为26

4. 如何请求

import requests# 请求参数的十六进制字符串
hex_string = "00 00 00 00 1A 0A 16 0A 05 70 61 70 65 72 12 06 E4 B8 AD E8 8D AF 28 01 30 14 42 01 00 10 01"# 移除空格并将十六进制字符串转换为字节串
byte_string = bytes.fromhex(hex_string.replace(" ", ""))headers = {"content-type": "application/grpc-web+proto","user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
}url = "https://s.wanfangdata.com.cn/SearchService.SearchService/search"response = requests.post(url, data=byte_string, headers=headers)
print(response)
print(response.text)

在这里插入图片描述
得到的结果是序列化之后的数据


import blackboxprotobuf
import requests# 给定的十六进制字符串
hex_string = "0A 16 0A 05 70 61 70 65 72 12 06 E4 B8 AD E8 8D AF 28 01 30 14 42 01 00 10 01"# 移除空格并将十六进制字符串转换为字节串
byte_string = bytes.fromhex(hex_string.replace(" ", ""))
print(byte_string)# 解析得到原始数据和消息类型
original_data, message_type = blackboxprotobuf.protobuf_to_json(byte_string)
print(original_data) # str类型
print(message_type) # dict类型# 序列化数据
# 修改消息类型之后的数据
original_data = {"1": {"1": "paper","2": "中药","5": 1,"6": 20,"8": "\u0000"},"2": 1
}form_data = bytes(blackboxprotobuf.encode_message(original_data, message_type))
print("序列化数据-->", form_data) # b'\n\x16\n\x05paper\x12\x06\xe4\xb8\xad\xe8\x8d\xaf(\x010\x14B\x01\x00\x10\x01'
print(len(form_data))headers = {"content-type": "application/grpc-web+proto","user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
}url = "https://s.wanfangdata.com.cn/SearchService.SearchService/search"response = requests.post(url, data=bytes([0,0,0,0,len(form_data)]) + form_data, headers=headers)
print(response)# 反序列化响应结果
response_data, message_type = blackboxprotobuf.protobuf_to_json(response.content[5:])
print(response_data)

http://www.mrgr.cn/news/69052.html

相关文章:

  • 使用python编写工具:快速生成chrome插件相关文件结构
  • PyAEDT:Ansys Electronics Desktop API 简介
  • 自顶向下逐步求精解决LeetCode第3307题找出第K个字符II题
  • Axure网络短剧APP端原型图,竖屏微剧视频模版40页
  • SPIRiT-Diffusion:基于自一致性驱动的加速MRI扩散模型|文献速递-基于深度学习的病灶分割与数据超分辨率
  • ODC 如何精确呈现SQL耗时 | OceanBase 开发者工具解析
  • jdk 1.8新特性--接口增强
  • Node.js 常用工具util、文件系统使用介绍 (基础介绍 七)
  • C语言多维数组抽象理解:切格子思维
  • Go 中的泛型,日常如何使用
  • D63【python 接口自动化学习】- python基础之数据库
  • 随身 WiFi 锁频段、频点和小区提升网速
  • 24-11-9-读书笔记(三十二)-《契诃夫文集》(六)上([俄] 契诃夫 [译] 汝龙)药品是甜的,真理是美的,咖啡是苦的,生活是什么啊?
  • Linux 零拷贝技术
  • VScode中使用Cmake遇到的问题及其解决方法[最全+亲测有效]
  • 食品加工厂废水处理设备结构与功能
  • 【梯度下降法优化】随机梯度下降、牛顿法、动量法、Nesterov、AdaGrad、RMSprop、Adam
  • Chromium 中chrome.tabs扩展接口定义c++
  • 青少年编程与数学 02-003 Go语言网络编程 19课题、Go语言Restful编程
  • 自动驾驶系列—DAI起步提醒功能:让你不再错过每一个绿灯
  • C++入门基础(二)
  • STM32单片机WIFI语音识别智能衣柜除湿消毒照明
  • 共享汽车管理:SpringBoot技术实现指南
  • AP8106低电压升压芯片
  • 黄仁勋:AI数据中心可扩展至百万芯片 性能年翻倍,能耗年减2-3倍
  • 初始C++(下)-- 引用、内联函数、auto关键字、基于范围的for循环、空指针nullptr