吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8093|回复: 42
收起左侧

[原创] Protobuf的正逆向学习和基于python的实现

  [复制链接]
jingtai123 发表于 2022-9-25 12:57
本帖最后由 jingtai123 于 2022-9-26 09:06 编辑

1、起因

  • 期初开始对https://cat-match.easygame2021.com/sheep/v1/game/game_over_ex/ 抓到的包,很好奇,MatchPlayInfo到底是个啥加密方式。
  • 通过分析JS源码,找到一个叫做 Protbuf 的东西,头一次 接触,学了一下,如何用Python实现这个玩意,所以有了这篇文章,算是对学习protobuf的记录。
  • 欢迎大佬批评指正。
{
  "MatchPlayInfo" : "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",
  "Version" : "0.0.1",
  "MapSeed2" : "1666910531",
  "skin" : 1,
  "rank_time" : 144,
  "rank_role" : 1,
  "rank_state" : 1,
  "rank_score" : 1
}

2、protobuf 是什么

protobuf是google提供的一个 开源序列化框架类似于XML,JSON这样的数据表示语言,其最大的特点是 基于二进制 ,因此比传统的XML 表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成 相关的类,可以支持php、java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反 序列化工作。

protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在 google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。

简单看来 就是一个序列化和反序列化工具。

3、protobuf 怎么用

正向:

  1. 定义一个.proto文件的message结构体
  2. 通过proto库提供的工具 生成所需语言的代码
  3. 通过生成的代码 进行加解密

逆向:

  1. 通过blackboxprotobuf工具对密文解码
  2. 通过读源码分析对应的参数
  3. 构造message结构体
  4. 通过生成的代码加解密

4、逆向实操

step1

对密文的预处理

  1. 通过源码可以看到,MatchPlayInfo是序列化后通过base64编码的
    var N ={        rank_score: 1,
                   rank_state: t,
                   rank_time: this.countdown,
                   rank_role: o,
                   skin: r,
                   MatchPlayInfo: S.default.base64_encode(b)
          };
  2. 需要下述将MatchPlayInfo中的内容先base64解码

    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

  3. base64解码:
    import base64
    mydate = "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"
    out_b = base64.b64decode(mydata)

    得到的就是protobuf序列化后的结果

    b'\x08\x03"\x05\x08\x8a\x01\x10\x08"\x05\x08\x8b\x01\x10\x08"\x05\x08\x90\x01\x10\x08"\x05\x08\xd1\x01\x10\x05"………………

step2

使用blackboxprotobuf 对密文反序列化

  1. 安装blackboxprotobuf , protobuf
    pip install blackboxprotobuf protobuf
  2. 解析为json
    import blackboxprotobuf
    deserialize_data, message_type = blackboxprotobuf.protobuf_to_json(out_b)
    print(f"原始数据: {deserialize_data}")
    print(f"消息类型: {message_type}")

    得到结果:

原始数据: {"1": "3","4": [ { "1": "138","2": "8"},{"1": "139","2": "8"},{"1": "144","2": "8"},…………]}
消息类型: {'1': {'type': 'int', 'name': ''}, '4': {'type': 'message', 'message_typedef': {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''}}, 'name': ''}}

step3

