QQ浏览器返回和发送的数据都是通过JceStruct协议来传输的.当然这个传输过程是经过层层加密的.解密后的内容就是JceStruct协议.
JceStruct 协议和Protobuf 协议有点像,也是采用Key-Value的形式.但感觉比Protobuf更简洁一点.也更简单一点.
JceStruct 的内容组织形式
Key
我们先来看看Key是怎么组织的.
描述Key的类为:HeadData
|
1 2 3 4 |
|
可以看到Key被分为了两部分,一部分是tag,一部分是type.
读取Key的函数为
|
1 2 3 4 5 6 7 8 9 10 |
|
函数功能非常简单.
- 字节低4位为type 表示序号对应的类型
- 字节高4位为tag 表示序号
- 如果tag为0xF,下一个字节为tag.
总结一下:
- Key由tag和type组成
- Key为1个字节或两个字节.两个字节时第二个字节为tag否则第一个字节的高4位为tag.type始终为第一个字节的低4位.
- type最多有16种类型,tag最大为255.
type
根据分析type的类型如下:
| 值 | 类型 |
|---|---|
| 0 | byte 或 bool |
| 1 | Short |
| 2 | Int |
| 3 | Long |
| 4 | Float |
| 5 | Double |
| 6,7 | String |
| 8 | Map |
| 9 | List |
| 10 | STRUCT_BEGIN 继承了JceStruct类的开始 |
| 11 | STRUCT_END 继承了JceStruct类的结束 |
| 12 | ZERO_TAG |
Value解析
解析标准的Java类型
根据不同的类型对Value的解析就会有所不同.
其中byte,bool,Short,Int,Long, Float,Double的解析都是一样的,只不过读取的字节数不同而已.
我们以Int为例:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
可以看到非常简单,读到指定类型,那么getXXX就可以了.这是Java的标准类型.
解析String
我们先看一下解析String的Java代码.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
我们知道String的类型为6,7.
当类型为6时,String的长度为一个字节.
当类型为7时,String的长度为一个Int.且字符串的最大长度为104857600个字节.
读取了长度之后,之后的字节就是String的内容.其中sServerEncoding字段指定了字符串的编码类型.
在我分析的时候都是UTF-8.
解析Map
依然是我们看代码说话:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
我们看一下read(key,0,true),read(value,1,true)调用的函数是
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
- 如果类型为8,也就是说类型是Map,那么接下来的值是一个Int表示这个Map有n个成员.
- 然后他的n个成员都是按照Key-Value,Key-Value.....这样子连续存储下来.
List解析
List解析调用的是readAllay函数.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
可以看到和Map差不多,只不过是没有Map的Key部分而已.
- 如果类型为9,也就是说是List,那么接下来的值是一个Int表示接下来List有n个成员
- 然后他的n个成员都是按照Value,Value,....这样子连续存储下来.
解析继承JectObject的对象
有人和觉得解析这个可能会比前面都难,但是其实也挺简单,单单就是调用JectObject类的抽象函数readFrom
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
readFrom就是看每个继承了JceStruct类怎么组织自己的内容,然后按照自己的字段组织在里面顺序调用各个read重载函数就可以了.
实例
通过抓包工具抓取下来一个包,并对其进行解密后得到的就是JceStruct.这个包是返回Home页内容的.
我用IDEA写了一个Java项目.通过把JceStruct的代码抽取出来.其中只有少许的改动.因为有几个函数经过反编译是编译结果是错误的.只能手动从Smali翻译过来了.
进过项目解析之后:
最近996很流行啊.
转载自 :https://bbs.pediy.com/thread-250845.htm 看雪论坛