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

爬虫逆向学习(十六):某方数据protobuf协议逆向解析

此分享只用于学习用途,不作商业用途,若有冒犯,请联系处理

某方数据protobuf协议逆向解析

  • protobuf
  • 站点信息
  • 发包研究
  • 反爬点定位
  • 请求体protobuf解析
  • 接口请求实现
  • 总结

protobuf

承接上文什么是protobuf?在Python中如何应用?,前面我们了解什么是protobuf以及它的相关应用,接下来我们来实战protobuf协议逆向解析。当然,在研究该站点前我也是阅读了其它相关资料,谨在此以自己的理解记录下逆向过程。

站点信息

  • 网站:aHR0cHM6Ly9kLndhbmZhbmdkYXRhLmNvbS5jbi9wZXJpb2RpY2FsL3dseGIyMDIzMDEwMDE=
  • 接口:aHR0cHM6Ly9kLndhbmZhbmdkYXRhLmNvbS5jbi9EZXRhaWwuRGV0YWlsU2VydmljZS9nZXREZXRhaWxJbkZvcm1hdGlvbg==

发包研究

我们复制接口的CURL包到postman请求,可以成功,然后转成python-requests请求也能拿到数据,通过调参可以确定该站点只有protobuf需要处理,没有其它明显的反爬。

在这里插入图片描述

其实看请求体和响应内容,如果业务对数据完整有太大要求,也可以不需要处理protobuf,提取需要的数据即可,像请求体直接替换参数,其它保持不变也能拿到数据。
在这里插入图片描述

反爬点定位

老操作,添加xhr断点,然后刷新页面,会在send时断住

在这里插入图片描述

然后看到调用堆栈,双击1处,之所以操作这里,是因为它很明显就是跟目标接口相关的

然后在2处加上断电,它也是跟目标接口相关的,而且大家看到serializeBinary没,这在上篇文章我们就讲过了,它就是protobuf的特征代码,所以这里大胆确定就是在这个JS文件进行的protobuf数据序列化与反序列化。

在这里插入图片描述

刷新界面断住后跟进去

在这里插入图片描述

看到这里就确定入口了,接下来只要跟着找到结构数据即可

在这里插入图片描述
在这里插入图片描述

请求体protobuf解析

对比上面两张图,第一张是目标站点的,第二张是上篇文章中我们生成的JS文件,通过它我们可以确定其基本结构如下:

在这里插入图片描述

继续跟下去,这里可以看出DetailInfoRequest定义了六个变量:

  • 序号为1、类型为String的resourcetype
  • 序号为2、类型为String的id
  • 序号为3、类型为String的referer
  • 序号为4、类型为String的md5id
  • 序号为5、类型为String的transaction
  • 序号为6、类型为Bool的isFetchAccountField

在这里插入图片描述
在这里插入图片描述

所以,proto文件结构如下:

在这里插入图片描述

这里我们需要验证一下结构是否准确,需要用到Fiddler抓包,它可以导出二进制文件,抓到包后,打开二进制数据,最下面黑色部分就是请求体的二进制数据

在这里插入图片描述

注意:就如下图中的 00 00 00 00 1B,这段校验和是不属于数据序列化后的字节,是后来加上去的,所以导出时不要选择这部分,不行会解析失败,然后右键选择红色框标注的操作然后保存为bin文件即可。

在这里插入图片描述

使用命令protoc.exe --decode_raw < post.bin可以查看实际数据,这里说一下,吐过出现下图问题,是因为用的是PowerShell窗口,需要使用cmd打开的命令行窗口

在这里插入图片描述

看打印结果只需要用到

看打印结果只需要用到前两个参数

在这里插入图片描述
逆向时不需要完全按照代码的来,只要满足需求即可,最终的.proto文件

在这里插入图片描述

接口请求实现

  • 将最终的.proto转成python代码
    protoc.exe --python_out=. Information.proto

  • 编写调用代码

    import Information_pb2 as pb
    
    
    detail_body = pb.DetailInfoRequest()
    
    detail_body.resourcetype = 'Periodical'
    detail_body.id = 'wlxb202301001'
    
    with open('me.bin', mode="wb") as f:
        f.write(detail_body.SerializeToString())
    print(detail_body.SerializeToString().decode())
    
    
  • bin文件对比
    两者生成结果一致
    在这里插入图片描述

  • 请求接口

    import requests
    
    import Information_pb2 as pb
    
    url = "url"
    detail_body = pb.DetailInfoRequest()
    
    detail_body.resourcetype = 'Periodical'
    detail_body.id = 'wlxb202301001'
    
    headers = {
        'accept': '*/*',
        'accept-language': 'zh-CN,zh;q=0.9',
        'content-type': 'application/grpc-web+proto',
        'origin': 'origin',
        'referer': 'referer',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
        'x-grpc-web': '1',
        'x-user-agent': 'grpc-web-javascript/0.1'
    }
    
    bytes_body = detail_body.SerializeToString()
    
    # 构造字节序列的头部
    bytes_head = bytes([0, 0, 0, 0, len(bytes_body)])
    print(bytes_head + bytes_body)
    
    resp = requests.post(url=url, data=bytes_head + bytes_body, headers=headers)
    
    print(resp.text)
    
    

    对比后确定与实际结果一致,这里请求就构建成功了。

    在这里插入图片描述

总结

暂时就到这里,还有响应结果需要处理,后续再讲解记录!!!


http://www.kler.cn/a/544245.html

相关文章:

  • 使用DeepSeek和Kimi快速自动生成PPT
  • 如何在 GitHub 上写博客
  • VSCode中出现“#include错误,请更新includePath“问题,解决方法
  • 进程状态
  • 详解信号量机制
  • 内网ip网段记录
  • untiy3D为游戏物体制作简单的动画
  • 提示词生成新方法,用Make自动化生成
  • MongoDB基础入门
  • Maven Profile 配置:支持不同环境的构建
  • 回环地址127.0.0.1跟自身IP有什么区别?
  • 简述MySQL主从复制原理及其工作过程,配置一主两从并验证
  • 订单自动关闭方案设计
  • 如何在Linux中设置定时任务(cron)
  • 使用 React 16+Webpack 和 pdfjs-dist 或 react-pdf 实现 PDF 文件显示、定位和高亮
  • 【C#零基础从入门到精通】(十一)——C#Reandom随机类详解
  • 1.攻防世界 unserialize3(wakeup()魔术方法、反序列化工作原理)
  • 2、k8s 二进制安装(详细)
  • 《qt open3d中添加随机点采样》
  • ubuntu部署snmp
  • 深入解析:如何利用期货Level2高频Tick数据洞察市场动态
  • 变形的宽搜 育才官网 HN036 涂色游戏
  • Windows中使用Docker安装Anythingllm,基于deepseek构建自己的本地知识库问答大模型,可局域网内多用户访问、离线运行
  • JVM 类加载子系统在干什么?
  • 后端程序如何应对流量激增
  • 5、《Spring Boot自动配置黑魔法:原理深度剖析》