Hopper

前言

Mach-O 、hopper analysis 分析Mach-O文件的过程

正文

hopper

  • hopper analysis 一个dylib的过程
<!--  -->
Hopper is ready
Mach-O ARMv7 file loaded
Starting background analysis
Analysis segment __TEXT
> analysis section __text
> analysis section __picsymbolstub4
> analysis section __stub_helper
> analysis section __gcc_except_tab
> analysis section __objc_methname
> transform section __objc_methname to C strings
> analysis section __ustring
> analysis section __cstring
> transform section __cstring to C strings
> analysis section __objc_classname
> transform section __objc_classname to C strings
> analysis section __objc_methtype
> transform section __objc_methtype to C strings
Analysis segment __DATA
> analysis section __nl_symbol_ptr
> analysis section __la_symbol_ptr
> analysis section __mod_init_func
> analysis section __const
> analysis section __cfstring
> analysis section __objc_classlist
> analysis section __objc_protolist
> analysis section __objc_imageinfo
> analysis section __objc_const
> analysis section __objc_selrefs
> analysis section __objc_classrefs
> analysis section __objc_superrefs
> analysis section __objc_ivar
> analysis section __objc_data
> analysis section __data
> analysis section __bss
Analysis segment __LINKEDIT
Analysis segment External Symbols
> mark procedures
Analysis of segment __TEXT
> analysis of section __text
> disassemble section __text
> searching for additional procedures in section __text
> searching for additional procedures in section __text
> analysis of section __picsymbolstub4
> disassemble section __picsymbolstub4
> searching for additional procedures in section __picsymbolstub4
> searching for additional procedures in section __picsymbolstub4
> analysis of section __stub_helper
> disassemble section __stub_helper
> searching for additional procedures in section __stub_helper
> searching for additional procedures in section __stub_helper
> analysis of section __gcc_except_tab
> analysis of section __objc_methname
> analysis of section __ustring
> analysis of section __cstring
> analysis of section __objc_classname
> analysis of section __objc_methtype
Analysis of segment __DATA
> analysis of section __nl_symbol_ptr
> analysis of section __la_symbol_ptr
> analysis of section __mod_init_func
> analysis of section __const
> analysis of section __cfstring
> analysis of section __objc_classlist
> analysis of section __objc_protolist
> analysis of section __objc_imageinfo
> analysis of section __objc_const
> analysis of section __objc_selrefs
> analysis of section __objc_classrefs
> analysis of section __objc_superrefs
> analysis of section __objc_ivar
> analysis of section __objc_data
> analysis of section __data
> analysis of section __bss
Analysis of segment __LINKEDIT
Analysis of segment External Symbols
> dataflow analysis of procedures in segment __TEXT
> dataflow analysis of procedures in segment __DATA
> dataflow analysis of procedures in segment __LINKEDIT
> dataflow analysis of procedures in segment External Symbols
> searching for additional procedures in section __text
> searching for additional procedures in section __picsymbolstub4
> searching for additional procedures in section __stub_helper
> searching for additional procedures in section __gcc_except_tab
> searching for additional procedures in section __objc_methname
> searching for additional procedures in section __ustring
> searching for additional procedures in section __cstring
> searching for additional procedures in section __objc_classname
> searching for additional procedures in section __objc_methtype
> searching for additional procedures in section __nl_symbol_ptr
> searching for additional procedures in section __la_symbol_ptr
> searching for additional procedures in section __mod_init_func
> searching for additional procedures in section __const
> searching for additional procedures in section __cfstring
> searching for additional procedures in section __objc_classlist
> searching for additional procedures in section __objc_protolist
> searching for additional procedures in section __objc_imageinfo
> searching for additional procedures in section __objc_const
> searching for additional procedures in section __objc_selrefs
> searching for additional procedures in section __objc_classrefs
> searching for additional procedures in section __objc_superrefs
> searching for additional procedures in section __objc_ivar
> searching for additional procedures in section __objc_data
> searching for additional procedures in section __data
> searching for additional procedures in section __bss
> dataflow analysis of procedures in segment __TEXT
> dataflow analysis of procedures in segment __DATA
> dataflow analysis of procedures in segment __LINKEDIT
> dataflow analysis of procedures in segment External Symbols
Background analysis ended in 10308ms

