某站弹幕Protobuf协议逆向分析

2023-11-15

​一杯敬明天,一杯敬过往。大家好,我是TheWeiJun,时间过得好快,转眼间春节已过,此刻大家都已经开始复工了吧!首先祝大家新年快乐、2023年一路旺旺旺。小编也是心情激动,才有了前面的开场白。直入主题:今天给大家带来某站弹幕protobuf协议逆向分析,全程高能,在阅读的同时不要忘记点赞+关注哦⛽️

特别声明:本公众号文章只作为学术研究,不用于其它不法用途;如有侵权请联系作者删除。

立即加星标

每天看好文

 目录

一、前言介绍

二、网站分析

三、Protobuf协议还原

四、完整代码实现

五、思路总结


新年展望

这是本公众号2023年的第一篇文章,今天写这篇文章是为了解决某个粉丝提到的问题:如何实现某站弹幕protubuf协议还原,最好是用Go语言去实现。小编看到粉丝提到的问题故写了这篇文章分享给各位,希望对大家提高技术有一定的帮助。然后给大家分享一个好消息,经过2022年坚持不懈的努力,作者创作了32篇文章,官方给予作者科技自媒体黄标认证。能拿到这个官方认证,我要感谢各位粉丝的陪伴和鼓励。也感谢对TheWeiJun提供技术指导的朋友,希望大家在2023年技术能更上一层楼⛽️。黄标公众号如下:

逆向与爬虫的故事

专注于网络爬虫、JS逆向、APP逆向、安全攻防实战经验分享及总结。

公众号


一、前言介绍

什么是protobuf协议?

前言:Protobuf (Protocol Buffers) 是谷歌开发的一款无关平台,无关语言,可扩展,轻量级高效的序列化结构的数据格式,用于将自定义数据结构序列化成字节流,和将字节流反序列化为数据结构。所以很适合做数据存储和为不同语言,不同应用之间互相通信的数据交换格式,只要实现相同的协议格式,即后缀为proto文件被编译成不同的语言版本,加入各自的项目中,这样不同的语言可以解析其它语言通过Protobuf序列化的数据。目前官方提供c++,java,go等语言支持。


二、网站分析

1、首先打开我们本次分析的网站,搜索指定弹幕内容,截图如下图所示:

环节说明由于弹幕内容使用了protobuf协议,所以无法直接搜索定位,我们需要分析response数据包请求,去定位具体的url链接。

2、分析Response数据包请求,定位到弹幕链接,截图如下所示:

环节说明:从截图中我们可以清楚看出,这就是弹幕的内容。但是毕竟该网站使用了protobuf协议编码,如果我们想还原出明文信息,接下来需要去进行JS断点调试分析了。

3、使用xhr/fetch对该请求打断点调试,截图如下图所示:

环节说明因为该请求是对response进行了protobuf协议编码,所以我们定位到该请求发包位置后,只需要关注后面的协议解码逻辑即可实现明文信息还原。

4、打好断点后,点击操作按钮,截图如下图所示:

说明:此刻r变量即为我们要访问的弹幕url地址,定位到url地址后,我们需要接下来继续执行断点进行跟栈。

5、继续执行断点,持续调式,截图如下图所示:

5.1、此刻我们打印变量r的值,截图如下所示:

说明:这不就是我们想要的明文信息么?接下来,我们只需要找到protobuf协议初始化参数id定义就可以还原明文了。

6、经过JS断点调试,最终定位到protobuf协议初始化参数如下:

7、将Console中的数据复制后进行JSON在线格式化解析,截图如下:

总结:知道response明文及protobuf协议定义的参数规则后,接下来我们只需要构建protoc文件即可完成对整个弹幕明文信息的还原。


三、Protobuf协议还原

1、还原protobuf协议,编辑go语言protobuf代码结构如下:

2、执行如下命令,编译为golang protobuf可执行文件:

protoc  --go_out=. *.proto

3、运行以上命令后,生成.pb.go代码文件,截图如下图所示:

总结:走到这里protobuf协议就完全还原了,接下来让我们进入完整go代码实现环节吧。


四、完整代码实现

1、整个项目完整代码如下:

package main
​
import (
  "fmt"
  "github.com/golang/protobuf/proto"
  resp "hello/bilibili"
  "io/ioutil"
  "log"
  "net/http"
)
​
func main() {
  client := &http.Client{}
  req, err := http.NewRequest("GET", "https://xxxx/x/v2/dm/web/seg.so?type=1&segment_index=1", nil)
  if err != nil {
    log.Fatal(err)
  }
  req.Header.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36")
  req.Header.Set("accept", "*/*")
  req.Header.Set("accept-language", "zh-CN,zh;q=0.9")
  req.Header.Set("cache-control", "no-cache")
  req.Header.Set("origin", "https://www.xxxx.com")
  req.Header.Set("pragma", "no-cache")
  req.Header.Set("sec-ch-ua-mobile", "?0")
  req.Header.Set("sec-ch-ua-platform", `"macOS"`)
  req.Header.Set("sec-fetch-dest", "empty")
  req.Header.Set("sec-fetch-mode", "cors")
  req.Header.Set("sec-fetch-site", "same-site")
  resp, err := client.Do(req)
  if err != nil {
    log.Fatal(err)
  }
  defer resp.Body.Close()
  bodyText, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Fatal(err)
  }
  processBody(bodyText)
}
​
func processBody(body []byte) {
  response := resp.Feed{}
  err := proto.Unmarshal(body, &response)
  if err != nil {
    log.Fatal(err)
  }
  messages := response.Message
  for _, message := range messages {
    fmt.Println(message.Content, message.IdStr)
  }
}

2、代码编辑完毕后,我们运行代码,截图如下图所示:


五、思路总结

回顾整个分析流程,本次难点主要概括为以下几点:

  • 如何快速定位加密协议的位置

  • 了解并熟练掌握protobuf协议

  • 能够通过源码还原proto文件

  • 如何在golang中使用protobuf

今天分享到这里就结束了,欢迎大家关注下期文章,我们不见不散⛽️


  往期回顾

▶ 某游戏社区App | So层逆向分析

▶ 某容器管理平台模拟登录(Go语言版本)

▶ 某麦最新analysis算法逆向分析(多种语言实现)

▶ B站弹幕protobuf协议还原分析

▶ GoLang - colly爬虫框架


    我是TheWeiJun,有着执着的追求,信奉终身成长,不定义自己,热爱技术但不拘泥于技术,爱好分享,喜欢读书和乐于结交朋友,欢迎加我微信与我交朋友。

    分享日常学习中关于爬虫、逆向和分析的一些思路,文中若有错误的地方,欢迎大家多多交流指正☀️

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

