某某 App protobuf 协议逆向分析

这是「进击的Coder」的第 771 篇技术分享

作者:TheWeiJun

来源:逆向与爬虫的故事

阅读本文大概需要 5 分钟。

     大家好,我是 TheWeiJun。前期发布的两篇某大厂的文章因为收到律师函,作者已经对文章进行删除。今天我们分享一个 protobuf 协议逆向分析,教你如何在无结构的数据中抽取并定义 proto 文件。各位读者在阅读的同时不要忘记点赞+关注哦⛽️

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

14a8cb53290c4dee537bde29826ef4d8.gif

 目录


一、什么是 protobuf?

二、protobuf 堆栈结构

三、proto 定义及编译

四、完整代码实现

五、心得分享及总结


趣味模块

      小明是一名爬虫开发工程师,自从上次小明解决了字体反爬、websocket 协议、B 站 protobuf 协议后,小明一直所向披靡,过五关斩六将,在一个多月的时间里一直没有遇到过有难度的问题。但是今天,小红遇到了某某 App 端的 protobuf 协议加密,不再是js端一样去找定义的类型 id 了。那么今天我们去分析下小红同学遇到的新问题吧,如何通过无结构定义 proto 文件并还原某某 App 的 protobuf 协议!


一、什么是 protobuf 协议?

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


二、protobuf 堆栈输出

1、首先从charles应用中保存我们抓到的某某App数据包,截图如下所示:

e4c97633c168520b242c7bca9eace790.png

2、使用 Postman 访问协议接口,将 response 响应内容保存为 .bin 格式文件,截图如下所示:

93ab58d2e1e1c7dd240133a566cec155.png

3、使用 protobuf_inspector python 第三方包打印 protobuf 文件堆栈信息,截图如下所示:

b9a8eb98ab84eda96d63e1facf4b7a03.png

总结:打印 protobuf 数据堆栈信息后,接下来我们只需要根据打印的堆栈信息定义 proto id 类型文件并编译为 python 可执行文件即可完成对某某 App protobuf 协议还原。


三、proto 文件定义及编译

1、通过分析打印的堆栈信息,确定我们本次要提取的文字内容,截图如下所示:

cdc1b39b48f3d1d2463ad0ac89082222.png

2、确定我们要提取的文字内容后,定义 proto 文件格式,定义后的结构体如下所示:

syntax = 'proto3';
message DanMo{


  message Message{
    int32 id = 1;
    int32 time = 8;
    string content = 7;
  }


  repeated Message message = 1;
}

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

protoc  --python_out=. *.proto

4、运行命令后,生成 python protobuf py 文件,截图如下所示:

d68681402a64ce4382b93b2dfc90293f.png

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


四、完整代码实现

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

from google.protobuf.json_format import MessageToDict
from danmo_pb2 import DanMo




with open('test.bin', 'rb') as f:
    _info = DanMo()
    _info.ParseFromString(f.read())
    _data = MessageToDict(_info, preserving_proto_field_name=True)
    items = _data.get("message", [])
    for item in items:
        _id = item.get("id")
        _time = item.get("time")
        content = item.get("content")
        print(_time, content, _id)

2、代码编写完成后,我们运行代码,代码输出截图如下所示:

ba6383cd5753b5918e45baf89edb18a0.png



五、心得总结分享

      通过本次案例分享,我发现有些技术不是难,而是没有找到好的方案去解决;有的问题需要思考 3 个小时甚至更久,但是解决只需要 10 分钟。今天分享到这里就结束了,欢迎大家关注下期文章,我们不见不散⛽️

23b43be7c4197cb5e5aca1ebef5f5974.png

End

崔庆才的新书《Python3网络爬虫开发实战(第二版)》已经正式上市了!书中详细介绍了零基础用 Python 开发爬虫的各方面知识,同时相比第一版新增了 JavaScript 逆向、Android 逆向、异步爬虫、深度学习、Kubernetes 相关内容,‍同时本书已经获得 Python 之父 Guido 的推荐,目前本书正在七折促销中!

内容介绍:《Python3网络爬虫开发实战(第二版)》内容介绍

c6639aee70cb1183b89768b26e7eab90.jpeg

扫码购买

778657e54d89445187ae789525b328e5.png

3ab42a2bf6a11925f2b15319e4fc68b1.png

点个在看你最好看

outside_default.png

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值