protobuf是一套非常优秀的序列化与反序列化协议,因此在平时的逆向过程中,与之打交道是不可避免的。如何能够在浩瀚的数据海洋中一眼认出它并准确快速地定位出它的数据结构呢?
识别protobuf
内存中的protobuf数据往往具体有样的特点:二进制流中掺杂着明文、明文与非明文数据交替出现。一串二进制流出现这样的特征时,第一时间就可以往protobuf方向考虑。如何检验这种猜测呢?
校验protobuf
有很多种方法去检验一段数据是不是protobuf,最为高效的是使用ProtobufViewer工具。从内存中将二进制流导入到文件后,用ProtobufViewer打开这个文件,就能够具体看到protobuf的具体结构信息了。
除了能够从文件中读取数据外,ProtobufViewer还接收Hex字符串类型的Protobuf数据。
protobufviewerProtobufViewer能够将ProtobufViewer的数据结构非常清晰地展示出来,如果便能够很轻松地还原出proto文件。当然每个字段对应的物理含义,还需要根据字段值去猜测,实在无法确定时,就需要通过逆向的手段定位到此字段赋值时的代码,进而确定其物理意义。
内存结构
Proto对象结构以cpp代码为例,proto对象在内存中的数据结构大致是图中这样的:前8个字节标识着对象的类型,通过它能够定位出proto对象的descrition数据。后面16个字节是保留字段,其具体含义及作用我也不甚了解,对于本文所要描述的主题作用不大。再后面的所有数据都对应了protobuf对象的每一个字段,至于每个字段所占用的字节数,这个就需要具体问题具体分析了。
Message-2.jpg除了上面的ProtobufViewer工具能够定位Proto对象所数据结构外,通过proto对象的description数据同样能够确定每个字段的数据类型与字段序号。description数据位于Message对象的0x38偏移位置。
proto文件
上面所做的一切都是为了导出proto对象的proto文件,通过这个文件,protoc程序能够输出很多语言版本的proto类代码,进而就能够去实现下一个目标了,同样以cpp代码为参考,导出命令如下:
protoc -I ./ --cpp_out=./ xxx.proto
网友评论