某站弹幕Protobuf协议逆向分析 的相关文章

  • 练习:网络爬虫 - 并发不起作用

    我正在经历 golang 之旅 并致力于最后的练习 以将网络爬虫更改为并行爬行而不是重复爬行 http tour golang org 73 http tour golang org 73 我所改变的只是抓取功能 var used make
  • 复制切片的通用方法

    我需要复制切片 以及底层数组的一部分 以便调用者不会改变数组的原始元素 我想我可以编写一个函数来对特定类型的数组执行此操作 func duplicateSliceOfSomeType sliceOfSomeType SomeType Som
  • Go(lang): 如何使用 PPROF 堆分析来查找内存泄漏?

    我正在尝试使用 pprof 来验证内存泄漏 能否解释一下如何读取您在以下位置找到的堆配置文件 http localhost 6060 debug pprof heap debug 1 另外 通过键入web启动后命令go tool pprof
  • 指定共享对象(共享库)的名称

    Go 编译器为共享对象生成的名称是错误的 例子 go install buildmode shared linkshared github com apache thrift lib go thrift code google com p
  • 如何在 Go 中解组可以是数组或字符串的字段?

    我正在尝试解组该文件 babel email protected cdn cgi l email protection licenses MIT repository https github com babel babel tree ma
  • 为什么这里会出现僵局

    我想了解 golang 通道是如何工作的 我读了一本关于go语言的书 发现了下面的例子 package main import fmt Send the sequence 2 3 4 to returned channel func gen
  • 使用反射从泛型结构获取类型参数

    想象一下我有以下结构 type MyGeneric T string int struct 我想在创建新的 MyGeneric 时检查用于实例化该结构的泛型是字符串还是 int myGenericString MyGeneric strin
  • 是否可以从 JS 显式调用导出的 Go WebAssembly 函数?

    是否可以调用 Go WebAssembly 函数 除了main 在 JavaScript 中 让我先展示一下我做了什么 我的Go函数定义如下 package main import fmt func main fmt Println it
  • 尝试创建问题时 GitHub API 422 出现意外错误响应

    当向 GitHub API V3 发布问题时 我收到了意外的响应 即422不可处理的实体 但是 错误的详细信息是针对搜索端点的 而不是针对 POST 创建端点的 message 验证失败 errors resource 搜索 field q
  • 切片文字中的求值顺序

    我最近浏览了Go的 语言规范 https golang org ref spec Order of evaluation https golang org ref spec Order of evaluation但发现评估顺序与本文档中解释
  • golang 范围内的指针不起作用

    为什么结果是A 1 A 2 A 2 not A 1 A 2 A 3 我们不能在范围内使用指针吗 这是代码 我设置了一个指针 指向范围循环 但它失败了 package main import fmt type A struct Barry B
  • 从恐慌中恢复的程序未按预期退出

    根据我的理解 当恐慌恢复时 我期望程序退出并表现出正常行为 但事实并非如此 我期望最后一行打印 程序结束 是正确的吗 如果出现运行时错误 它不会被打印 是吗 package main import fmt func main defer f
  • 重写 ResponseWriter 接口以捕获 HTTP 错误

    我正在用 Go 编写一个 Web 应用程序 虽然各种 mux 库提供了一种设置自定义 404 错误处理程序的方法 但没有任何其他 4xx 和 5xx 错误代码 一个建议是重写 ResponseWriter 接口中的 WriteHeader
  • 从 C 调用带有字符串参数的 Go 函数?

    我可以从 C 调用一个没有参数的 Go 函数 按照下面的 https github com joeprivacy crefgo hello world 这通过编译go build和打印 Hello from Golang main func
  • Go1编译器如何工作?

    我在一个学校项目中接触 Go 大约一个月了 我注意到 src pkg go 文件夹中的 go ast go token go parser 等包 但是 gc 编译器基于位于 src cmd gc 中的 C 文件 我的问题是关于 Go1 中用
  • Go 中的格式错误 - %s %v 或 %w

    s v and w可用于格式化 Go 中的错误 将它们转换为字符串 fmt Errorf 它们在 Go 自己的工具中的使用方式似乎有所不同 In cmd go internal get path go https github com go
  • 如何获取字段类型的零值

    我有一个包含许多字段的结构 我已经弄清楚如何使用反射提取字段名称 值和标签信息 我还想做的是确定字段的值是否与字段的默认值不同 目前 我有这个 有效 但有点臭 qsMap make map string interface var defa
  • ConstantTimeByteEq 如何工作?

    在大神的密码库里 找到了这个函数ConstantTimeByteEq http golang org src pkg crypto subtle constant time go s 897 936 L17 它有什么作用 如何工作 Cons
  • 空或不需要的结构字段

    我有两个结构体 代表将插入到 mongodb 数据库中的模型 一个结构 投资 将另一个结构 集团 作为其字段之一 type Group struct Base Name string json name bson name type Inv
  • mysql 查询中的 golang 切片,带有 where in 子句

    我正在运行以下查询 但只获取第一个 id 值 select from table where table id in 1 2 3 4 5 6 7 9 11 13 14 15 17 and table deleted at is null 我