分析源码构造message的.proto文件

  1. 源码:

    MatchPlayInfo部分
    o.MatchPlayInfo = function () {
                    function t(t) {
                        if (this.stepInfoList = [], t) for (var e = Object.keys(t), o = 0; o < e.length; ++o) null != t[e[o]] && (this[e[o]] = t[e[o]]);
                    }
    
                    return t.prototype.gameType = 0, t.prototype.mapId = 0, t.prototype.mapSeed = 0,
                        t.prototype.stepInfoList = r.emptyArray, t.create = function (e) {
                        return new t(e);
                    }, t.encode = function (t, e) {
                        if (e || (e = a.create()), null != t.gameType && Object.hasOwnProperty.call(t, "gameType") && e.uint32(8).int32(t.gameType),
                        null != t.mapId && Object.hasOwnProperty.call(t, "mapId") && e.uint32(16).int32(t.mapId),
                        null != t.mapSeed && Object.hasOwnProperty.call(t, "mapSeed") && e.uint32(24).int32(t.mapSeed),
                        null != t.stepInfoList && t.stepInfoList.length) for (var o = 0; o < t.stepInfoList.length; ++o) c.protocol.MatchStepInfo.encode(t.stepInfoList[o], e.uint32(34).fork()).ldelim();
                        return e;
                    }, t.decode = function (t, e) {
                        t instanceof i || (t = i.create(t));
                        for (var o = void 0 === e ? t.len : t.pos + e, n = new c.protocol.MatchPlayInfo(); t.pos < o;) {
                            var a = t.uint32();
                            switch (a >>> 3) {
                                case 1:
                                    n.gameType = t.int32();
                                    break;
    
                                case 2:
                                    n.mapId = t.int32();
                                    break;
    
                                case 3:
                                    n.mapSeed = t.int32();
                                    break;
    
                                case 4:
                                    n.stepInfoList && n.stepInfoList.length || (n.stepInfoList = []), n.stepInfoList.push(c.protocol.MatchStepInfo.decode(t, t.uint32()));
                                    break;
    
                                default:
                                    t.skipType(7 & a);
                            }
                        }
                        return n;
                    }, t;
                }()
    MatchStepInfo部分
    o.MatchStepInfo = function () {
                    function t(t) {
                        if (t) for (var e = Object.keys(t), o = 0; o < e.length; ++o) null != t[e[o]] && (this[e[o]] = t[e[o]]);
                    }
    
                    return t.prototype.chessIndex = 0, t.prototype.timeTag = 0, t.create = function (e) {
                        return new t(e);
                    }, t.encode = function (t, e) {
                        return e || (e = a.create()), null != t.chessIndex && Object.hasOwnProperty.call(t, "chessIndex") && e.uint32(8).int32(t.chessIndex),
                        null != t.timeTag && Object.hasOwnProperty.call(t, "timeTag") && e.uint32(16).int32(t.timeTag),
                            e;
                    }, t.decode = function (t, e) {
                        t instanceof i || (t = i.create(t));
                        for (var o = void 0 === e ? t.len : t.pos + e, n = new c.protocol.MatchStepInfo(); t.pos < o;) {
                            var a = t.uint32();
                            switch (a >>> 3) {
                                case 1:
                                    n.chessIndex = t.int32();
                                    break;
    
                                case 2:
                                    n.timeTag = t.int32();
                                    break;
    
                                default:
                                    t.skipType(7 & a);
                            }
                        }
                        return n;
                    }, t;
               }()
  2. 根据源码及解析结果构建.proto文件

syntax = 'proto3';

message MatchPlayInfo{
  int32 gameType = 1;
  int32 mapId = 2;
  int32 mapSeed = 3;
  repeated StepInfoList stepInfoList = 4;
}
message StepInfoList{
  int32 chessIndex = 1;
  int32 timeTag = 2;
}

存为 yang.proto文件

step4

通过.proto文件生成对应的python代码

  1. 安装grpcio-tools库
    pip install grpcio-tools
  2. 终端运行 生成对应的 yang_pb2.py
    python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. yang.proto

step5

引用 yang_pb2.py 进行加解密

解密:

import yang_pb2
mydata = "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"
out_b = base64.b64decode(mydata)

matchPlayInfo_out = yang_pb2.MatchPlayInfo()
matchPlayInfo_out.ParseFromString(out_b)
print(matchPlayInfo_out)

打印结果:

gameType: 3
stepInfoList {
  chessIndex: 138
  timeTag: 8
}
stepInfoList {
  chessIndex: 139
  timeTag: 8
}
stepInfoList {
  chessIndex: 144
  timeTag: 8
}
stepInfoList {
  chessIndex: 209
  timeTag: 5
}
………………

构造加密:

improt yang_pb2
matchPlayInfo=yang_pb2.MatchPlayInfo()
matchPlayInfo.gameType=3
stepInfoList = yang_pb2.StepInfoList()
for i in range(1,297):  
    stepInfoList.chessIndex=i
    stepInfoList.timeTag=i
    matchPlayInfo.stepInfoList.append(stepInfoList)
