google protobuf解码

0x00 背景

谷歌出了一款协议叫做protobuffer,它可以将数据编码成二进制流,并跨平台传输。它主要用在网络传输,尤其是http上。如果你使用burp等proxy截取使用protobuf的http请求,你只能看到一些乱码,看上去跟加了密似的w。当然如果你有.proto文件,你就可以完全解码这些二进制。遗憾的是,有时候你无法拿到.proto文件,比如说,某pkg,它使用IL2CPP编译成了汇编,不要说无法拿到.proto文件了,就连编译成的.cs文件也拿不到,这个时候就可以根据protobuf编码的规则,直接解码二进制,当然解码出来的东西并不完全准确,有些需要靠猜,而且各个field的名字也是无法复原的。

其实google自己已经提供了protobuf的解码,使用cat file.pb | protoc --decode_raw就可以了,但是这个解码提供的信息较少,且不能将float,double等type直接转换出来。另外google并没有提供改写protobuf二进制的方法,所以我自己写了这个解码器,可以讲protobuf的二进制以json的形式输出,包含较多信息,且支持编辑后写回二进制,此外还将这个解码器集成成了burp的插件,可以直接在burp中改写包含protbuf的http请求。

0x01 原理

其实很简单,读一下google protobuf encoding这个规则就好了。具体可以参考这个ppt的后半段:owasp night发表资料。然后使用递归就可以parse protobuf的二进制了。注意如果不仔细阅读编码规则,会遇到很多坑,比如每个域的field_number以及长度都是用Varint的方式编码的,而不是固定的一个字节。再比如embedded message和string和bytes都是同样的wire_type,解码它们的时候需要靠猜,如果解码失败则返回上一层递归继续猜。

0x02 代码

https://github.com/nevermoe/protobuf-decoder