MacOS IOS Mach-O修改补丁之增加外部未定义符号并调用

1. Mach-O的文件的基本结构如下:


 

2.例子文件所有头部:

Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
   MH_MAGIC     ARM         V7  0x00      OBJECT     5       1960 SUBSECTIONS_VIA_SYMBOLS
Load command 0
      cmd LC_SEGMENT
  cmdsize 1824
  segname 
   vmaddr 0x00000000
   vmsize 0x0003e3b4
  fileoff 1988
 filesize 252337
  maxprot rwx
 initprot rwx
   nsects 26
    flags (none)
Section
  sectname __text
   segname __TEXT
      addr 0x00000000
      size 0x0000922c
    offset 1988
     align 2^4 (16)
    reloff 254328
    nreloc 1670
      type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
 reserved1 0
 reserved2 0
Section
  sectname __gcc_except_tab
   segname __TEXT
      addr 0x0000922c
      size 0x00000330
    offset 39408
     align 2^2 (4)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __StaticInit
   segname __TEXT
      addr 0x0000955c
      size 0x000001c4
    offset 40224
     align 2^2 (4)
    reloff 267688
    nreloc 90
      type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
 reserved1 0
 reserved2 0
Section
  sectname __common
   segname __DATA
      addr 0x0003d9b1
      size 0x00000820
    offset 0
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_ZEROFILL
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __cstring
   segname __TEXT
      addr 0x00009720
      size 0x00000222
    offset 40676
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_CSTRING_LITERALS
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __bss
   segname __DATA
      addr 0x0003e1d4
      size 0x000001e0
    offset 0
     align 2^2 (4)
    reloff 0
    nreloc 0
      type S_ZEROFILL
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __data
   segname __DATA
      addr 0x00009950
      size 0x00000130
    offset 41236
     align 2^4 (16)
    reloff 268408
    nreloc 71
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __const
   segname __DATA
      addr 0x00009a80
      size 0x00000114
    offset 41540
     align 2^2 (4)
    reloff 268976
    nreloc 67
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __const
   segname __TEXT
      addr 0x00009ba0
      size 0x00000098
    offset 41828
     align 2^4 (16)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __mod_init_func
   segname __DATA
      addr 0x00009c38
      size 0x00000004
    offset 41980
     align 2^2 (4)
    reloff 269512
    nreloc 1
      type S_MOD_INIT_FUNC_POINTERS
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __bitcode
   segname __LLVM
      addr 0x00009c40
      size 0x00023e10
    offset 41988
     align 2^4 (16)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __cmdline
   segname __LLVM
      addr 0x0002da50
      size 0x00000066
    offset 188948
     align 2^4 (16)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __debug_str
   segname __DWARF
      addr 0x0002dab6
      size 0x00001ab5
    offset 189050
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __debug_loc
   segname __DWARF
      addr 0x0002f56b
      size 0x00000000
    offset 195887
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __debug_abbrev
   segname __DWARF
      addr 0x0002f56b
      size 0x000000c3
    offset 195887
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __debug_info
   segname __DWARF
      addr 0x0002f62e
      size 0x00004cb0
    offset 196082
     align 2^0 (1)
    reloff 269520
    nreloc 1916
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __debug_ranges
   segname __DWARF
      addr 0x000342de
      size 0x00001ea8
    offset 215714
     align 2^0 (1)
    reloff 284848
    nreloc 1426
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __debug_macinfo
   segname __DWARF
      addr 0x00036186
      size 0x00000001
    offset 223562
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __apple_names
   segname __DWARF
      addr 0x00036187
      size 0x00002974
    offset 223563
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __apple_objc
   segname __DWARF
      addr 0x00038afb
      size 0x00000024
    offset 234175
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __apple_namespac
   segname __DWARF
      addr 0x00038b1f
      size 0x00000024
    offset 234211
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __apple_types
   segname __DWARF
      addr 0x00038b43
      size 0x0000002c
    offset 234247
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __apple_exttypes
   segname __DWARF
      addr 0x00038b6f
      size 0x00000024
    offset 234291
     align 2^0 (1)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __nl_symbol_ptr
   segname __DATA
      addr 0x00038b94
      size 0x00000034
    offset 234328
     align 2^2 (4)
    reloff 0
    nreloc 0
      type S_NON_LAZY_SYMBOL_POINTERS
