72、iOS逆向(一):IPA结构、Mach-O分析、class-dump使用
说实话,iOS逆向这个领域,我一开始接触的时候也觉得挺神秘的。那时候刚入行,看到别人能把App里的头文件全扒出来,觉得这简直是黑科技。后来自己动手做了一遍,才发现——嗯,其实就是几个工具的组合使用,加上一点耐心。
这一章,咱们先打基础。把IPA的结构、Mach-O文件怎么分析、class-dump怎么用,这三个核心点讲透。你把这些搞明白了,后面的动态分析、Hook、调试,才能玩得转。
1. IPA文件结构:App的“压缩包”
IPA,全称是iOS App Store Package。说白了,就是一个压缩包。你把它后缀改成.zip,解压就能看到里面的内容。
我刚开始逆向的时候,第一件事就是解压IPA。为什么呢?因为里面藏着很多关键信息。
一个典型的IPA解压后,你会看到这样的结构:
Payload/
└── WeChat.app/
├── WeChat # 可执行文件(Mach-O)
├── Info.plist # 应用配置信息
├── embedded.mobileprovision # 描述文件(签名信息)
├── Frameworks/ # 动态库
├── PlugIns/ # 扩展插件
└── Assets.car # 资源文件(图标、图片等)
这里面,最重要的就是 WeChat 这个文件。它就是Mach-O格式的可执行文件。所有的代码逻辑、类信息、方法调用,都藏在这里面。
Info.plist。里面有个 CFBundleExecutable 字段,直接告诉你哪个文件是可执行文件。省得你瞎猜。
2. Mach-O文件分析:App的“骨架”
Mach-O是iOS和macOS上的可执行文件格式。你可以把它理解成Windows上的PE文件,或者Linux上的ELF文件。
Mach-O的结构,大致分为三部分:
- Header:文件头,包含CPU架构、文件类型等信息。
- Load Commands:加载命令,告诉系统怎么加载这个文件。
- Data:真正的代码和数据,包括多个Segment(段)和Section(节)。
我常用的分析工具是 otool 和 MachOView。前者是命令行,后者是图形界面。
举个例子,查看Mach-O的Header信息:
otool -h WeChat
输出大概长这样:
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
0xfeedfacf 16777228 0 0x00 2 45 5432 0x00200085
这里 magic 是 0xfeedfacf,表示这是64位的Mach-O。如果是32位,就是 0xfeedface。你想想看,这个魔数是不是挺有意思的?
再看Load Commands:
otool -l WeChat | head -50
你会看到很多 LC_SEGMENT_64、LC_SYMTAB 之类的命令。其中 LC_SEGMENT_64 定义了各个段在内存中的位置。比如 __TEXT 段放代码,__DATA 段放数据。
__TEXT 段被加密了。这种情况多见于那些做了代码混淆或加壳的App。这时候,你需要先脱壳,才能继续分析。常用的脱壳工具有 dumpdecrypted 或 frida-ios-dump。
3. class-dump的使用:把“骨架”变成“说明书”
class-dump,是我个人觉得最爽的一个工具。它能从Mach-O文件里提取出所有Objective-C的类声明、方法、属性、协议。说白了,就是把编译后的二进制文件,还原成你能看懂的头文件。
安装很简单,用Homebrew:
brew install class-dump
使用也简单:
class-dump -H WeChat -o ./headers
这条命令的意思是:从 WeChat 这个Mach-O文件里提取头文件,输出到 ./headers 目录。
运行之后,你会看到一堆 .h 文件。比如:
headers/
├── AppDelegate.h
├── ViewController.h
├── WXApi.h
├── CMessageMgr.h
└── ...
打开一个看看:
// CMessageMgr.h
@interface CMessageMgr : NSObject
- (void)sendMessage:(id)arg1;
- (id)getMessageWithID:(NSString *)msgID;
@property (nonatomic, retain) NSString *currentUserName;
@end
看到没?类的所有方法、属性,一目了然。这就像你拿到了App的API文档。
nm 或 strings 来辅助分析。
4. 实战:用class-dump分析一个简单App
咱们来走一遍完整的流程。假设你有一个叫 DemoApp.ipa 的文件。
- 解压IPA:
unzip DemoApp.ipa -d ./DemoApp - 找到可执行文件:进入
Payload/DemoApp.app,找到DemoApp文件。 - 检查架构:
file DemoApp,看看是arm64还是armv7。 - 运行class-dump:
class-dump -H DemoApp -o ./headers - 分析头文件:打开
./headers目录,看看有哪些类。
我一般会先看 AppDelegate.h,了解App的启动流程。然后看 ViewController.h,看看主界面有哪些交互。最后,重点关注那些名字里带 Manager、Service、Helper 的类,这些通常是核心逻辑所在。
5. 知识体系总览
下面这张图,帮你理清这一章的核心逻辑:
6. 一些实用技巧
- 查看所有类名:
class-dump -A DemoApp,只输出类名,不输出方法。适合快速浏览。 - 过滤特定类:
class-dump DemoApp | grep "Manager",只显示包含“Manager”的类。 - 查看字符串:
strings DemoApp | grep "http",可以找到网络请求的URL。 - 查看符号表:
nm DemoApp | grep "OBJC_CLASS",列出所有Objective-C类。
_objc_msgForward 之类的。这些在逆向分析时很有用,但上架App Store时千万别用,会被拒的。
好了,这一章的内容就这些。IPA的结构、Mach-O的分析、class-dump的使用,这三个点你掌握了,iOS逆向的第一步就算迈出去了。下一章,咱们会深入动态分析,用LLDB和Cycript来调试App。到时候,你会发现——原来逆向可以这么好玩。
公众号:蓝海资料掘金营,微信deep3321