xcrun

  • 查看section段: 有些 segment 中有多个 section
<!-- devzkndeMacBook-Pro:~ devzkn$ xcrun size -x -l -m tmp -->

tmp (for architecture armv7):
Segment __TEXT: 0x44000 (vmaddr 0x0 fileoff 0)
	Section __text: 0x37ea4 (addr 0x4160 offset 16736)
	Section __picsymbolstub4: 0x4c0 (addr 0x3c004 offset 245764)
	Section __stub_helper: 0x3b4 (addr 0x3c4c4 offset 246980)
	Section __gcc_except_tab: 0x38 (addr 0x3c878 offset 247928)
	Section __objc_methname: 0x2fba (addr 0x3c8b0 offset 247984)
	Section __ustring: 0x1b58 (addr 0x3f86a offset 260202)
	Section __cstring: 0x1e4b (addr 0x413c2 offset 267202)
	Section __objc_classname: 0x32f (addr 0x4320d offset 274957)
	Section __objc_methtype: 0xac2 (addr 0x4353c offset 275772)
	total 0x3fe9e
Segment __DATA: 0x8000 (vmaddr 0x44000 fileoff 278528)
	Section __nl_symbol_ptr: 0x1c8 (addr 0x44000 offset 278528)
	Section __la_symbol_ptr: 0x130 (addr 0x441c8 offset 278984)
	Section __mod_init_func: 0x8 (addr 0x442f8 offset 279288)
	Section __const: 0x538 (addr 0x44300 offset 279296)
	Section __cfstring: 0x1ec0 (addr 0x44838 offset 280632)
	Section __objc_classlist: 0x94 (addr 0x466f8 offset 288504)
	Section __objc_protolist: 0x18 (addr 0x4678c offset 288652)
	Section __objc_imageinfo: 0x8 (addr 0x467a4 offset 288676)
	Section __objc_const: 0x3a40 (addr 0x467ac offset 288684)
	Section __objc_selrefs: 0x714 (addr 0x4a1ec offset 303596)
	Section __objc_classrefs: 0x130 (addr 0x4a900 offset 305408)
	Section __objc_superrefs: 0x84 (addr 0x4aa30 offset 305712)
	Section __objc_ivar: 0x24c (addr 0x4aab4 offset 305844)
	Section __objc_data: 0x5c8 (addr 0x4ad00 offset 306432)
	Section __data: 0x13c (addr 0x4b2c8 offset 307912)
	Section __bss: 0x48 (addr 0x4b404 offset 0)
	total 0x744c
Segment __LINKEDIT: 0x28000 (vmaddr 0x4c000 fileoff 311296)
total 0x74000
tmp (for architecture arm64):
Segment __TEXT: 0x40000 (vmaddr 0x0 fileoff 0)
	Section __text: 0x30c7c (addr 0x6e80 offset 28288)
	Section __stubs: 0x360 (addr 0x37afc offset 228092)
	Section __stub_helper: 0x378 (addr 0x37e5c offset 228956)
	Section __gcc_except_tab: 0x8c (addr 0x381d4 offset 229844)
	Section __objc_methname: 0x2fba (addr 0x38260 offset 229984)
	Section __ustring: 0x1b58 (addr 0x3b21a offset 242202)
	Section __cstring: 0x1e51 (addr 0x3cd72 offset 249202)
	Section __objc_classname: 0x32f (addr 0x3ebc3 offset 256963)
	Section __objc_methtype: 0xb3b (addr 0x3eef2 offset 257778)
	Section __const: 0xc8 (addr 0x3fa30 offset 260656)
	Section __unwind_info: 0x508 (addr 0x3faf8 offset 260856)
	total 0x3917d