attributes (none)
 reserved1 0 (index into indirect symbol table)
 reserved2 0
Section
  sectname __debug_frame
   segname __DWARF
      addr 0x00038bc8
      size 0x00000da0
    offset 234380
     align 2^2 (4)
    reloff 296256
    nreloc 217
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Section
  sectname __debug_line
   segname __DWARF
      addr 0x00039968
      size 0x00004049
    offset 237868
     align 2^0 (1)
    reloff 297992
    nreloc 2
      type S_REGULAR
attributes DEBUG
 reserved1 0
 reserved2 0
Load command 1
      cmd LC_VERSION_MIN_IPHONEOS
  cmdsize 16
  version 9.0
      sdk n/a
Load command 2
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 298008
 datasize 968
Load command 3
     cmd LC_SYMTAB
 cmdsize 24
  symoff 299028
   nsyms 417
  stroff 304032
 strsize 17752
Load command 4
            cmd LC_DYSYMTAB
        cmdsize 80
      ilocalsym 0
      nlocalsym 69
     iextdefsym 69
     nextdefsym 236
      iundefsym 305
      nundefsym 112
         tocoff 0
           ntoc 0
      modtaboff 0
        nmodtab 0
   extrefsymoff 0
    nextrefsyms 0
 indirectsymoff 298976
  nindirectsyms 13
      extreloff 0
        nextrel 0
      locreloff 0
        nlocrel 0

3. 外部符号也是符号表的一部分,符号表包括了三种的符号的(nlocalsym + nextdefsym + nundefsym),如外部符号是N_DEF, N_EXT.

Load command 3
     cmd LC_SYMTAB
 cmdsize 24
  symoff 299028
   nsyms 417
  stroff 304032
 strsize 17752
Load command 4
            cmd LC_DYSYMTAB
        cmdsize 80
      ilocalsym 0
      nlocalsym 69    // 个数
     iextdefsym 69   
     nextdefsym 236   // 个数
      iundefsym 305
      nundefsym 112   // 个数
         tocoff 0
           ntoc 0
      modtaboff 0
        nmodtab 0
   extrefsymoff 0
    nextrefsyms 0
 indirectsymoff 298976
  nindirectsyms 13
      extreloff 0
        nextrel 0
      locreloff 0
        nlocrel 0

如可以看到 nlocalsym + nextdefsym + nundefsym = nsyms 

 69  + 236 + 112  =  417

 

 stroff 304032 <---这个是符号字符串的文件偏移

 

一个符号的定义结构如下:


/*
 * Format of a symbol table entry of a Mach-O file for 32-bit architectures.
 * Modified from the BSD format.  The modifications from the original format
 * were changing n_other (an unused field) to n_sect and the addition of the
 * N_SECT type.  These modifications are required to support symbols in a larger
 * number of sections not just the three sections (text, data and bss) in a BSD
 * file.
 */
struct nlist {
	union {
#ifndef __LP64__
		char *n_name;	/* for use when in-core */
#endif
		uint32_t n_strx;	/* index into the string table */
	} n_un;
	uint8_t n_type;		/* type flag, see below */
	uint8_t n_sect;		/* section number or NO_SECT */
	int16_t n_desc;		/* see <mach-o/stab.h> */
	uint32_t n_value;	/* value of this symbol (or stab offset) */
};

/*
 * This is the symbol table entry structure for 64-bit architectures.
 */
struct nlist_64 {
    union {
        uint32_t  n_strx; /* index into the string table */
    } n_un;
    uint8_t n_type;        /* type flag, see below */
    uint8_t n_sect;        /* section number or NO_SECT */
    uint16_t n_desc;       /* see <mach-o/stab.h> */
    uint64_t n_value;      /* value of this symbol (or stab offset) */
};

n_strx是str的一个偏移, 如取一个符号可以这样计算:

   stroff+ n_strx = 304032 + 16907 = 320939 , 

320939(0x4E5AB) 即就是一个符号的文件偏移.

 

 

如图0x4E5AB即是GCC_except_table6这个符号的字符串了。

 

下面是外部符号

stroff+ n_strx = 304032 + 0x199A = 320939 (0x4BD3A)

