【Web逆向】万方数据平台正文的逆向分析(上篇--加密发送请求)—— 逆向protobuf
【Web逆向】万方数据平台正文的逆向分析(上篇--加密发送请求)—— 逆向protobuf
- 声明
- 一、了解protobuf协议:
- 二、前期准备:
- 二、目标网站:
- 三、开始分析:
- 我们一句句分析:
- 先for循环部分:
- 后面就是给a赋值了:
- 四、写proto文件(核心)
声明
本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除!
一、了解protobuf协议:
Protobuf(Protocol Buffer)是 Google 开发的一套数据存储传输协议,为二进制序列化格式,可用作 JSON 或 XML 等格式的更有效替代方案。开发人员可以在 .proto 文件中定义消息格式,并使用 protobuf 编译器(protoc)按他们选择的语言生成消息处理程序。Protobuf 编码是二进制的,与 json、xml 不同,它不是可读的,也不容易手动修改。Protobuf 能够把数据压缩得很小,所以传输数据就比 xml 和 json 快几倍,使用其有利于提高效率,但同时增加了分析或修改数据的难度。
序列化 (Serialization) 是指将对象转换为字节序列的过程,在序列化期间,对象将其当前状态写入到临时或持久性存储区,以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
二、前期准备:
下载protoc文件:找对应版本下载
然后添加到环境变量,便于之后使用。
二、目标网站:
基于矢量光场空间调制的光波偏振方向解算方法研究
打开网站,找到我们这次需要分析的包。
返回数据也是乱码:
经过查资料,观察返回的content-type为application/grpc-web+proto 是以protobuf数据结构传输的。
我们用fiddler抓包,过滤掉png和js,只显示主机是d.wanfangdata.com.cn;的
可以看到getDetailInFormation发送的十六进制数据,黑色16进制数据是发送的数据,蓝色是请求头数据:
我们把黑色部分从第六位起(也就是0A)保存为bin文件,如下图:
三、开始分析:
我们下个xhr断点看看,看看数据是怎么来的。
可以看到数据是以字节集的形式发出的,与上面fd抓包的16进制数据是一一对应的。
接下来,我们看看数据是怎么来的?跟e来到上一个栈,可以发现是a赋值给e的。
我们在e赋值的地方下断点,看看a怎么来的,重新调试一次,主要看a怎么构成的。
发现其实核心就是10406行到10415行赋值这一段。
for (n = (e = (0,n.a)(e.getRequestMessage())).length,l = [0, 0, 0, 0],a = new Uint8Array(5 + n),s = 3; 0 <= s; s--)l[s] = n % 256,n >>>= 8;
if (a.set(new Uint8Array(l), 1),a.set(e, 5),e = a,
我们一句句分析:
先for循环部分:
e = (0,n.a) (e.getRequestMessage())
得到的是一个unit8Array数组,刚刚好就是我们刚才排查出发包的数据从5开始往后数。
n = (e = (0,n.a)(e.getRequestMessage())).length
这里得到这个数组长度是27。
f = [0, 0, 0, 0]
这里类似设置了一个头,4位空数组
a = new Uint8Array(5 + n)
这里a的初始化,因为我们知道最后a是一个Uint8Array的数组,他的长度是5+n。
s = 3; 0 <= s; s--
这里可以确定整个循环的次数,4次。
因为js是以;为结束的,所以相当于下列语句循环了4次,那这步操作是干嘛的呢?
f[s] = n % 256,
n >>>= 8;
给f数组各位赋值的,刚刚好f数组就是4位。所以说先给f的第四位赋值相当于f[3], 再 n进行>>>=移位操作,得到:
f[3] =27%256=27 27 >>>8=0 =>n=0
f[2] = 0%256 =0 0 >>>8=0 =>n=0
f[1] = 0%256 =0 0 >>>8=0 =>n=0
f[0] = 0%256 =0 0 >>>8=0 =>n=0
f=[0, 0, 0, 27]
后面就是给a赋值了:
a.set(new Uint8Array(f), 1)
a是数组,然后查mdn文档,可知set方法的作用:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set
set()
方法用于从指定数组中读取值,并将其存储在类型化数组中。
有两个参数,typedarray,offset(可选,默认为 0)
typedarray对应 new Uint8Array(f)
offset 对应 1
相当于从下标1开始,给a数组插入值f。
所以得到
这里核心就是这个set方法,不懂查一下就理解了。
a.set(e, 5)
相当于从数组下标5开始把e的值赋值给a
ok,我们到这里已经把a怎么来的理解清楚了,也明白了前面5位是怎么来的。
但是,我们还是没接触到protobuf
啊,只是知道了数据得到的大概过程。核心就在(0,n.a)(e.getRequestMessage())
里面。
四、写proto文件(核心)
跟进n.a方法
发现了写protobuf数据格式的关键函数:serializeBinary
关键点:
根据serializeBinaryToWriter关键函数,可以得到此结构分层,跟进去可以得到包含几个信息
write + (信息类型)函数,第一个参数代表是第几个。(如下图圈主部分)
看到writeMessage,后面有serializeBinaryToWriter关键函数,跟进去,就能再次得到此message的结构层次,一样分析,就能得出完整结构。
一个个分析按顺序写proto文件
syntax = "proto3";message SearchService {string getResourcetype = 1;string getId = 2;string getReferer = 3;string getMd5id = 4;string getTransaction = 5;
}
命令行生成可python操作的protobuf文件
数据分析:fd抓包下载bin,然后命令行 protoc --decode_raw < test.bin执行,解析protobuf数据结构
然后对应上面的结构找到对应变量,用python赋值运行:
import test_pb2 as pbSearchRequest = pb.SearchService()
SearchRequest.getResourcetype = 'Periodical'
SearchRequest.getId = 'wlxb202301001'
SearchRequest.getReferer = ''
SearchRequest.getMd5id = ''
SearchRequest.getTransaction = ''
form_data = SearchRequest.SerializeToString()
print(form_data)
我们验证一下上面输出是否正确,用blackboxprotobuf
模块解析,即可看到原始数据(这里用到上面解析出来的bin文件):
import blackboxprotobuf# 1、得到消息类型message_type
with open(r"test.bin", "rb") as fp:data = fp.read()deserialize_data, message_type = blackboxprotobuf.protobuf_to_json(data)print(f"原始数据: {deserialize_data}")print(f"消息类型: {message_type}")# str 转 dictdeserialize_data = eval(deserialize_data)form_data = bytes(blackboxprotobuf.encode_message(deserialize_data, message_type))print(form_data)
和咱们用proto文件编译出来protobuf文件去解析的输出一样,所以咱们编译没问题!
用python发包,根据上面的分析,发现需要补头5位
bytes_head = bytes([0, 0, 0, 0, len(form_data)])
完整代码(获得数据):
import test_pb2 as pbSearchRequest = pb.SearchService()
SearchRequest.getResourcetype = 'Periodical'
SearchRequest.getId = 'wlxb202301001'
SearchRequest.getReferer = ''
SearchRequest.getMd5id = ''
SearchRequest.getTransaction = ''
form_data = SearchRequest.SerializeToString()
print(form_data)
print(len(form_data))
bytes_head = bytes([0, 0, 0, 0, len(form_data)])
print(bytes_head + form_data)
header = {"Accept": "*/*","Accept-Language": "zh-CN,zh;q=0.9,zh-TW;q=0.8","Content-Type": "application/grpc-web+proto","Origin": "https://s.wanfangdata.com.cn","Referer": "https://d.wanfangdata.com.cn/periodical/wlxb202301001","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
}url = 'https://d.wanfangdata.com.cn/Detail.DetailService/getDetailInFormation'
res = requests.post(url, data=bytes_head + form_data, headers=header)
print(res.content)
发送请求后返回的数据:
相关文章:

【Web逆向】万方数据平台正文的逆向分析(上篇--加密发送请求)—— 逆向protobuf
【Web逆向】万方数据平台正文的逆向分析(上篇--加密发送请求)—— 逆向protobuf声明一、了解protobuf协议:二、前期准备:二、目标网站:三、开始分析:我们一句句分析:先for循环部分:后…...

Amazon S3 服务15岁生日快乐!
2021年3月14日,作为第一个发布的服务,Amazon S3 服务15周岁啦!在中国文化里,15岁是个临界点,是从“舞勺之年”到“舞象之年”的过渡。相信对于 Amazon S3 和其他的云服务15周岁也将是其迎接更加美好未来的全新起点。亚…...

【python】函数详解
注:最后有面试挑战,看看自己掌握了吗 文章目录基本函数-function模块的引用模块搜索路径不定长参数参数传递传递元组传递字典缺陷,容易改了原始数据,可以用copy()方法避免变量作用域全局变量闭包closurenonlocal 用了这个声明闭包…...
AoP-@Aspect注解处理源码解析
对主类使用EnableAspectJAutoProxy注解后会导入组件, Import(AspectJAutoProxyRegistrar.class) public interface EnableAspectJAutoProxy {AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口中的registerBeanDefinitions()方法,此…...

宝塔搭建实战php悟空CRM前后端分离源码-vue前端篇(二)
大家好啊,我是测评君,欢迎来到web测评。 上一期给大家分享了悟空CRM server端在宝塔部署的方式,但是由于前端是用vue开发的,如果要额外开发新的功能,就需要在本地运行、修改、打包重新发布到宝塔才能实现功能更新&…...

FastASR+FFmpeg(音视频开发+语音识别)
想要更好的做一件事情,不仅仅需要知道如何使用,还应该知道一些基础的概念。 一、音视频处理基本梳理 1.多媒体文件的理解 1.1 结构分析 多媒体文件本质上可以理解为一个容器 容器里有很多流 每种流是由不同编码器编码的 在众多包中包含着多个帧(帧在音视…...
二分查找的实现代码JAVA
二分查找一、思路二、实现代码(普通版)三、整数溢出问题四、改进代码一、思路 1.前提: 有已排序数组A (假设已经做好) 2.定义左边界L、 右边界R,确定搜索范围,循环执行二分查找(3、4两步) 3.获取中间索引 M Floor((LR) 1/2) 4.中间素索引的值…...

cesium: 设置skybox透明并添加背景图 ( 003 )
第003个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置skybox透明并添加背景图。 我们不想要黑乎乎的背景,想自定义一个背景图,然后前面显示地球。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共70…...

【python】类的详解
注:最后有面试挑战,看看自己掌握了吗 文章目录PO verses OOPOOO当一个类很复杂的时候,考虑多弄一个类的改造私有类的模块化静态类verses动态类动态类查看模块源代码对象机制的基石 PyObjectPO verses OO PO PO耦合性高,很多过程…...

西安银行就业总结
引 进银行性价比最高的时刻是本科,研究生的话可以去需要研究生较多的银行,比如邮储或者证券类的中信建投。中信建投很香,要求本硕西电。研究生学历的话,一般情况下银行不会卡本科,只看最高学历,部分银行需…...

JavaScript Window
文章目录JavaScript Window浏览器对象模型 (BOM)Window 对象Window 尺寸其他 Window 方法JavaScript Window 浏览器对象模型 (BOM) 使 JavaScript 有能力与浏览器"对话"。 浏览器对象模型 (BOM) 浏览器对象模型(Browser Object Model (BOM))…...

那些开发过程中需要遵守的开发规范
入职公司三天,没干啥其他活,基本在配置本地环境和阅读相关文档。技术方面公司基本用的是主流的技术体系,入职后需要先阅读阿里的开发规范和其他的一些产研文档。今天整理一些平时需要关注的阿里规约和数据库开发规范,方便今后在开…...
EFCore 基础入门教程
一、EFCore 基础入门教程EF 框架的简介、发展历史;ORM框架概念学习地址:https://blog.csdn.net/u011127019/article/details/129212786?spm1001.2014.3001.5502EFCore 安装,引入、支持的数据库学习地址:https://www.cnblogs.com/…...

HTML5 Drag and Drop
这是2个组合事件 dom对象分源对象和目标对象 绑定的事件也是分别区分源对象和目标对象 事件绑定 事件顺序 被拖拽元素,事件触发顺序是 dragstart->drag->dragend; 对于目标元素,事件触发的顺序是 dragenter->dragover->drop/…...

惠普m1136打印机驱动程序安装教程
惠普m113打印机是一款功能强大的多功能打印机,它能够打印、复印、扫描和传真等。如果你要使用这款打印机,你需要下载并安装驱动程序,以确保它能够在你的计算机上正常工作。在本文中,我们将介绍如何下载和安装惠普m1136打印机驱动程…...

数据增强,扩充了数据集,增加了模型的泛化能力
数据增强(Data Augmentation)是在不实质性的增加数据的情况下,从原始数据加工出更多的表示,提高原数据的数量及质量,以接近于更多数据量产生的价值。 其原理是,通过对原始数据融入先验知识,加工…...

MySQL/Oracle获取当前时间几天/分钟前的时间
获取当前时间 要想获取当前时间几天/分钟前的时间,首先要知道怎么获取当前时间; 对于MySQL和Oracle获取当前时间的方法是不一样的; MySQL: select NOW(); 示例: Oracle: select sysdate from dual; 示…...

如何在Wordpress中使用wp_nav_menu()在<li>及a标记中添加Class
我正在使用wp_nav_menu($args),我想将my_own_classCSS类名添加到<li>元素中以获得以下结果:<li classmy_own_class><a href>Link</a>怎么做?wp_nav_menu()在<li>标记中添加Class方法一:只需使用其他参数并为nav_menu_css_…...

Chat Support Board WordPress聊天插件 v3.5.8
功能列表 支持和聊天功能 Slack聊天完全同步 - 直接从Slack发送和接收用户信息。 立即工作 - 只需插入短码,即可立即安装和使用。 丰富的信息 - Dialogflow机器人发送丰富的信息。 机器人--集成一个由API.AI驱动的多语言机器人。 电子邮件通知 - 当收到回复时&#…...

2022年网络安全竞赛——数字取证调查attack.pcapng
攻击日志分析:需求环境可私信博主获取 任务环境说明: 服务器场景:PYsystem0031服务器场景操作系统:未知服务器场景FTP用户名:anonymous 密码:空从靶机服务器的FTP上下载attack.pcapng数据包文件,通过分析数据包attack.pcapng,找出黑客的IP地址,并将黑客的IP地址作为FL…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...