Segment __DATA: 0x10000 (vmaddr 0x40000 fileoff 262144)
	Section __got: 0x378 (addr 0x40000 offset 262144)
	Section __la_symbol_ptr: 0x240 (addr 0x40378 offset 263032)
	Section __mod_init_func: 0x10 (addr 0x405b8 offset 263608)
	Section __const: 0x880 (addr 0x405d0 offset 263632)
	Section __cfstring: 0x3d80 (addr 0x40e50 offset 265808)
	Section __objc_classlist: 0x128 (addr 0x44bd0 offset 281552)
	Section __objc_protolist: 0x30 (addr 0x44cf8 offset 281848)
	Section __objc_imageinfo: 0x8 (addr 0x44d28 offset 281896)
	Section __objc_const: 0x6a28 (addr 0x44d30 offset 281904)
	Section __objc_selrefs: 0xe28 (addr 0x4b758 offset 309080)
	Section __objc_classrefs: 0x260 (addr 0x4c580 offset 312704)
	Section __objc_superrefs: 0x108 (addr 0x4c7e0 offset 313312)
	Section __objc_ivar: 0x24c (addr 0x4c8e8 offset 313576)
	Section __objc_data: 0xb90 (addr 0x4cb38 offset 314168)
	Section __data: 0x248 (addr 0x4d6c8 offset 317128)
	Section __bss: 0x90 (addr 0x4d910 offset 0)
	total 0xd994
Segment __LINKEDIT: 0x2c000 (vmaddr 0x50000 fileoff 327680)
total 0x7c000

<!-- 在 segment中,一般都会有多个 section。 -->

它们包含了可执行文件的不同部分。
1、在 __TEXT segment 中,__text section 包含了编译所得到的机器码。
__stubs 和 __stub_helper 是给动态链接器 (dyld) 使用的。通过这两个 section,在动态链接代码中,可以允许延迟链接。

__const (在我们的代码中没有) 是常量,不可变的,就像 __cstring (包含了可执行文件中的字符串常量 – 在源码中被双引号包含的字符串) 常量一样。

2、__DATA segment 中包含了可读写数据

__nl_symbol_ptr 和 __la_symbol_ptr,它们分别是 non-lazy 和 lazy 符号指针

 __const,在这里面会包含一些需要重定向的常量数据

 __bss section 没有被初始化的静态变量

<!-- devzkndeMacBook-Pro:~ devzkn$ otool -t tmp -->
tmp (architecture armv7):
Contents of (__TEXT,__text) section

<!-- devzkndeMacBook-Pro:~ devzkn$ otool -s __TEXT __text tmp -->
tmp (architecture armv7):
Contents of (__TEXT,__text) section

由此可以看出 -t 参数在otool 中是 -s __TEXT __tex的简写

除了hopper ,还有一个工具很强大otool

  • 使用otool 查看反汇编代码 -tv
devzkndeMacBook-Pro:~ devzkn$ otool -tv tmp
tmp (architecture armv7):
(__TEXT,__text) section
-[ initWithTimeOut:::]:
00004160	b0 b5 	push	{r4, r5, r7, lr}
  • __cstring 包含了可执行文件中的字符串常量 – 在源码中被双引号包含的字符串- 方法名
devzkndeMacBook-Pro:~ devzkn$ xcrun otool -v -s __TEXT __cstring tmp
tmp (architecture armv7):
Contents of (__TEXT,__cstring) section
000413c2  [switch ip]  %@!
000413d9  [switch ip]  %@!

<!-- devzkndeMacBook-Pro:~ devzkn$ xcrun otool -v -s __TEXT __const tmp -->

  • 查看某段中某节的命令为: otool -s __TEXT __text 可执行文件。

Mach-O

  • Apple 系统上(包括 MacOS 以及 iOS)的可执行文件格式
<!-- Mach-O 是 Mach object 文件格式的缩写 -->
1、这种文件格式由文件头(Header)、加载命令(Load Commands)以及具体数据(Segment&Section)三部分组成

