[iOS逆向]5、Mach-O
1、定义
Mach-O其实是Mach Object文件格式的缩写,是mac以及iOS上可执行文件的格式, 类似于windows上的PE格式 (Portable Executable ), linux上的elf格式 (Executable and Linking Format)
1.1、clang下的Mach-O
1、创建文件test.c
#include <stdio.h>
int main() {
printf("Hello world\n");
return;
}
clang -c test.c
file test.o
test.o: Mach-O 64-bit object arm64
clang test.o
file a.out
a.out: Mach-O 64-bit executable arm64
./a.out
Hello world
2、指定生成test2文件
clang -o test2 test.c
3、将多个文件合并成一个文件
test1.c
#include <stdio.h>
void test1();
int main() {
printf("test\n");
test1();
return 0;
}
test2.c
#include <stdio.h>
void test1() {
printf("test1\n");
}
直接生成目标文件
clang -o demo test1.c test2.c
./demo
test
test1
生成中间文件
clang -c demo1 test1.c test2.c
4、查看demo中的mach-o信息
objdump --macho -d demo
100003f48: ff 83 00 d1 sub sp, sp, #32
100003f4c: fd 7b 01 a9 stp x29, x30, [sp, #16]
100003f50: fd 43 00 91 add x29, sp, #16
100003f54: 08 00 80 52 mov w8, #0
100003f58: e8 0b 00 b9 str w8, [sp, #8]
100003f5c: bf c3 1f b8 stur wzr, [x29, #-4]
100003f60: 00 00 00 90 adrp x0, 0 ; 0x100003000
100003f64: 00 a0 3e 91 add x0, x0, #4008 ; literal pool for: "test\n"
100003f68: 0d 00 00 94 bl 0x100003f9c ; symbol stub for: _printf
100003f6c: 05 00 00 94 bl _test1
100003f70: e0 0b 40 b9 ldr w0, [sp, #8]
100003f74: fd 7b 41 a9 ldp x29, x30, [sp, #16]
100003f78: ff 83 00 91 add sp, sp, #32
100003f7c: c0 03 5f d6 ret
_test1:
100003f80: fd 7b bf a9 stp x29, x30, [sp, #-16]!
100003f84: fd 03 00 91 mov x29, sp
100003f88: 00 00 00 90 adrp x0, 0 ; 0x100003000
100003f8c: 00 b8 3e 91 add x0, x0, #4014 ; literal pool for: "test1\n"
100003f90: 03 00 00 94 bl 0x100003f9c ; symbol stub for: _printf
100003f94: fd 7b c1 a8 ldp x29, x30, [sp], #16
100003f98: c0 03 5f d6 ret
2、Mach-O文件格式
2.1、Mach-O文件格式定义
Mach-O为Mach object文件格式的缩写,它是一种用于可执行文件、目标代码、动态库的文件格式。作为a.out格式的替代,Mach-O提供了更强的扩展性。
2.2、MachO格式的常见文件
1、目标库
.o
2、库文件
.a
、.dylib
、.Framework
3、可以执行文件
dyld
、.dsym
3、lipo命令
3.1、通用二进制文件(Universial binary)
苹果公司提出的一种程序代码。能同时适用多种架构的二进制文件.
同一个程序包中同时为多种架构提供最理想的性能。
3.2、lipo
1、查看MachO文件包含的架构
lipo -info xxxx
2、用lipo –thin 拆分某种架构
lipo MachO文件 –thin 架构 –output 输出文件路径
3、使用lipo -create 合并多种架构
lipo -create MachO1 MachO2 -output 输出文件路径
4、Mach-O文件结构
mach-o4.1、Header 包含该二进制文件的一般信息
1、字节顺序、架构类型、加载指令的数量等
2、使得可以快速确认一些信息,比如当前文件用于32位还是64位,对应的处理器是什么、文件类型是什么
mach-o header
- magic 魔数,快速定位属于64位还是32位
- cputype CPU类型,比如ARM
- cpusubtype CPU的具体类型 arm64、armv7
- filetype 文件类型,比如可执行文件
- ncmds loadCommands条数
- sizeofcmds loadCommands的大小
- flags 标志位标识二进制文件支持的功能。主要是系统文件加载、链接有关
- reserved 保留
4.2、Load commands 一张包含很多内容的表
内容包括区域的位置、符号表、动态符号表等
1、将文件中(32位或64位)的段映射到进程地址空间中
- VM Address 虚拟内存地址
- VM Size 虚拟内存大小
- File Offset数据在文件中的偏移地址
- File Size数据在文件中的大小
2、LC_DYLD_INFO_ONLY 动态链接相关信息
LC_DYLD_INFO_ONLY
- Rebase Info Size 程序重定向大小。
- Rebase Info Offset 函数的开始地址值 。
- Binding Info Size 外部符号的绑定大小。
3、LC_SYMTAB 符号表地址
LC_SYMTAB
4、LC_DYSYMTAB 动态符号表地址
LC_DYSYMTAB
5、LC_LOAD_DYLINKER 动态链接库
6、LC_SOURCE_VERSION 代码版本
7、LC_MAIN main函数入口
8、LC_ENCRYPTION_INFO_64 加密信息
9、LC_RPATH 动态库framwork的地址
10、LC_FUNCTION_STARTS 函数的起始位置表
11、LC_DATA_IN_CODE
12、LC_CODE_SIGNATURE 代码签名
4.3、Data 通常是对象文件中最大的部分
包含Segement的具体数据
1、Section64(__TEXT,__text) 主程序的入口
2、Section64(__TEXT,__stubs) 符号绑定
3、Section64(__TEXT,__objc_methname) 方法名称
4、Section64(__TEXT,__objc_classname) 类名
5、Section64(__TEXT,__objc_methtype) 方法类型(方法签名)
6、Section64(__TEXT,__cstring) 常量
7、Section64(__DATA,__got) 启动时绑定
查看fat文件信息
otool -f Demo