APK逆向 zip格式错误1:文件结尾恶意修改

1,185 阅读3分钟

1 问题描述

众所周知,apk文件其实就是zip格式

如下图所示,apk文件末尾增加了comment(红线标记的范围内是文件尾,后面是comment),正常来说没有问题,但是comment里面还包含了504b0506这个zip文件尾的标识

image.png

使用jeb逆向可以正确解析,但是python自动化分析时,使用androguard库解析失败。

还有另外一种情况,如下,apk包含了2个格式合法的文件尾,依旧导致androguard解析报错

image.png

2 分析

2.1 第一种

androguard使用了python自带的zipfile库,第一种情况是因为zipfile库为了提高性能,是从文件末尾向前检查504b0506标记,导致出错。

下面是zipfile解析zip文件尾的部分代码(python3.8),里面注释说明了comment不能包含类似504b0506的zip文件尾标记;其方法就是从文件末尾向前找(64k+22) 个字节,其中64k是最大comment长度,22是文件尾长度。这样确实节省了查找时间,但是遇到恶意插入comment的样本就会报错,解决办法就是直接把data.rfind() 改成data.find()

    # Either this is not a ZIP file, or it is a ZIP file with an archive
    # comment.  Search the end of the file for the "end of central directory"
    # record signature. The comment is the last item in the ZIP file and may be
    # up to 64K long.  It is assumed that the "end of central directory" magic
    # number does not appear in the comment.
    maxCommentStart = max(filesize - (1 << 16) - sizeEndCentDir, 0)
    fpin.seek(maxCommentStart, 0)
    data = fpin.read()

    start = data.rfind(stringEndArchive)

2.2 第二种

导致错误的原因与第一种有点类似,因为python的zipfile库是从末尾向前读数据,读取顺序为:

end locator -> file entry -> file record

注:这里用的010编辑器模板的说法,还有其他说法如 file entry叫做 central directory

三种chunk的头部标记分别为50 4b 05 0650 4b 01 0250 4b 03 04.

由于从后向前读,第一个读到的就是最后面的end locator,而前面的一个end locator会被忽略掉。然后zipfile库其中有一句如下

        # "concat" is zero, unless zip was concatenated to another file
        # 翻译:"concat"为0,除非当zip文件还附带了另外的文件
        concat = endrec[_ECD_LOCATION] - size_cd - offset_cd

zipfile会检测zip文件的前面是否还附带了其他的数据(比如附带一个图片,然后把文件后缀改成jpg,一般人打开就是一张图,但是用winrar打开就是一个压缩文件)。

它的检测方法就是用end locator首地址(从整个文件的开头开始算的地址)减去file entry的大小,再减去file entry的偏移地址(相对于zip头部的偏移,不是相对于整个文件开头的偏移,所以这个就相当于file record的大小)。

正常来说,这样减完后,刚好把zip文件部分全部剪掉了,如果还有数据,那就说明前面还附带了其他文件。但是这个例子里,zipfile读取的end locatorfile entry之间还夹了一个end locator,这样就导致读取数据错位了

image.png

如果只用来分析apk,可以直接改源码,让concat=0就行