在抓一个app的包的时候发现http的Content-type竟然是application/x-protobuf,第一次遇到这种。网上也有不少问关于这方面的,或许有人已经研究出来了,但是不肯放干货啊。只能自己探索了。
首先我用的抓包工具是Charles,抓包是能看到内容的。Charles本身是用java写的,所以很容易看到源代码。在com.xk72.charles.gui.transaction.viewers.protobuf包下面确实有一个ProtocolBuffersTreeBodyViewer$1的视图,因为jd-gui搜索代码功能有缺陷,导出jar也一直卡着,哪里开始解析的没有找到。只能从protobuf编码开始研究了。然后发现有个命令‘protoc.exe --decode_raw ’直接可以解析任意字节流了。
能看到包的内容算是解决了,但是怎么伪造protobuf包呢?答案就是保持字节流的长度不变,直接替换byte的内容。然后直接发包就可以了。
比如我在分析一个protobuf字节流的时候,拿到的二进制保存到文件里查看是这样的:
86177897654321267"006006* b8e6683bd8cf4f5997f9ff55d04da8910ÿÿÿB`
$ffffffff-c978-5f17-ffff-ffffc2e834d93.8.5.1*$手机型å·ï¼šMuMu版本å·ï¼š6.0.1BaJæ¸ é“
然后另外一个protobuf字节流拿到的二进制保存到文件里查看是这样的:
kOKc182****1121 b8e6683bd8cf4f5997f9ff55d04da891 ¤ç‹®¼©ÎÐ×Ìë2019/9/6 11:26:19
在使用‘protoc.exe --decode_raw ’查看包内容的时候,有一个int的关键字他的值是2290596,这个关键字之前的字符串是
b8e6683bd8cf4f5997f9ff55d04da891
然后分解这两个字节流的byte数组发现,b8e6683bd8cf4f5997f9ff55d04da891后面有几个一模一样的值
-92 -25 -117 1
是不是这四个字节或者其中的一部分就代表2290596呢?
protobuf采用的是Varints编码
比如数字149通过Varints编码后变成了
10010101 00000001
这里面有2个字节,在Varints中每个字节的第一个bit都是代表后面还有没有更多的字节,从上面的例子能看出,第一个字节首bit是1,代表后面还有字节,需要继续处理,第二个的首bit是0,代表到此为止后面没有字节了。
还有一个需要注意的是,Varints采用的是 least significant group first, 网上没有找到合适的翻译,其实就是它在表示整型变量时将字节顺序反过来存储,比如上面这个例子:
10010101 00000001 -> 0010101 0000001 //去掉首bit
0010101 0000001 ->00000010010101 //反转顺序
00000010010101换算成10进制就是149
————————————————
该部分引用:https://blog.csdn.net/toxie6415176/article/details/80258513
因为2^21次方是2097152小于2290596所以,需要四个字节来表示,因此上面四个字节都是用来表示2290596。
2290596的二进制是:10 0010 1111 0011 1010 0100按照上面规则它的Varints编码就是:
11011100 1001101 11110101 00000001
-92 -25 -117 1的补码:
11011100 1001101 11110101 00000001
就能验证结果了,所以发包的时候直接替换对应byte索引里面的内容就可以了。
关于protoc.exe --decode_raw 这个命令网上很少有介绍。
protoc.exe --decode_raw < input_raw.bin > out_put.txt
input_raw.bin就是protob的二进制文件,out_put.txt就是输入结构到制定文件,如果不使用就直接显示在命令行上了。