2、一种用于记录可执行文件、对象代码、共享库、动态加载代码和内存转储的文件格式。作为 a.out 格式的替代品,Mach-O 提供了更好的扩展性,并提升了符号表中信息的访问速度。

使系统能够快速定位其运行环境以及文件类型

  • struct
struct mach_header_64 {
	uint32_t	magic;		/* mach magic number identifier */
	cpu_type_t	cputype;	/* cpu specifier */
	cpu_subtype_t	cpusubtype;	/* machine specifier */
	uint32_t	filetype;	/* type of file */
	uint32_t	ncmds;		/* number of load commands */
	uint32_t	sizeofcmds;	/* the size of all the load commands */
	uint32_t	flags;		/* flags */
	uint32_t	reserved;	/* reserved */
};
  • otool -h
devzkndeMacBook-Pro:~ devzkn$ otool -h tmp
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface      12          9  0x00           6    33       3640 0x00100085
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777228          0  0x00           6    33       4200 0x00100085
devzkndeMacBook-Pro:~ devzkn$ otool -hv tmp
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
   MH_MAGIC     ARM         V7  0x00       DYLIB    33       3640   NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64   ARM64        ALL  0x00       DYLIB    33       4200   NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS

filetype 以及 flags 只列举了几个比较常见的定义,还有其他的详见 EXTERNAL_HEADERS/mach-o/x86_64/loader.h。
/Users/devzkn/Downloads/kevinsoftware/ios-Reverse_Engineering/mac-headers-master/usr/include/mach-o/loader.h

Load Commands

  • Load Commands 是跟在 Header 后面的加载命令区.
<!-- 所有 commands 的大小总和即为 Header->sizeofcmds 字段,共有 Header->ncmds 条加载命令。 -->
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface      12          9  0x00           6    33       3640 0x00100085

  • otool -l
<!-- 看加载命令区 -->
devzkndeMacBook-Pro:~ devzkn$ otool -l tmp
tmp (architecture armv7):
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface      12          9  0x00           6    33       3640 0x00100085

<!--LC_SEGMENT_64  将对应的段中的数据加载并映射到进程的内存空间去 -->
Load command 0
      cmd LC_SEGMENT
  cmdsize 668
  segname __TEXT
   vmaddr 0x00000000
   vmsize 0x00044000

   Load command 1
      cmd LC_SEGMENT
  cmdsize 1144
    segname __DATA
Load command 2
      cmd LC_SEGMENT
  cmdsize 56
  segname __LINKEDIT
   vmaddr 0x0004c000
   vmsize 0x00028000
  fileoff 311296
 filesize 154080
  maxprot 0x00000001
 initprot 0x00000001
   nsects 0
    flags 0x0
Load command 3
          cmd LC_ID_DYLIB
      cmdsize 84
         name /Library/MobileSubstrate/DynamicLibraries/.dylib (offset 24)
   time stamp 1 Thu Jan  1 08:00:01 1970
      current version 1.0.0
compatibility version 1.0.0

Load command 4
            cmd LC_DYLD_INFO_ONLY
        cmdsize 48
     rebase_off 311296

<!-- 符号表信息 -->
Load command 5
     cmd LC_SYMTAB
 cmdsize 24
  symoff 323260
   nsyms 4023
  stroff 372600
 strsize 76988
 <!-- LC_DYSYMTAB符号表  动态符号表信息
 -->
Load command 6
            cmd LC_DYSYMTAB
        cmdsize 80
      ilocalsym 0
<!-- 唯一的 UUID,标示该二进制文件,128bit -->
Load command 7
     cmd LC_UUID
 cmdsize 24
    uuid 5A3F7C11---ADC9-

<!-- 要求的最低系统版本(Xcode中的Deployment Target) -->
Load command 8
      cmd LC_VERSION_MIN_IPHONEOS
  cmdsize 16
  version 9.1
      sdk 10.3

Load command 9
      cmd LC_SOURCE_VERSION
  cmdsize 16
  version 0.0
  <!-- 加密信息   grep cryptid 可以查看是否加密。 -->
