如何获取APK的声明文件大小与总文件大小?附代码验证
APK文件声明大小与总大小解析及获取方案
一、两个大小的定义
- 总文件大小:APK文件在磁盘上的实际字节数,对应警告中的
total file size。这是文件系统层面的真实大小,包含所有内容(包括被追加到文件末尾的额外数据)。 - 声明文件大小:指APK内部DEX文件头部(DexHeader)中
file_size字段的值,对应警告里的Declared filesize。正常情况下,这个值应该等于DEX文件的实际大小,但恶意样本常篡改该字段或在DEX末尾追加数据,导致两者不匹配,从而触发AndroGuard的警告。
二、正确获取两个大小的方法
1. 总文件大小
你用os.path.getsize(apk_file)获取总大小的代码是正确的,该函数直接返回APK文件在磁盘上的物理字节数。
2. 声明文件大小(DEX头部的声明值)
你提供的代码触发KeyError,原因是benign_path[0]不是APK内DEX文件的有效路径。APK中的DEX文件通常命名为classes.dex,部分多DEX的APK会有classes2.dex等。正确的方式是读取DEX文件头部的file_size字段,代码如下:
import os import zipfile import struct def extract_declared_dex_size(apk_path): declared_size = None with zipfile.ZipFile(apk_path, 'r') as apk_zip: # 遍历APK内所有DEX文件 for entry in apk_zip.namelist(): if entry.endswith('.dex'): with apk_zip.open(entry) as dex_fp: # DexHeader中file_size字段位于偏移0x20,占8字节(小端字节序) dex_fp.seek(0x20) declared_size = struct.unpack('<Q', dex_fp.read(8))[0] # 若只需要第一个DEX的声明大小,可直接break break return declared_size # 示例调用 apk_path = "target_apk.apk" total_size = os.path.getsize(apk_path) declared_dex_size = extract_declared_dex_size(apk_path) print(f"总文件大小: {total_size}") print(f"DEX声明大小: {declared_dex_size}")
说明:DEX文件头部的file_size字段是8字节无符号长整数,采用小端字节序,偏移量固定为0x20(即从文件开头数第32字节位置),读取该位置的值即可得到声明的DEX大小。
三、针对恶意APK的EDA分析建议
- 统计触发警告样本中,总大小与DEX声明大小的差值分布,差值较大的样本大概率存在额外恶意载荷。
- 对比多DEX APK中每个DEX的声明大小与实际大小,构建差异特征用于恶意样本筛选。
- 对存在异常资源类型的APK,进一步解析AXML结构,排查资源类型篡改的恶意逻辑。
内容的提问来源于stack exchange,提问作者Minwoo Lee
相关产品推荐
相关产品推荐