随机推荐

  • nvidia tx/xavier/orin硬件平台上添加开机启动程

    概述 随着NVIDIA的xavier及orin系列硬件平行推出 自动驾驶车端处理器也逐渐频繁开发及使用 开机脚本使用 etc profile 通常在系统登录时 会执行 多次登录 多次执行 xavier上增加开机启动脚本 不能在 etc pr
  • 记录解压zip文件

    zip文件有30G unzip不能用 改用jar解压 unzip 解压 JPEGImages zip 文件时 异常提示如下 Archive dataset test rgb zip End of central directory sign
  • 隐藏Chrome浏览器新增标签页下方的快捷方式缩略图

    作为强迫症患者不喜欢搜索栏下方还有多余的东西 看着8个最近访问的快捷方式缩略图太不舒服了 在网上搜索了一堆方法 最有效的是替换一个PAK文件 但是过程有些繁琐 自己摸索后发现了一个简单的方法 在这记录一下以防自己忘记 查看设置中搜索引擎的地
  • 8种常见的排序算法-----你值得掌握(很细,很全)

    目录 一 排序的概念 二 常见的排序 三 常见排序算法的实现 1 插入排序 1 1 基本思想 1 2直接插入排序动态图 1 3直接插入排序的代码实现 2 希尔排序 2 1基本思想 2 2希尔排序过程 2 3希尔排序代码实现 2 4gap的选
  • CVPR2019接收结果公布了,但CVPR 2018的那些论文都怎么样了?

    CVPR 作为计算机视觉三大顶级会议之一 一直以来都备受关注 被 CVPR 收录的论文更是代表了计算机视觉领域的最新发展方向和水平 今年 CVPR 2019 将于美国洛杉矶举办 上个月接收结果公布后 又引起了 CV 届的一个小高潮 一时间涌
  • arxiv文章下载

    使用中科院arxiv的镜像地址 http xxx itp ac cn 地址由 https arxiv org pdf 1512 02325 pdf 切换到 http xxx itp ac cn pdf 1512 02325 pdf
  • 异步通知实验(信号)

    目录 异步通知 异步通知简介 驱动中的信号处理 应用程序对异步通知的处理 硬件原理图分析 实验程序编写 修改设备树文件 程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 在前面使用阻塞或者非阻塞的方式来读取驱动中按键值
  • 单片机知识总结,51中断秘籍(外部中断,定时器中断,定时器计数),串口通信秘籍【1000字】【原创】

    文章目录 1 普中科技开发板 2 中断寄存器配置详解 截图 3 中断寄存器配置文字总结 4 文字总结2 5 文字总结3 6 代码函数示例 1 外部中断0初始化函数 2 外部中断1初始化函数 3 定时器中断0初始化函数 4 定时器中断1初始化
  • 大语言模型之一 Attention is all you need ---Transformer

    大语言模型已经在很多领域大显身手 其应用包括只能写作 音乐创作 知识问答 聊天 客服 广告文案 论文 新闻 小说创作 润色 会议 文章摘要等等领域 在商业上模型即产品 服务即产品 插件即产品 任何形态的用户可触及的都可以是产品 商业付费一般
  • 性能:15个JavaScript本地存储技术的函数库和工具

    当构建更复杂的JavaScript应用程序运行在用户的浏览器是非常有用的 它可以在浏览器中存储信息 这样的信息可以被共享在不同的页面 浏览会话 在最近的过去 这将有可能只被cookies文本文件保存到用户的计算机 管理这些JavaScrip
  • 手把手实战react + storybook组件库

    引入 在UI组件库的开发过程中 如何方便的展示组件 测试组件 编写文档呢 storybook就提供了这样一种工具 利用它我们可以更方便地进行UI组件开发 最近一直在研究react react和storybook的碰撞会是怎么样的呢 下面将从
  • 防止内卷和被潜规则,Spring Cloud Alibaba微服务架构实战派(上下册)|35岁程序员那些事

    目录 1 写书缘由 2 本书上册核心内容 2 1 Spring Cloud Alibaba基础实战 2 1 1 主要内容 2 1 2 MyBatis Plus实现多租户架构的核心原理 2 2 分布式服务治理 基于Nacos 2 2 1 主要
  • unity资源商店出现“抱歉,此链接不再有效”怎么办

    首先 返回资源商店首页 登录自己的账号就可以了
  • 解决room重复插入数据

    我设置的是消息时间为主键 消息时间 NonNull PrimaryKey private String messageTime 插入的时候如果重复则替换 Insert onConflict OnConflictStrategy REPLAC
  • visual basic_什么是Visual Basic?

    visual basic In 2008 Microsoft stopped support for VB and declared it a Legacy software Feel free to read this article w
  • SQL server 查汉字和字符长度

    len 一个汉字 一个字符 SELECT len 喷涂黑 喷涂黑 显示为 datalength 一个汉字 两个字符 SELECT datalength 喷涂黑 喷涂黑 显示为
  • vue虚拟列表实现原理

    vue中实现一个虚拟列表 应用场景 前端的业务开发中会遇到不使用分页方式来加载长列表的需求 如在数据长度大于 1000 条情况 DOM 元素的创建和渲染需要的时间成本很高 完整渲染列表所需要的时间不可接受 同时会存在滚动时卡顿问题 解决该卡
  • iOS14 修改启动视图为全屏模式

    iOS14里面启动一个视图其会默认以非全屏模式打开 有些时候需要全屏展示 该如何修改 修改示例 let secondVC SecondViewController secondVC modalPresentationStyle fullSc
  • linux之安装Apache服务

    1 在镜像中查找web服务 2 安装web服务 3 关闭防火墙和selinux 4 启动服务 5 测试服务 6 配置文件 292行 302行 402行 7 创建文件并进入 8 配置wyg文件 9 重启服务 查看服务
  • 某站弹幕Protobuf协议逆向分析

    一杯敬明天 一杯敬过往 大家好 我是TheWeiJun 时间过得好快 转眼间春节已过 此刻大家都已经开始复工了吧 首先祝大家新年快乐 2023年一路旺旺旺 小编也是心情激动 才有了前面的开场白 直入主题 今天给大家带来某站弹幕protobu