2. App的构建与打包:APK与IPA文件结构
好,咱们今天聊聊App的构建和打包。说白了,就是开发写完代码后,怎么变成一个你能装到手机上的文件。
我刚开始做逆向的时候,拿到一个APK第一反应就是解压。结果发现一堆乱七八糟的文件,完全不知道从哪下手。后来踩的坑多了,才慢慢摸清楚每个文件是干嘛的。
今天咱们就掰开揉碎,把Android的APK和iOS的IPA这两个东西讲明白。
2.1 Android APK文件结构
APK其实就是一个ZIP压缩包。你可以用任何解压工具打开它。我习惯用7-Zip,轻量又好用。
解压后,你会看到这些核心文件:
| 文件/目录 | 作用 | 我的经验 |
|---|---|---|
| AndroidManifest.xml | App的身份证,声明权限、组件、版本 | 逆向第一步,先看这个文件 |
| classes.dex | Dalvik字节码,App的核心逻辑 | 反编译主要就是搞它 |
| resources.arsc | 编译后的资源索引表 | 字符串、布局、图片的映射关系 |
| lib/ | Native库,.so文件 | 加密、核心算法常藏在这里 |
| META-INF/ | 签名信息 | 改完APK必须重新签名 |
| res/ | 原始资源文件 | 图片、布局、动画等 |
2.1.1 AndroidManifest.xml
这个文件是App的入口。我每次拿到一个APK,第一件事就是看它。
它告诉你:
- App的包名是什么
- 申请了哪些权限(比如读取联系人、定位)
- 有哪些Activity、Service、BroadcastReceiver
- 入口Activity是哪个
举个例子,你看到一个App申请了READ_CONTACTS权限,但它是个手电筒App。嗯,这里要注意,这很可能有问题。
我曾经遇到过一个恶意App,它在Manifest里声明了RECEIVE_BOOT_COMPLETED权限。开机自启动,偷偷上传用户数据。这种小动作,一看Manifest就露馅了。
2.1.2 classes.dex
这是App的核心。所有的Java/Kotlin代码,最终都编译成Dalvik字节码,放在这个文件里。
为什么叫classes.dex?因为早期Android App只有一个dex文件。后来方法数超过65535,就有了多dex方案,比如classes2.dex、classes3.dex。
逆向分析时,我们主要就是反编译这个dex文件。常用的工具有:
- jadx:我目前的主力工具,直接反编译成Java代码
- JEB:商业工具,功能强大,但收费
- apktool:可以反编译成smali代码,适合做修改
2.1.3 resources.arsc
这个文件是个索引表。它记录了所有资源的ID和对应的值。
比如你在代码里写R.string.app_name,实际对应的是一个数字ID。resources.arsc就是把这个ID映射到实际的字符串。
逆向时,我们经常通过这个文件来找关键字符串。比如:
- API接口地址
- 加密密钥
- 错误提示信息
我有个习惯:拿到APK后,先用工具把resources.arsc里的字符串全部导出。然后搜索"http"、"key"、"secret"这些关键词。经常能发现一些开发者不小心留下的敏感信息。
2.1.4 lib目录
这个目录存放Native库,也就是.so文件。它们是用C/C++写的,编译成机器码。
为什么App要用Native代码?
- 性能要求高(比如游戏引擎、音视频处理)
- 复用已有的C/C++库
- 隐藏核心逻辑(反编译dex容易,反编译so难)
lib目录下通常有多个子目录,对应不同的CPU架构:
armeabi-v7a:老款ARM设备arm64-v8a:主流64位ARM设备x86/x86_64:模拟器常用
我曾经分析过一个金融App,它的支付签名逻辑全在so里。dex里只是调用了Native方法。想绕过它的签名校验?必须把so啃下来。
2.2 iOS IPA文件结构
说完了Android,咱们看看iOS。IPA本质上也是一个压缩包,但结构完全不同。
IPA文件其实是个ZIP包,把后缀改成.zip就能解压。解压后你会看到:
| 文件/目录 | 作用 | 我的经验 |
|---|---|---|
| Payload/ | 核心目录,里面放.app包 | 所有东西都在这里 |
| Info.plist | App的配置信息 | 类似Android的Manifest |
| 可执行文件 | Mach-O格式,App的二进制代码 | 逆向的主要目标 |
| _CodeSignature/ | 代码签名 | 改完必须重签 |
| iTunesArtwork | App图标 | 没啥用,但别删 |
2.2.1 Payload目录
这是IPA的核心。里面只有一个.app包,名字通常和App的Bundle Identifier有关。
这个.app其实是个目录,里面包含了:
- 可执行文件(Mach-O)
- 资源文件(图片、音频、NIB/XIB)
- Frameworks(动态库)
- PlugIns(插件)
我刚开始逆向iOS App时,第一反应是直接看可执行文件。后来发现,很多App把资源文件藏在了Asset.car里。这个文件需要用专门的工具才能解包。
2.2.2 Info.plist
这个文件是iOS App的配置文件。用Xcode或文本编辑器都能打开。
它包含:
- Bundle Identifier(唯一标识)
- 版本号
- 权限声明(比如相机、定位)
- 支持的设备方向
- URL Schemes
CFBundleURLSchemes。它定义了App能处理的URL协议。很多App通过URL Scheme实现App间跳转,这里经常有安全漏洞。
我记得有个社交App,它的URL Scheme里直接暴露了用户ID。你只要构造一个URL,就能直接打开某个用户的聊天界面。这种问题,一看Info.plist就能发现。
2.2.3 可执行文件
这是iOS App的核心。它是一个Mach-O格式的二进制文件。
Mach-O是苹果系统的可执行文件格式。它和Windows的PE、Linux的ELF是同一类东西。
逆向Mach-O文件,常用的工具有:
- Hopper Disassembler:我比较喜欢用,界面友好
- IDA Pro:功能最强大,但价格不菲
- Ghidra:免费开源,NSA出品
Mach-O文件的结构大致如下:
- Header:文件类型、CPU架构
- Load Commands:加载指令,告诉系统怎么加载这个文件
- Segments:代码段、数据段等
- Symbol Table:符号表,函数名、变量名
我曾经花了一整天去分析一个加密的Mach-O文件,结果发现忘了先解密。嗯,这种低级错误,犯过一次就不会再犯了。
2.3 知识体系总览
说了这么多,咱们用一张图来总结一下APK和IPA的核心结构。
这张图把APK和IPA的核心文件都列出来了。你想想看,逆向分析时,我们主要就是跟这些文件打交道。
Android这边,重点看dex和so。iOS那边,重点看Mach-O和Info.plist。掌握了这些,你就知道该从哪下手了。
好了,这一章的内容就到这。记住,拿到一个App,先看它的结构,再决定分析策略。别上来就反编译,那样效率很低。
公众号:蓝海资料掘金营,微信deep3321