符号是零结束的字符串. 

 

我们要加增一个外部符号,需要做以下的修改:

LC_SYMTAB:

   nsyms 417   --> 417+1 = 418
  stroff 304032 --> 304032+12 = 304044(0x4A3AC)
 strsize 17752 -->17752 + strlen("CreateIphonePathFileSystem")(26)+1 =  17779(0x4573)

 

LC_DYSYMTAB:

      nundefsym 112 --> 112 +1  == 113

计算插入符号结构的偏移

  symoff 299028 

299028  + 417 * 12  = 304032

插入12字节

58450000 01000000 00000000

 

在文件未尾插入新的符号。

CreateIphonePathFileSystem

结果如下:

 

 

 

至此,符号已经加上。

下面加入调用的指令

 

关于ARM的B,BL跳转指令
.text:00001260 A3 04 00 EB                             BL      sub_24F4
 

echo "obase=2;ibase=16;EB0004A3" | bc

11101011000000000000010010100011

COND  OP     S  Rd   Rn   shifter_operand
1110 1011000 0 0000 0000 010010100011

操作数转成16进制
echo "obase=16;ibase=2;010010100011" | bc
4A3


2.外部引用跳转例子A

指令:
0000687C CF DE 00 EB                             BL              _UnityApplicationDir
0003E3C0 ??                                      IMPORT _UnityApplicationDir

转成二进制:
echo "obase=2;ibase=16;EB00DECF" | bc 
1110 101100 0 0000 0110 1111011001111
                    110 1111011001111 <---跳转偏移

计算偏移:
(0003E3C0 - 0000687C -8)/4 =  0xDECF 

echo "obase=2;ibase=16;DECF" | bc 
110 1111011001111  <---即Rn和shifter_operand



2.外部引用跳转例子B

000068D4 BB DE 00 EB                             BL              _UnityLibraryDir
0003E3C8 ??                                      IMPORT _UnityLibraryDir 


$ echo "obase=2;ibase=16;EB00DECF" | bc 
1110 101100 0 0000 0110 1111011001111

$ echo "obase=16;ibase=2;1101111010111011" | bc
DEBB


(0003E3C8-000068D4-8)/4 = DEBB

 

当前地址+ (偏移 << 2 + 8) = 目标地址

0x1260 + 0x4A3 * 4 + 8 = 24F4

偏移 = (目标地址 - 当前地址 - 8) >> 2

偏移 = (0x24F4 - 0x1260 - 8) / 4 = 0x4A3

假设跳转指令处的地址是A,跳转目标处的地址是B.
B,BL指令保存的是偏移地址,这个地址的计算方法是:
1.B-(A+8).A+8是因为ARM的流水线使得指令执行到A处时,PC实际的值是A+8.
2.第一步得到的值是4的倍数,因为ARM的指令是4对齐的,即最低两位为00.于是将这个值右移两位.
3.得到最终偏移

执行时:
1.取出偏移
2.左移两位
3.加入PC,这时PC的值刚好为目标处的地址值,即目标地址指令进入取指,流水线前两级被清空

 

根据上面的原理,进行armv7 32bit的.o文件进行调用修改, 过程如下:






__text:000009EC 1D FF FF EA                             B               __ZN10FileSystemC2ERK10MemLabelId

1110 1010111 1 1111 1111 111100011101


