逆向App的基本步骤
界面分析
Cycript、Reveal
代码分析
对Mach-O文件的静态分析
MachOView、class-dump、Hopper Disassembler、ida等
动态调试
对运行中的APP进行代码调试
debugserver、LLDB
4.代码编写
注入代码到APP中
必要时还可能需要重新签名、打包ip
class-dump
class-dump的作用是把Mach-O文件的class信息给dump出来(把类信息给导出来),生成对应的.h头文件。下载完工具包后将class-dump文件复制到Mac的/usr/local/bin目录,这样在终端就能识别class-dump命令了。
命令格式为:
class-dump -H Mach-O文件路径 -o 头文件存放目录
-H表示要生成头文件
-o用于制定头文件的存放目录
Hopper Disassmbler
Hopper Disassmbler能够将Mach-O文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码。
正常情况下,OC代码编译后生成汇编代码,汇编代码编译后再生成机器码,而汇编代码和机器码是一一对应的,所以可以通过机器码反编译成汇编代码,但是OC代码和汇编代码不是一一对应的,所以只能生成OC的伪代码。
Hopper Disassmbler直接在网上下载安装就可以了。安装好了之后,打开Hopper Disassmble,将App的Mach-O可执行文件拖进去就自动分析并生成伪代码。
怎么找到App的Mach-O可执行文件呢?
将App的安装问价ipa的扩展名改成zip,然后解压缩,找到Payload里面的文件,右击显示包内容,在里面找到和ipa文件名相同的可执行文件,就是Mach-O可执行文件。
我们通常也想反汇编一下系统库文件,那么系统库的Mach-O可执行文件又在哪里呢?
系统动态库缓存
从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache)。缓存文件路径:/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX。dyld_shared_cache_armX的X代表ARM处理器指令集架构。
v6
iPhone、iPhone3G、iPod Touch、iPod Touch2
v7
iPhone3GS、iPhone4、iPhone4S、iPad、iPad2、iPad3(The New iPad)
iPad mini、iPod Touch3G、iPod Touch4、iPod Touch5
v7s
iPhone5、iPhone5C、iPad4
arm64
iPhone5S、iPhone6、iPhone6 Plus、iPhone6S、iPhone6S Plus
iPhoneSE、iPhone7、iPhone7 Plus、iPhone8、iPhone8 Plus、iPhoneX
iPad5、iPad Air、iPad Air2、iPad Pro、iPad Pro2
iPad mini with Retina display、iPad mini3、iPad mini4、iPod Touch6
iPhone XR、iPhone XS
注意:
所有指令集原则上都是向下兼容的
动态库共享缓存一个非常明显的好处是节省内存
现在的ida、Hopper反编译工具都可以识别动态库共享缓存
在Mac\iOS中,是使用了/usr/lib/dyld程序来加载动态库,dyld源码地址。dyld全称为dynamic link editor,动态链接编辑器。
由于系统动态库缓存文件比较大,我们通常只需要分析其中的某个系统库(例如UIKit库),我们可以将这个系统动态库缓存文件拆分成一个个的系统库Mach-O文件。具体做法如下:
可找到dyld源码中的launch-cache/dsc_extractor.cpp
将#if 0前面的代码删除(包括#if 0),把最后一行的#endif也删掉
编译dsc_extractor.cpp
clang++ -o dsc_extractor dsc_extractor.cpp
使用dsc_extractor
./dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的文件夹
什么是Mach-O
Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式
属于Mach-O格式的文件类型有如下类型,可以在xnu源码
中,查看到Mach-O格式的详细定义。具体是在EXTERNAL_HEADERS/mach-o/loader.h文件中。
#define MH_OBJECT 0x1 /* relocatable object file */
#define MH_EXECUTE 0x2 /* demand paged executable file */
#define MH_FVMLIB 0x3 /* fixed VM shared library file */
#define MH_CORE 0x4 /* core file */
#define MH_PRELOAD 0x5 /* preloaded executable file */
#define MH_DYLIB 0x6 /* dynamically bound shared library */
#define MH_DYLINKER 0x7 /* dynamic link editor */
#define MH_BUNDLE 0x8 /* dynamically bound bundle file */
#define MH_DYLIB_STUB 0x9 /* shared library stub for static */
/* linking only, no section contents */
#define MH_DSYM 0xa /* companion file with only debug */
/* sections */
#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */
常见的Mach-O文件
MH_OBJECT
目标文件(.o)
静态库文件(.a),静态库其实就是N个.o合并在一起
MH_EXECUTE:可执行文件
.app/News
MH_DYLIB:动态库文件
.dylib
.framework/xx
MH_DYLINKER:动态链接编辑器
/usr/lib/dyld
MH_DSYM:存储着二进制文件符号信息的文件
.dSYM/Contents/Resources/DWARF/xx(常用于分析APP的崩溃信息)
我们可以在Xcode中查看target的Mach-O文件类型。
Build Settings->Linking->Mach-O Type
Mach-O文件的结构
Mach-O基本结构.png
Mach-O文件的结构如上图,可以参考官方描述。一个Mach-O文件包含3个主要区域。
Header
文件类型、目标架构类型等
Load commands
描述文件在虚拟内存中的逻辑结构、布局
Raw segment data
在Load commands中定义的Segment的原始数据
我们可以使用工具查看Mach-O文件的结构。
命令行工具file
file:查看Mach-O的文件类型
file 文件路径
命令行工具otool
查看Mach-O特定部分和段的内容
命令行工具lipo
常用于多架构Mach-O文件的处理
查看架构信息:lipo -info 文件路径
导出某种特定架构:lipo 文件路径 -thin 架构类型 -output 输出文件路径
合并多种架构:lipo 文件路径1 文件路径2 -output 输出文件路径
GUI工具
MachOView
Universal Binary(通用二进制文件)
同时适用于多种架构的二进制文件
包含了多种不同架构的独立的二进制文件
因为需要储存多种架构的代码,通用二进制文件通常比单一平台二进制的程序要大
由于两种架构有共同的一些资源,所以并不会达到单一版本的两倍之多
由于执行过程中,只调用一部分代码,运行起来也不需要额外的内存
因为文件比原来的要大,也被称为“胖二进制文件”(Fat Binary)
dyld和Mach-O
dyld用于加载以下类型的Mach-O文件
MH_EXECUTE
MH_DYLIB
MH_BUNDLE
APP的可执行文件、动态库都是由dyld负责加载的