Load command 10
          cmd LC_ENCRYPTION_INFO
      cmdsize 20
     cryptoff 16384
    cryptsize 262144
      cryptid 0
<!-- 加载的动态库,包括动态库地址、名称、版本号等 -->
Load command 11
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name /System/Library/PrivateFrameworks/StoreServices.framework/StoreServices (offset 24) 名称
   time stamp 2 Thu Jan  1 08:00:02 1970
      current version 1440.12.0  版本号
compatibility version 1.0.0

Load command 27
          cmd LC_RPATH
      cmdsize 32
         path @executable_path (offset 12)

         Load command 28
          cmd LC_RPATH
      cmdsize 56
         path /Library/MobileSubstrate/DynamicLibraries (offset 12)
Load command 29
          cmd LC_RPATH
      cmdsize 36
         path /var/mobile/frameworks/ (offset 12)

<!-- 函数地址起始表 -->

Load command 30
      cmd LC_FUNCTION_STARTS
  cmdsize 16
  dataoff 322000
 datasize 852

Load command 31
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 322852
 datasize 408
 <!-- 代码签名信息 -->
Load command 32
      cmd LC_CODE_SIGNATURE
  cmdsize 16
  dataoff 449600
 datasize 15776

Segment

Mach-O 文件有多个段(Segment),每个段有不同的功能。然后每个段又分为很多小的 Section。 LC_SEGMENT 意味着这部分文件需要映射到进程的地址空间去

  • 段名
__PAGEZERO: 空指针陷阱段,映射到虚拟内存空间的第一页,用于捕捉对 NULL 指针的引用。


__TEXT: 包含了执行代码以及其他只读数据。该段数据可以 VM_PROT_READ(读)、VM_PROT_EXECUTE(执行),不能被修改。


__DATA: 程序数据,该段可写 VM_PROT_WRITE/READ/EXECUTE。


__LINKEDIT: 链接器使用的符号以及其他表。


LC_DYSYMTAB符号表

LC_DYSYMTAB符号表有非常大的作用,捕获到线上 Crash 或者 卡顿 堆栈的地址信息时,需要进行符号还原,进而确认卡顿、崩溃的具体位置,这个使用就要使用到LC_DYSYMTAB符号表;

  • 结构
struct symtab_command {
    uint32_t    cmd;        /* LC_SYMTAB */
    uint32_t    cmdsize;    /* sizeof(struct symtab_command) */
    uint32_t    symoff;        /* symbol table offset */
    uint32_t    nsyms;        /* number of symbol table entries */
    uint32_t    stroff;        /* string table offset */
    uint32_t    strsize;    /* string table size in bytes */
};

<!-- 符号表在 Mach-O目标文件中的地址可以通过LC_SYMTAB加载命令指定的 symoff找到,对应的符号名称在stroff,总共有nsyms条符号信息 -->

Section

它的结构体跟随在 LC_SEGMENT 结构体之后,LC_SEGMENT 又在 Load Commands 中, segment 的数据内容是跟在 Load Commands 之后的。 /Users/devzkn/Downloads/kevinsoftware/ios-Reverse_Engineering/mac-headers-master/usr/include/mach-o/loader.h

  • 各节的作用
Section 作用
__text: 主程序代码
__stub_helper: 用于动态链接的存根
__symbolstub1: 用于动态链接的存根
__objc_methname: Objective-C 的方法名
__objc_classname: Objective-C 的类名
__cstring: 硬编码的字符串
__lazy_symbol: 懒加载,延迟加载节,通过 dyld_stub_binder 辅助链接
_got: 存储引用符号的实际地址,类似于动态符号表
__nl_symbol_ptr: 非延迟加载节
__mod_init_func: 初始化的全局函数地址,在 main 之前被调用
__mod_term_func: 结束函数地址
__cfstring: Core Foundation 用到的字符串(OC字符串)
__objc_clsslist: Objective-C 的类列表
__objc_nlclslist: Objective-C 的 +load 函数列表,比 __mod_init_func 更早执行
__objc_const: Objective-C 的常量
__data: 初始化的可变的变量
__bss: 未初始化的静态变量
  • Section 是具体有用的数据存放的地方
