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格式的可执行文件。所有的代码逻辑、类信息、方法调用,都藏在这里面。

我的习惯:拿到IPA后,我通常会先看 Info.plist。里面有个 CFBundleExecutable 字段,直接告诉你哪个文件是可执行文件。省得你瞎猜。

2. Mach-O文件分析:App的“骨架”

Mach-O是iOS和macOS上的可执行文件格式。你可以把它理解成Windows上的PE文件,或者Linux上的ELF文件。

Mach-O的结构,大致分为三部分:

  • Header:文件头,包含CPU架构、文件类型等信息。
  • Load Commands:加载命令,告诉系统怎么加载这个文件。
  • Data:真正的代码和数据,包括多个Segment(段)和Section(节)。

我常用的分析工具是 otoolMachOView。前者是命令行,后者是图形界面。

举个例子,查看Mach-O的Header信息:

otool -h WeChat

输出大概长这样:

Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777228          0  0x00           2    45       5432 0x00200085

这里 magic0xfeedfacf,表示这是64位的Mach-O。如果是32位,就是 0xfeedface。你想想看,这个魔数是不是挺有意思的?

再看Load Commands:

otool -l WeChat | head -50

你会看到很多 LC_SEGMENT_64LC_SYMTAB 之类的命令。其中 LC_SEGMENT_64 定义了各个段在内存中的位置。比如 __TEXT 段放代码,__DATA 段放数据。

避坑指南:我曾经在分析一个App时,发现它的 __TEXT 段被加密了。这种情况多见于那些做了代码混淆或加壳的App。这时候,你需要先脱壳,才能继续分析。常用的脱壳工具有 dumpdecryptedfrida-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文档。

注意:class-dump只能提取Objective-C的类信息。如果App是用Swift写的,或者做了大量的C++混编,那class-dump能提取到的信息就有限了。这时候,你需要用 nmstrings 来辅助分析。

4. 实战:用class-dump分析一个简单App

咱们来走一遍完整的流程。假设你有一个叫 DemoApp.ipa 的文件。

  1. 解压IPAunzip DemoApp.ipa -d ./DemoApp
  2. 找到可执行文件:进入 Payload/DemoApp.app,找到 DemoApp 文件。
  3. 检查架构file DemoApp,看看是arm64还是armv7。
  4. 运行class-dumpclass-dump -H DemoApp -o ./headers
  5. 分析头文件:打开 ./headers 目录,看看有哪些类。

我一般会先看 AppDelegate.h,了解App的启动流程。然后看 ViewController.h,看看主界面有哪些交互。最后,重点关注那些名字里带 ManagerServiceHelper 的类,这些通常是核心逻辑所在。

5. 知识体系总览

下面这张图,帮你理清这一章的核心逻辑:

iOS逆向基础:IPA → Mach-O → class-dump IPA 文件 解压 → Payload/ Mach-O 文件 分析工具:otool / MachOView class-dump 输出:.h 头文件 核心流程:从IPA中提取Mach-O,再用class-dump还原头文件

6. 一些实用技巧

  • 查看所有类名class-dump -A DemoApp,只输出类名,不输出方法。适合快速浏览。
  • 过滤特定类class-dump DemoApp | grep "Manager",只显示包含“Manager”的类。
  • 查看字符串strings DemoApp | grep "http",可以找到网络请求的URL。
  • 查看符号表nm DemoApp | grep "OBJC_CLASS",列出所有Objective-C类。
我的经验:class-dump出来的头文件,有时候会包含一些私有API。比如 _objc_msgForward 之类的。这些在逆向分析时很有用,但上架App Store时千万别用,会被拒的。

好了,这一章的内容就这些。IPA的结构、Mach-O的分析、class-dump的使用,这三个点你掌握了,iOS逆向的第一步就算迈出去了。下一章,咱们会深入动态分析,用LLDB和Cycript来调试App。到时候,你会发现——原来逆向可以这么好玩。


公众号:蓝海资料掘金营,微信deep3321