bang dream proto相关

本文相关轮子: proto读取导出 | 定时任务本体数据库对比主数据


A python + libil2cpp.so(Android) dumper:

Article: Generating Proto File For Banddream | DNARoma

gist


因为上周的一个想法,写出了redive和cgss的master数据库diff库,还造了一波bundle解压的轮子

redive第三个号被制裁了,平稳科技流也开始查了

土豆的内容星月大佬写离线的时候已经表示过master不可行,都是登录时返回部分master,所以就可以放弃了

然后就是bang了,开搞前我还又去debug了一下,结果看到密钥瞬间才想起power之前给我说过

炸梦通信是protobuf,包括master和manifest也是,所以就必须要提取原始关系才行了。我刚开始还想尝试暴力提取数据,但是内结构和字符串都是wireType 2,没法区分

在之前我已经在Prefare博客上看到过说dump属性什么的,dnspy改了之后也没搞懂怎么看。后来在评论区看到回复才找到

Perfare:邦邦用的是protobuf-net不是Google.Protobuf,不需要.proto文件,你只需要找到带ProtoContractAttrbuit的类并还原出properties上ProtoMemberAttribute的值就可以序列化了

知道入口后就开始观察了,搜索了一波然后看到master数据的类是SuiteMasterGetResponse(基本上各种proto类都叫GetResponse)

观察了下结构之后就开始写proto dumper了,以SuiteMasterGetResponse为入口,循环匹配含有 [ProtoMemberAttribute] 的成员,然后匹配子类递归。匹配中就需要特殊处理,比如xxxx[]就是一个数组,List<xxxx>也是一个数组,Dictionary2<xxx, yyy>就是键值对,观察了下数据分布这里的结构是

即key+value形式

名称和类型之类的导出做完之后,就是tag id了。tag id并不是连续数,所以就需要读取原始数据。每个成员的ProtoMember属性都带一个地址,这个地址是一个函数,每个函数看起来都是这样的:

可以明显看出是个只有5条指令的函数,而id明显就是第3条,那么就只需要读取出立即数就行了

结果这个可以说是整个读取里面最大的坑了。因为某种优化,编译器输出的立即数赋值指令有两种:

movk指令的话,很简单,匹配中间的i位就可以了

但是orr整整卡了我两个小时,在群里大佬stat带领下才逐渐搞明白读取方法

简单讲,从第二字节开始,第一位为0,第二位N表示是否64位,3-8位为immr——旋转数,第三字节1-6为imms——大小数。此处nnnnn恒为11111,表示W31寄存器,即WZR,或读0。立即数结尾imms位设置为1,然后循环右移immr位,即为所读立即数

这里本来imms还表示pattern大小,但其实也没做出来,因为都是32位的pattern。

搞定tag id读取之后就是一路爽了,稍作修改就能输出规范proto。导出代码gist

造完这么个奇怪的轮子之后又得继续造读取轮子。现有的开源实现没找到能快捷转换protobuf到php数组的,估计也是php类型太少会导致格式信息丢失吧。拿出之前读b站弹幕的轮子改了改,换了最近写的FileStream轮子读取内容(Utaha:你要记住自己的本质是一个轮子工(),读完之后再进行字典键值对处理,最后又一个自定义json输出美化的轮子

高潮来了

写完逻辑代码后跑了一遍,但是我在第二遍才加了core.filemode=false,一堆mode change,于是…

一 秒 爽 到

当场恢复了message导出代码,但是主逻辑不见了。今天早上花了一上午grep /dev/sdb1恢复(msys2竟然有这个设备映射),但是p都没找着。于是,又重新造了一遍自己刚造完的轮子(Utaha:你要记住自己的本质是一个轮子工(

这次记录的基本上就这些,还是要感谢各位前辈造好的轮子,我才能这么爽到(x