out_b = matchPlayInfo.SerializeToString()

out_b结果:

b'\x08\x03"\x04\x08\x01\x10\x01"\x04\x08\x02\x10\x02"\x04\x08\x03\x10\x03"\x04\x08\x04\x10\x04"\x04\x08\x05\x10\x05"\…………

对out_b进行base64编码即得到结果

b64out_b = base64.b64encode(out_b)
print(b64out_b)

b'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'

用上述的解密方法对构造的加密解密:

matchPlayInfo_out = yang_pb2.MatchPlayInfo()
matchPlayInfo_out.ParseFromString(out_b)
print(matchPlayInfo_out)

matchPlayInfo_out结果:

gameType: 3
stepInfoList {
  chessIndex: 1
  timeTag: 1
}
stepInfoList {
  chessIndex: 2
  timeTag: 2
}
stepInfoList {
  chessIndex: 3
  timeTag: 3
}
stepInfoList {
  chessIndex: 4
  timeTag: 4
}
…………
stepInfoList {
  chessIndex: 295
  timeTag: 295
}
stepInfoList {
  chessIndex: 296
  timeTag: 296
}

免费评分

参与人数 23威望 +2 吾爱币 +120 热心值 +23 收起 理由
Right_Hai + 1 谢谢@Thanks!
RedStorm + 1 + 1 用心讨论,共获提升!
TiakonPwd + 1 + 1 谢谢@Thanks!
xin1235 + 1 用心讨论,共获提升!
nevinhappy + 1 + 1 用心讨论,共获提升!
fengbu401 + 1 + 1 我很赞同!
gaosld + 1 + 1 谢谢@Thanks!
allspark + 1 + 1 用心讨论,共获提升!
lsgzhanghu + 1 + 1 谢谢@Thanks!
Sunshines + 1 + 1 说的啥玩意啊,全程就看到用各种Python的库,然后一些意义不明的代码,讲了.
三滑稽甲苯 + 2 + 1 用心讨论,共获提升!
努力加载中 + 1 + 1 热心回复!
精灵墙 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
RippleSky + 1 热心回复!
抱歉、 + 1 谢谢@Thanks!
zhuanke8 + 1 + 1 谢谢@Thanks!
lemonrains + 1 + 1 用心讨论,共获提升!
875988045 + 1 + 1 用心讨论,共获提升!
SunerC + 2 + 1 我很赞同!
杨辣子 + 1 + 1 用心讨论,共获提升!
li645944229 + 1 + 1 谢谢@Thanks!
yuweb + 1 + 1 热心回复!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| jingtai123 发表于 2022-9-27 19:44
这篇帖子的目的只是探讨protobuf  不是为了刷次数
gugouo163 发表于 2022-9-27 13:42
子诺 发表于 2022-9-27 10:59
请问下楼主,这个方法我能够成功提交。但是为什么自己构造的数据不能刷通关次数,它们的通关次数 是什么原 ...

同样情况,感觉还是数据有不对
子诺 发表于 2022-9-27 10:59
请问下楼主,这个方法我能够成功提交。但是为什么自己构造的数据不能刷通关次数,它们的通关次数 是什么原理?有没有知道的?
zhaohyperion 发表于 2022-9-26 14:42
感谢分享,blackboxprotobuf,这个玩意木有听说过,看看
wkunzhi 发表于 2022-9-26 17:39
学习了,谢谢
buggur 发表于 2022-9-26 18:57
有没有php版本对这个进行实现的
buggur 发表于 2022-9-26 19:02
为什么我解出来是这样的
image.png
shutegame 发表于 2022-9-26 20:32
厉害了。。。DUBBO的东西也破解了
mfvpnhaha 发表于 2022-9-26 23:21
看不懂啊这个咋使用的哦?
 楼主| jingtai123 发表于 2022-9-27 00:22
shutegame 发表于 2022-9-26 20:32
厉害了。。。DUBBO的东西也破解了

算不上破解  正常使用
BySiHan 发表于 2022-9-27 01:51
好像并未成功计算次数 楼主可以自己再试一下提交
xixicoco 发表于 2022-9-27 02:02
不错的教程
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 03:30

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表