__text:00000800 28 00 A0 E3                             MOV             R0, #0x28 ; '('
__text:00000804 49 F7 00 EB                             BL              __ZnwmRK10MemLabelIdmPKci ; operator new(ulong,MemLabelId 
__text:00000808 84 13 08 E3 03 10 40 E3                 MOV             R1, #(__ZTV20LocalFileSystemPosix_ptr - loc_81C)
__text:00000810 9C 23 08 E3                             MOV             R2, #:lower16:(_kMemString_ptr - loc_824)
__text:00000814 01 10 9F E7                             LDR             R1, [PC,R1] ; __ZTV20LocalFileSystemPosix_ptr ...
__text:00000818 03 20 40 E3                             MOVT            R2, #:upper16:(_kMemString_ptr - loc_824)
__text:0000081C 02 20 9F E7                             LDR             R2, [PC,R2] ; _kMemString
__text:00000820 08 10 81 E2                             ADD             R1, R1, #8
__text:00000824 00 10 80 E5                             STR             R1, [R0]
__text:00000828 00 10 A0 E3                             MOV             R1, #0
__text:0000082C 04 10 80 E5                             STR             R1, [R0,#4]
__text:00000830 18 10 80 E5                             STR             R1, [R0,#0x18]
__text:00000834 00 0B D2 ED                             VLDR            D16, [R2]
__text:00000838 1C 3F 08 E3 00 30 40 E3                 MOV             R3, #(aRuntimeVirtual - loc_850) ; "./Runtime/VirtualFileSystem/
__text:00000840 08 20 92 E5                             LDR             R2, [R2,#8]
__text:00000844 28 41 09 E3                             MOV             R4, `vtable for'LocalFileSystemiPhone
__text:00000848 03 30 8F E0                             ADD             R3, PC, R3 ; "./Runtime/VirtualFileSystem/VirtualFile"...
__text:0000084C 00 40 40 E3                             MOVT            R4, vtable for'LocalFileSystemiPhone
__text:00000854 04 40 8F E0                             ADD             R4, PC, R4 ; `vtable for'LocalFileSystemiPhone
__text:00000858 07 0B C0 ED                             VSTR            D16, [R0,#0x1C]
__text:0000085C 08 10 C0 E5                             STRB            R1, [R0,#8]
__text:00000860 08 20 84 E2                             ADD             R2, R4, #8
__text:00000864 00 20 80 E5                             STR             R2, [R0]
__text:00000868 08 20 9D E5                             LDR             R2, [SP,#8] --> load This
__text:0000086C 04 00 82 E5                             STR             R0, [R2,#4]  --> this->0x4
__text:00000870 00 00 82 E5                             STR             R0, [R2]   -->this->0x0


改成

__text:00000804          5D F7 00 EB                 BL CreateIphonePathFileSystem
__text:00000808 		 16 00 00 EA                B  00000868

//.....
__text:00000868 08 20 9D E5                             LDR             R2, [SP,#8] --> load This
__text:0000086C 04 00 82 E5                             STR             R0, [R2,#4]  --> this->0x4
__text:00000870 00 00 82 E5                             STR             R0, [R2]   -->this->0x0


UNDEF:0003E580                 IMPORT CreateIphonePathFileSystem


过程:
1. 计算调用外部函数:

(0003E580-00000804 -8)/4 = 0xF75D
$ echo "obase=2;ibase=16;F75D" | bc 
1111011101011101



1110 1011000 0 0000 1111 011101011110

echo "obase=16;ibase=2;11101011000000001111011101011101" | bc
EB00F75D

指令为: 5D F7 00 EB 



2. 计算跳转:

(00000868 - 00000808 -8)/4 = 0x16
echo "obase=2;ibase=16;16" | bc 
10110


07 00 00 EA     B loc_9BC
echo "obase=2;ibase=16;EA000007" | bc 
11101010000000000000000000000110
$ echo "obase=16;ibase=2;11101010000000000000000000010110" | bc
EA000016


 

对于0804这个事实上是受重定位表影响的,我们不能直接像上面那样修改,详情如下图:

实际在0804这个地址的原始数并非 反编译看到那些数据49 F7 00 EB ,而是FD FD FF EB,  这个重定位的类型是BR24, 应该是说在加载的时候直接修改这条指令的低24bit.

这个数据结构:


/*
 * Format of a relocation entry of a Mach-O file.  Modified from the 4.3BSD
 * format.  The modifications from the original format were changing the value
 * of the r_symbolnum field for "local" (r_extern == 0) relocation entries.
 * This modification is required to support symbols in an arbitrary number of
 * sections not just the three sections (text, data and bss) in a 4.3BSD file.
 * Also the last 4 bits have had the r_type tag added to them.
 */
struct relocation_info {
   int32_t	r_address;	/* offset in the section to what is being
				   relocated */
   uint32_t     r_symbolnum:24,	/* symbol index if r_extern == 1 or section
				   ordinal if r_extern == 0 */
		r_pcrel:1, 	/* was relocated pc relative already */
		r_length:2,	/* 0=byte, 1=word, 2=long, 3=quad */
		r_extern:1,	/* does not include value of sym referenced */
		r_type:4;	/* if not 0, machine specific relocation type */
};

即如果是外部符号的话 , r_symbolnum的低24bit,  即是符号的下标。


从上图的strlen我们进行计算 

5d00019F & FFFFFF  = 00019F  = 415

 rawoff = 0x49014 + 415*12 = 0x4A388

 

因此我们只需要修改一下重定位就可以了,即是,把0804的重定位到一个external符号

原来的:

0410F8:    00000804  

0410FC:   5D0018D   //397

 rawoff = 0x49014 + 397*12 = 0x4A388

修改的:

0410F8:    00000804  

0410FC:   5D001A1   //417

 rawoff = 0x49014 + 417*12 = 0x4A3A0

 

修改两处后,工作完成.

结果如下两图:

 

ARM64基本上一样,符号表比arm32位多了4个字节.

基本上按上面的流程处理就可以增另一个外部调用的符号表.

指令方面有些不一样的,但这个和32bit是一样结构编码的,如上图。

 

ARM64 BL和B指令, 跳转地址计算不大一样。
公式是: (目标地址-当前地址)/4 

验证一下:
00000000000008b4 03000014               b          loc_8c0

(76c - 764 )/4   = 3
0000000000000924 02000014               b          92c
(92c- 024)/4 = 2 

 

 


//这个有重定位表, 计算应该是一样的。
000000000000050c 7FF20094               bl         __ZnwmRK10MemLabelIdmPKci   

 



0000000000000508 E10314AA               mov        x1, x20
000000000000050c 7FF20094               bl         __ZnwmRK10MemLabelIdmPKci    ; operator new(unsigned long, MemLabelId const&, unsigned long, char const*, int)
0000000000000510 E8010090               adrp       x8, #0x3c000
0000000000000514 086947F9               ldr        x8, [x8, #0xed0]             ; __ZTV20LocalFileSystemPosix
0000000000000518 08410091               add        x8, x8, #0x10
000000000000051c 087C00A9               stp        x8, xzr, x0
0000000000000520 1F1000F9               str        xzr, [x0, #0x20]
0000000000000524 E8010090               adrp       x8, #0x3c000
0000000000000528 08B547F9               ldr        x8, [x8, #0xf68]             ; _kMemString
000000000000052c 090940B9               ldr        w9, [x8, #0x8]
0000000000000530 093000B9               str        w9, [x0, #0x30]
0000000000000534 080140F9               ldr        x8, x8
0000000000000538 081400F9               str        x8, [x0, #0x28]
000000000000053c 280000D0               adrp       x8, #0x6000
0000000000000540 08212B91               add        x8, x8, #0xac8               ; __ZTV21LocalFileSystemiPhone
0000000000000544 1F400039               strb       wzr, [x0, #0x10]
0000000000000548 08410091               add        x8, x8, #0x10                ; 0x6ad8
000000000000054c 080000F9               str        x8, x0

0000000000000550 A00200A9               stp        x0, x0, x21   	  // x0, x0, 存到x21+0, x21+8?
0000000000000554 BF0A00F9               str        xzr, [x21, #0x10]  //清零 x21+0x10
0000000000000558 230000D0               adrp       x3, #0x6000
000000000000055c 63F02191               add        x3, x3, #0x87c               ; "./Runtime/VirtualFileSystem/VirtualFileSystem.cpp"
0000000000000560 00148052               movz       w0, #0xa0
0000000000000564 E2031D32               orr        w2, wzr, #0x8
0000000000000568 84098052               movz       w4, #0x4c




改成    
000000000000050c  7FF20094         bl       _CreateIphonePathFileSystem  //这里还是转重定位表就可以了。
0000000000000518  0E000014         b        0000000000000550




 

重定位表的信息:

3E0D0:    5D0001A3 ->  5D0001BE (符号索引为446)

Arm64修改完成

000000000000050c A7F20094               bl         _CreateIphonePathFileSystem
0000000000000510 E8010090               adrp       x8, #0x3c000
0000000000000514 086947F9               ldr        x8, [x8, #0xed0]             ; __ZTV20LocalFileSystemPosix
0000000000000518 0E000014               b          loc_550
....
0000000000000550 A00200A9               stp        x0, x0, x21                 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值