Section 作用
TEXT.text 只有可执行的机器码
TEXT.cstring 去重后的C字符串(不含中文字符)
TEXT.const 初始化过的常量
TEXT.stubs 符号桩。本质上是一小段会直接跳入lazybinding的表对应项指针指向的地址的代码。
TEXT.stub_helper 辅助函数。上述提到的lazybinding的表中对应项的指针在没有找到真正的符号地址的时候,都指向这。
TEXT.unwind_info 用于存储处理异常情况信息
TEXT.eh_frame 调试辅助信息
DATA.data 初始化过的可变的(静态/全局)数据
DATA.nl_symbol_ptr 非lazy-binding的指针表,每个表项中的指针都指向一个在装载过程中,被动态链机器搜索完成的符号
DATA.la_symbol_ptr lazy-binding的指针表,每个表项中的指针一开始指向stub_helper
DATA.const 没有初始化过的常量
DATA.mod_init_func 初始化函数,在main之前调用
DATA.mod_term_func 终止函数,在main返回之后调用
DATA.bss 没有初始化的(静态/全局)变量
DATA.common 没有初始化过的符号声明
TEXT.ustring utf-8编码后的中文字符串
TEXT.objc_methname OC方法名(不含c方法,所有的方法都在TEXT.text中)
DATA.cfstring 用OC方法创建的字符串,对TEXT段中字符串的引用
DATA.__objc _classlist节 这个节列出了所有的class(metaclass自身也是一种class)。
DATA.__objc _catlist 代表的就是程序里面有哪些Category
DATA.__objc_protolist 代表的就是程序里面有哪些Protocol
DATA.__objc_classrefs 该节是为了标记这个类究竟有没有被引用
DATA.__objc_selrefs 告诉你究竟有哪些SEL对应的字符串被引用了
DATA.__objc_superrefs 在编译期指定方法对应的current_class,以方便后续的superclass方法列表查找
DATA.__objc_const 存放的是一些需要在类加载过程中用到的readonly data

see also

<!-- http://www.aosabook.org/en/llvm.html -->
Chris Lattner 生于 1978 年,2005年加入苹果,将苹果使用的 GCC 全面转为 LLVM。2010年开始主导开发 Swift 语言。

<!-- Clang 是 LLVM 的子项目,是 C,C++ 和 Objective-C 编译器 http://clang.llvm.org/docs/ -->
其中的 clang static analyzer 主要是进行语法分析,语义分析和生成中间代码,当然这个过程会对代码进行检查,出错的和需要警告的会标注出来。

<!-- lld 是 Clang / LLVM 的内置链接器,clang 必须调用链接器来产生可执行文件。 -->

<!--1、 先通过-E查看clang在预编译处理这步做了什么: 包括宏的替换,头文件的导入 -->
clang -E main.m

<!-- 2、预处理完成后就会进行词法分析,这里会把代码切成一个个 Token,比如大小括号,等于号还有字符串等 -->

<!-- 3、然后是语法分析,验证语法是否正确,然后将所有节点组成抽象语法树 AST 。 -->

<!-- 4、IR中间代码的生成:CodeGen 会负责将语法树自顶向下遍历逐步翻译成 LLVM IR,IR 是编译过程的前端的输出后端的输入  -->
1、Pass 教程: http://llvm.org/docs/WritingAnLLVMPass.html

2、如果开启了 bitcode 苹果会做进一步的优化,有新的后端架构还是可以用这份优化过的 bitcode 去生成。
clang -emit-llvm -c main.m -o main.bc

<!-- 5、生成汇编 -->

clang -S -fobjc-arc main.m -o main.s


<!--6、 生成目标文件 -->

clang -fmodules -c main.m -o main.o


<!--7、生成可执行文件-->
clang main.o -o main

<!-- 二、完整步骤: -->

