问题描述
遇到一个apk,其androidmanifest无法正常解析,报错文件长度不对
此处报错为axml头部声明的文件总长度为69044,但实际整个axml文件却只有46028,估计是解压出错了
010查看local file header内容,很容易发现问题:压缩方法为Stored,表示没有压缩,直接存的原文,但是下面的压缩前后的文件大小却为46028和69044,理论上这两个值应该相等。
分析
android压缩方法只有stored(保存原文)和deflate(一种压缩算法),并且android解析apk时,会直接使用central dir 的压缩方法,而不是local file header中的.
我第一时间去检查central dir,发现还是stored(504b下面一行的第6,7个字节都是0)
之后又猜测是不是android会比对解压前后的大小,发现不匹配就默认是deflate压缩?
验证猜想只能去看android源码了:
androidfw库:cs.android.com/android/pla…
zip相关库: cs.android.com/android/pla…
最后分析了半天zip库,终于在跟踪到androidfw库后发现了问题。。。
ZipFileRO里面一个逻辑是:如果压缩方法为stored,吧actualLen赋值为解压后长度
actualLen就是指压缩后的长度,如果是deflate压缩,就吧长actualLen的数据解压出来,是stored就直接把长为actualLen的数据复制出来
这里如果是stored,就直接忽略掉了解压前的长度
实在无法理解为什么专门要搞一个“实际长度”,直接用compressed_length不行吗
反思
感觉白浪费了几个小时,明明直接看zip里面文件数据就能猜出大概了,如下图,local file header后面接的androidmanifest数据,一眼就能看出是没压缩的,然而刚开始却忽视了这点
不过从源码里面找到了问题也算有收获了,最后提一下,jeb3、jadx、androguard这些主流分析软件,竟然都没法正常解析这个apk(因为这个错误)