抓包+逆向app分析protobuf

万事俱备,只欠东风。
前面的实验环境已经搭好了。下面来抓包分析下,看看protobuf协议在抓包软件上长什么样子。

首先明确我们的目标。我们的最终目标是还原proto文件,有了这个文件,我们就能对数据做序列化和反序列化,最终用python请求和解析数据。

1.抓包分析

拿到一款app(前面的demo),首先抓包

如果协议头是application/x-protobuf,那么charles可以大致解析出来响应的文本,甚至可以看到序号以及类型。注意这个前面的1,2,3不是charles自动标的序号,而是proto文件里面message中定义的字段编号。为了验证,我换了编号,请求响应如下:
在这里插入图片描述
如果传输内容不多,比较简单的话,基本上我们根据抓包结果就可以编写proto配置文件了。编写proto文件的时候注意,字段编号和类型一定得对上,不然就会出现问题。
但是现在大多数app,一般用了protobuf协议,基本上都是配合gzip压缩或者结合一些加密算法一起使用,提高效率和增加安全性。由于是直接传输的二进制流,charles并不能正确解析协议。
比如这样:
在这里插入图片描述
这时候就需要根据url或者其它一些可以利用的信息去分析app。
根据url搜,由于demo比较简单,一下就能找到封装请求的地方。
在这里插入图片描述
一下就能找到封装请求的地方。找到 ProtobufHandle.Request声明的地方.
在这里插入图片描述
这样就找到了它的编号。然后结合上下文分析它的类型等等。可能有嵌套关系。
有些app封装的比较好,不需要怎么分析,直接照着它的写也能还原出proto文件。
比如携程app:
在这里插入图片描述
这里它用的protocbuf2的版本,最后照着它的样子写出.proto文件即可。里面的变量名不需要与app中的一致(建议一致,方便校验)。但编号一定要对上。
还原了.proto文件之后,之后的操作就是用protoc转换,然后按照它的格式字段发包就行了(参考之前的文章: flask实现python后台,最后写了python客户端怎么发包)。
还有种方式,就是如果你分析app知道它是protobuf传输且使用了什么加密方式。可以利用中间人攻击的方式,解密数据并显示在charles上也可以。就算没有字段说明,spider们根据页面数据展示,也能大概猜出这些编号对应什么意思。(或许这是没有必要的,毕竟你连别人的加密都分析出来了。)
github上还有相关分析protobuf协议的工具

  1. https://github.com/marin-m/pbtk
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的示例代码,演示了如何在Linux C++中接收protobuf消息并进行解码: ```cpp #include <iostream> #include <string> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include "my_proto.pb.h" using namespace std; int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { cerr << "socket error!" << endl; exit(-1); } struct sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(8080); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { cerr << "connect error!" << endl; exit(-1); } char buffer[1024]; int n = read(sockfd, buffer, sizeof(buffer)); if (n < 0) { cerr << "read error!" << endl; exit(-1); } MyProto my_proto; if (!my_proto.ParseFromArray(buffer, n)) { cerr << "protobuf parse error!" << endl; exit(-1); } cout << "message: " << my_proto.message() << endl; close(sockfd); return 0; } ``` 这里假设我们已经定义了名为`MyProto`的protobuf消息类型,并将其编码后发送给了本机的8080端口。在客户端中,我们首先创建一个Socket套接字,并将其连接到服务器。然后,我们从Socket中读取数据,并将其存储在名为`buffer`的字符数组中。接下来,我们使用`ParseFromArray`函数将`buffer`中的数据解析为protobuf消息。最后,我们打印出消息中的内容,并关闭Socket连接。 请注意,上述代码仅为演示目的,并未进行错误处理或异常情况处理。在实际应用中,你需要根据具体情况进行适当的错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值