1)编译信息写入辅助文件,创建文件架构 .app 文件


2)处理文件打包信息

3)执行 CocoaPod 编译前脚本,checkPods Manifest.lock

4)编译.m文件,使用 CompileC 和 clang 命令

5)链接需要的 Framework

6)编译 xib

7)拷贝 xib ,资源文件

8)编译 ImageAssets

9)处理 info.plist

10)执行 CocoaPod 脚本

11)拷贝标准库

12)创建 .app 文件和签名

<!-- 三、clang 命令参数 -->

-x 编译语言比如objective-c

-arch 编译的架构,比如arm7

-f 以-f开头的。

-W 以-W开头的,可以通过这些定制编译警告

-D 以-D开头的,指的是预编译宏,通过这些宏可以实现条件编译

-iPhoneSimulator10.1.sdk 编译采用的iOS SDK版本

-I 把编译信息写入指定的辅助文件

-F 需要的Framework

-c 标识符指明需要运行预处理器,语法分析,类型检查,LLVM生成优化以及汇编代码生成.o文件

-o 编译结果

<!-- Build Phases:构建可执行文件的规则 -->
1)指定 target 的依赖项目,在 target build 之前需要先 build 的依赖。在 Compile Source 中指定所有必须编译的文件,

2)在 Link Binary With Libraries 里会列出所有的静态库和动态库,它们会和编译生成的目标文件进行链接。

3)build phase 还会把静态资源拷贝到 bundle 里。

4)可以通过在 build phases 里添加自定义脚本来做些事情,比如像 CocoaPods 所做的那样。





<!-- Build Rules: 指定不同文件类型如何编译  -->

<!-- Build Settings : 在 build 的过程中各个阶段的选项的设置。-->

<!-- 四、Clang Static Analyzer静态代码分析: https://code.woboq.org/llvm/clang/ -->

静态分析前会对源代码分词成 Token,这个过程称为词法分析(Lexical Analysis)


编译的概念(词法->语法->语义->IR->优化->CodeGen) 在 clang static analyzer 里到处可见。

<!-- Token 可以分为以下几类 -->
关键字:语法中的关键字,if else while for 等。

标识符:变量名

字面量:值,数字,字符串

特殊符号:加减乘除等符号

<!-- 语法分析(Semantic Analysis)将 token 先按照语法组合成语义生成 VarDecl 节点,然后将这些节点按照层级关系构成抽象语法树 Abstract Syntax Tree (AST)。 -->


<!-- 五、CodeGen 生成 IR 代码 -->

1)各种类,方法,成员变量等的结构体的生成,并将其放到对应的Mach-O的section中。

2)Non-Fragile ABI 合成 OBJCIVAR$_ 偏移值常量。

3)ObjCMessageExpr 翻译成相应版本的 objc_msgSend,super 翻译成 objc_msgSendSuper。

4)strong,weak,copy,atomic 合成 @property 自动实现 setter 和 getter。

5)@synthesize 的处理。

6)生成 block_layout 数据结构

7)block 和 weak

8)_block_invoke

9)ARC 处理,插入 objc_storeStrong 和 objc_storeWeak 等 ARC 代码。ObjCAutoreleasePoolStmt 转 objc_autorealeasePoolPush / Pop。自动添加 [super dealloc]。给每个 ivar 的类合成 .cxx_destructor 方法自动释放类的成员变量。


<!--  六、IR 结构 -->

LLVM IR 有三种表示格式,第一种是 bitcode 这样的存储格式,以 .bc 做后缀,第二种是可读的以 .ll,第三种是用于开发时操作 LLVM IR 的内存格式

llc 编译器是专门编译 LLVM IR 的编译器用来生成汇编文件。

<!-- Driver -->
Driver 是 Clang 面对用户的接口,用来解析 Option 设置,判断决定调用的工具链,最终完成整个编译过程。

<!-- Translate:Translate 就是把相关的参数对应到不同平台上不同的工具。-->

