简介
Mach-O是iOS/OS可执行文件。编译成功后,找到app文件->显示包内容,即可找到可执行文件。
常用指令
- 查看Mach-O格式
lipo -info <可执行文件>
- 查看Mach-O架构
lipo -info <可执行文件>
- 查看Mach-O的Header
otool -h <可执行文件>
otool -hv <可执行文件>
- 查看Mach-O的Load Commands
otool -lv <可执行文件>
Mach-O文件读取工具MachOView
Mach-O文件解析
- Mach64Header
magic(魔数):0xfeedface-32位、0xfeedfacf-64位、0xcafebabe-通用格式
(魔数的读取:32位为小端读取,低地址在低位,高地址在高位、64位为大端读取,低地址在高位,高地址在低位)
cputype、cpusubtype:CPU的平台与版本
armv7:cputype-12、cpusubtype-9
arm64:cputype-16777228、cupsubtype-0
filetype:可执行文件(2)、库文件、Core、内核扩展
OBJECT(目标文件)-1、EXECUTE(可执行文件)-2、DYLIB(动态库)-6
ncmds、sizeofcmds:Load Commands的个数和长度
flags:dyld加载时需要的标志位,PIE表示开启地址空间随机化
Reserved:只有64位时才存在
-
Load Commands
LC_SEGMENT/LC_SEGMENT_64 - 将文件中(32位或64位)的段映射到进程地址空间中
LC_SYMTAB - 符号表信息
LC_DYSYMTAB - 动态符号表信息
LC_LOAD_DYLINKER - 加载动态链接器(/usr/lib/dyld)
LC_UUID - 文件的唯一标识,crash解析中也会有,去匹配dysm文件和crash文件
LC_VERSION_MIN_IPHONEOS - 二进制文件要求最低操作系统版本
LC_MAIN - 设置程序主线程的入口地址和栈大小
LC_ENCRYPTION_INFO - 加密信息,查看文件加密信息(otool -l <可执行文件> | grep cryptid)
LC_LOAD_DYLIB - 加载的动态库,包括动态库地址和名称,当前版本号,兼容版本号(otool -l <可执行文件>)
LC_FUNCTION_STARTS - 函数起始地址表
LC_CODE_SIGNATURE - 代码签名信息
main函数地址查看
某些Segment中包含Section,Section是具体数据存放的地方
__TEXT中节分类:
__text - 主程序代码
__stub_helper - 用于动态链接的存根
__picsymbolstub4 - 用于动态链接的存根
__objc_methname - Object-C的方法名
__objc_classname - Object-C的类名
__objc_methtype - Object-C的方法类型
__cstring - 字符串
指令查看节的信息
otool -s __TEXT __text <可执行文件>
显示最上面的10行数据
otool -tv <可执行文件名> |head -n 10
__DATA中节分类:
__la_symbol_ptr - 延迟加载节,通过dyld_stub_binder辅助链接(程序在加载时,符号的地址没有对应到真实的地址,只有在第一次使用这个符号时,才会去匹配这个符号的地址,第二次使用时就可以直接找到)
__nl_symbol_ptr - 非延迟加载节(程序在加载时,符号的地址已经确定下来,使用时可以直接找到)
__mod_init_func - 初始化的全局函数的地址,会在main函数之前执行
__mod__term_func - 结束函数地址
__cfstring - Core Foundation用到的字符串
__objc_classlist - Object-C的类列表
__objc_protollist - 协议的列表
__objc_nlclslist - Object-C的load函数列表,比__mod_init_func更早执行
__objc_const - Object-C的常量
__data - 初始化的可变的变量
__bss - 未初始化的静态变量
- 查看可执行文件签名信息
codesign -dvvv <可执行文件名>
Mach-O解析案例
-
主程序代码__text真实偏移的计算(以armv7为例)
将可执行文件,拖入Mach-OView中
armv7起始偏移:16384->0x4000
Section Header偏移:24936->0x6168
Section(__TEXT,__text)真实偏移:0x4000+0x6168->0xA168 - 通过Mach-O查看类名、方法名、字符串
新建类MyObject,然后编译,将mach-o文件拖入MachOView中
#import "MyObject.h"
@implementation MyObject
- (void)my_init {
char *cStr = "c string is there";
NSString *ocStr = @"oc String is there";
}
@end
新建的类
新增的方法
代码中的字符串
__DATA,_cfstring中只有oc的字符串
生活如此美好,今天就点到为止。。。