<!-- 每次编译后生成的 dSYM 文件 -->
dSYM 文件里存储了函数地址映射,这样调用栈里的地址可以通过 dSYM 这个映射表能够获得具体函数的位置。一般都会用来处理 crash 时获取到的调用栈 .crash 文件将其符号化

https://zhangkn.github.io/2018/03/symbolicatecrash/


<!--  -->




<!-- Xcode 中编译器默认选择使用 clang -->
<!-- 编译器处理过程  -->

1、预处理

符号化 (Tokenization)
宏定义的展开
#include 的展开
语法和语义分析

2、将符号化后的内容转化为一棵解析树 (parse tree)
解析树做语义分析
输出一棵抽象语法树(Abstract Syntax Tree* (AST))
生成代码和优化

3、将 AST 转换为更低级的中间码 (LLVM IR)
对生成的中间码做优化
生成特定目标代码
输出汇编代码

4、汇编器

将汇编代码转换为目标对象文件。

5、链接器

将多个目标对象文件合并为一个可执行文件 (或者一个动态库)

<!-- devzkndeMacBook-Pro:~ devzkn$ xcrun size -x -l -m tmp -->
当虚拟内存系统进行映射时,segment 和 section 会以不同的参数和权限被映射。

__TEXT segment 包含了被执行的代码。它被以只读和可执行的方式映射


Segment __DATA: 0x8000 (vmaddr 0x44000 fileoff 278528)
	Section __nl_symbol_ptr: 0x1c8 (addr 0x44000 offset 278528)
	Section __la_symbol_ptr: 0x130 (addr 0x441c8 offset 278984)

__DATA segment 以可读写和不可执行的方式映射。它包含了将会被更改的数据。
__nl_symbol_ptr 和 __la_symbol_ptr,它们分别是 non-lazy 和 lazy 符号指针。

延迟符号指针用于可执行文件中调用未定义的函数,例如不包含在可执行文件中的函数,它们将会延迟加载。而针对非延迟符号指针,当可执行文件被加载同时,也会被加载。




<!-- 2.1:静态分析防护 -->

1.对抗hopper和ida的分析可以修改macho文件的某些偏移量, 让hopper和ida无法分析造成闪退

2.对抗class-dump 和工具分析可以方法名类名混淆,混淆方案大致三种
        1.编译前用脚本批量做宏定义替换
        2.LLVM混淆
        3.对Mach-O__objc_classnamehe __objc_methname

3.逻辑混淆(花指令)

<!-- 2.2:动态分析防护 -->

1.ptrace ,syscall sysctl,dlsym等

<!-- 2.3:动态注入防护 -->

1.__RESTRICT关联main函数: 用getsectiondata关联__RESTRICT

2.dladdr查看函数的内存空间信息, 验证函数的指针来自程序, 还是苹果的库, 还是未知.

<!-- 2.6:重签名防护 -->

1.拿到当前的签名文件的签名信息和编译前的签名信息比对

转载请注明: > Hopper

在操作过程或者文章有问题的话欢迎在 原文 里提问或指正。

赞赏支持

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少
最近的文章

iOSDevelopersRunErrorFrequentlyAskedQuestions

前言 target specifies product type ‘com.apple.product-type.tool’, but there’s no such product type for the ‘iphoneos’ <!-- http://iosre.com/t/com-apple-product-type-tool/7060/4 --><!-- sudo ./configure-xcode-for-ios-development -->...…

iOSre继续阅读
更早的文章

OutlineOfChineseHistory

前言 六个模块 <!-- 古代历史部分 -->1、封建社会、豪族社会、古代平民社会<!-- 近代 -->近代转型、现代革命、中国崛起与世界秩序的互动正文历史学才是正确的未来学思考未来的时候,最重要的事情是对未来目标的设定-》理解自己、世界的过去,搞清楚自己的位置 历史的功用 <!-- 通过过去看到未来 --> 理解中国和世界关系的变迁过程 <!-- 时间和空间两条线索 -->1、从内部来说,中国一直是一个超...…

OutlineOfChineseHistory继续阅读
更多