iOS逆向深入解析MachO文件

      網友投稿 1121 2022-05-30

      MachO文件簡介

      Mach-O其實是Mach Object文件格式的縮寫,它是Mac以及iOS上一種用于可執行文件、目標代碼、動態庫的文件格式,類似于Windows上面的PE格式(Portable Executable),linux上的elf格式(Executable and Link Format)。

      它是一種用于可執行文件、目標代碼、動態庫的文件格式,作為.out格式的替代,MachO提供了更強的擴展性。

      目標文件.o

      庫文件:.a .dylib .Framework

      可執行文件

      dyld(動態鏈接器)

      .dsym(符號表:Relese環境運行生成)

      iOS逆向之深入解析MachO文件

      $ file xxx.xx

      系統架構

      Architectures

      指定工程被編譯成可支持哪些指令集類型,支持的指令集越多,就會編譯出包含多個指令集代碼的數據包,對應生成二進制 .ipa 包會變大。

      Valid Architectures

      限制可能被支持的指令集的范圍,即:Xcode編譯出來的二進制包類型最終從這些類型產生,而編譯出哪種指令集的包,將由Architectures與Valid Architectures的交集來確定

      Build Active Architecture Only

      指定是否只對當前連接設備所支持的指令集編譯。當其值設置為YES,是為了debug的時候編譯速度更快,它只編譯當前的Architecture版本,而設置為no時,會編譯所有的版本。 所以,一般debug的時候可以選擇設置為YES,release的時候要改為NO。

      新建一個工程,真機運行,查看可執行文件僅是一個arm64架構的,將項目最低適配系統調為iOS9.0,真機運行 Relese環境:

      ~/Library/Developer/Xcode/DerivedData/TestDemo-aszxljwcoetyppfyxjarbzmhorsh /Build/Products/Release-iphoneos/TestDemo.app file TestDemo TestDemo: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7 ] [arm64:Mach-O executable arm64] TestDemo (for architecture armv7): Mach-O executable arm_v7 TestDemo (for architecture armv54): Mach-O 64-bit executable arm64

      1

      2

      3

      4

      5

      6

      為什么要改為iOS9.0呢 ?是因為iPhone5c等armv7、armv7s架構不支持iOS11.0;

      為什么要Relese環境運行呢 ?因為Xcode默認Debug只生成單一架構;

      怎么生成所有架構 ?Xcode10中只包含了v7和64,需要在 Architectures 中添加:

      通用二進制文件(Universal binary)

      通用二進制文件也被叫做胖二進制(Fat binary);

      蘋果公司提出的一種程序代碼,能同時適用多種架構的二進制文件;

      同一個程序包中同時為多種架構提供最理想的性能;

      由于需要儲存多種代碼,通用二進制應用程序通常比單一平臺二進制的程序要大;

      由于兩種架構有共通的非執行資源,所以并不會達到單一版本的兩倍之多;

      由于執行中只調用一部分代碼,運行起來也不需要額外的內存;

      架構查看

      lipo -info + macho

      1

      架構合并

      lipo -create macho_A macho_B -output(-o) macho_AB

      1

      架構分離

      lipo macho -thin -arm64 -o macho_arm64

      1

      胖二進制拆分后再重組會得到原始胖二進制;

      通用二進制的大小可能大于子架構大小之和,也可能小于,也可能等于,取決于公共資源文件的多少;

      MachO文件結構

      主要組成可以大概分為三大塊:

      Header部分(包含該二進制文件的一般信息):字節順序、架構類型、加載指令的數量等。使得可以快速確認一些信息,比如當前文件用于32位還是64位,對應處理器是什么,文件類型是什么。

      Load commands 部分(一張包含很多內容的表);內容區包括區域的位置、符號表、動態符號表等。

      Data段:包含Segement的具體數據。

      使用 MachOView 打開會看到通用二進制文件由 Fat Header 和可執行文件組成(可執行文件是由 Header 、 Load commands 和 Data 組成):

      可執行文件是由 Header 、 Load commands 和 Data 組成:

      可以使用otool命令來查看Mach-O文件,也可以使用MachOView這個工具查看剛剛生成的MachO文件,先cd到當前文件夾,然后:

      $otool -f MachO Fat headers fat_magic 0xcafebabe nfat_arch 3 architecture 0 cputype 12 cpusubtype 9 capabilities 0x0 offset 16384 size 73568 align 2^14 (16384) architecture 1 cputype 12 cpusubtype 11 capabilities 0x0 offset 98304 size 73568 align 2^14 (16384) architecture 2 cputype 16777228 cpusubtype 0 capabilities 0x0 offset 180224 size 73888 align 2^14 (16384)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      header 包含了該二進制文件的字節順序、架構類型、加載指令的數量等,使得可以快速確認一些信息,比如當前文件用于 32 位 還是 64 位 ,對應的處理器是什么、文件類型是什么;Xcode中 shift+command+O -> load.h -> 如下信息(mach_header_64(64位)對比mach_header(32位)只多了一個保留字段)

      struct mach_header_64 { uint32_t magic; /* 魔數,快速定位64位/32位 */ cpu_type_t cputype; /* cpu 類型 比如 ARM */ cpu_subtype_t cpusubtype; /* cpu 具體類型 比如arm64 , armv7 */ uint32_t filetype; /* 文件類型 例如可執行文件 .. */ uint32_t ncmds; /* load commands 加載命令條數 */ uint32_t sizeofcmds; /* load commands 加載命令大小*/ uint32_t flags; /* 標志位標識二進制文件支持的功能 , 主要是和系統加載、鏈接有關*/ uint32_t reserved; /* reserved , 保留字段 */ };

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      load commands 是一張包括區域的位置、符號表、動態符號表等內容的表。它詳細保存著加載指令的內容,告訴鏈接器如何去加載這個 Mach-O 文件。通過查看內存地址發現,在內存中 load commands 是緊跟在 header 之后的;

      load commands的詳情:

      /* Constants for the cmd field of all load commands, the type */ #define LC_SEGMENT 0x1 /* segment of this file to be mapped */ #define LC_SYMTAB 0x2 /* link-edit stab symbol table info */ #define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */ #define LC_THREAD 0x4 /* thread */ #define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */ #define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */ #define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */ #define LC_IDENT 0x8 /* object identification info (obsolete) */ #define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */ #define LC_PREPAGE 0xa /* prepage command (internal use) */ #define LC_DYSYMTAB 0xb /* dynamic link-edit symbol table info */ #define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */ #define LC_ID_DYLIB 0xd /* dynamically linked shared lib ident */ #define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */ #define LC_ID_DYLINKER 0xf /* dynamic linker identification */ #define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */ /* linked shared library */ #define LC_ROUTINES 0x11 /* image routines */ #define LC_SUB_FRAMEWORK 0x12 /* sub framework */ #define LC_SUB_UMBRELLA 0x13 /* sub umbrella */ #define LC_SUB_CLIENT 0x14 /* sub client */ #define LC_SUB_LIBRARY 0x15 /* sub library */ #define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */ #define LC_PREBIND_CKSUM 0x17 /* prebind checksum */ /* * load a dynamically linked shared library that is allowed to be missing * (all symbols are weak imported). */ #define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) #define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be mapped */ #define LC_ROUTINES_64 0x1a /* 64-bit image routines */ #define LC_UUID 0x1b /* the uuid */ #define LC_RPATH (0x1c | LC_REQ_DYLD) /* runpath additions */ #define LC_CODE_SIGNATURE 0x1d /* local of code signature */ #define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */ #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */ #define LC_LAZY_LOAD_DYLIB 0x20 /* delay load of dylib until first use */ #define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */ #define LC_DYLD_INFO 0x22 /* compressed dyld information */ #define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) /* compressed dyld information only */ #define LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) /* load upward dylib */ #define LC_VERSION_MIN_MACOSX 0x24 /* build for MacOSX min OS version */ #define LC_VERSION_MIN_IPHONEOS 0x25 /* build for iPhoneOS min OS version */ #define LC_FUNCTION_STARTS 0x26 /* compressed table of function start addresses */ #define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat like environment variable */ #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */ #define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */ #define LC_SOURCE_VERSION 0x2A /* source version used to build binary */ #define LC_DYLIB_CODE_SIGN_DRS 0x2B /* Code signing DRs copied from linked dylibs */ #define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */ #define LC_LINKER_OPTION 0x2D /* linker options in MH_OBJECT files */ #define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */ #define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */ #define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */ #define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */ #define LC_BUILD_VERSION 0x32 /* build for platform min OS version */

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      部分字段說明:

      data 是MachO文件中最大的部分,其中 _TEXT段 、 _DATA段 能給到很多信息。load commands 和 data 之間還留有不少空間,給我們留下了注入代碼的沖破口:

      dyld

      dyld(the dynamic link editor)是蘋果的動態鏈接器,是蘋果操作系統的一個重要組成部分,在系統內容做好程序準備工作之后,交由dyld負責余下的工作。

      系統庫的方法由于是公用的,存放在共享緩存中,那么我們的MachO在調用系統方法時,dyld會將MachO里調用存放在共享緩存中的方法進行符號綁定。這個符號在 release環境 是會被自動去掉的,這也是經常使用收集 bug 工具時需要恢復符號表的原因。

      iOS Mac OS

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:華為云顧炯炯:應用傳送網絡(ADN),重新定義云原生時代的媒體網絡
      下一篇:圖像搜索技術發展應知道
      相關文章
      亚洲视频在线观看| 久久精品国产亚洲AV麻豆王友容| 亚洲高清在线视频| 亚洲自偷自偷图片| 亚洲色精品vr一区二区三区 | 亚洲欧洲国产综合| 亚洲精品中文字幕乱码影院| 自怕偷自怕亚洲精品| 337p日本欧洲亚洲大胆艺术| 亚洲综合精品香蕉久久网97| 亚洲国产精品SSS在线观看AV| 亚洲精品乱码久久久久久久久久久久 | 亚洲香蕉免费有线视频| 亚洲精品人成电影网| 亚洲一级免费毛片| 亚洲综合国产成人丁香五月激情| 亚洲最大无码中文字幕| 久久久亚洲精华液精华液精华液| 国产精品日本亚洲777| 亚洲国产91精品无码专区| 国产亚洲精品精品国产亚洲综合 | 精品亚洲AV无码一区二区| 色噜噜亚洲男人的天堂| 亚洲熟伦熟女专区hd高清| 日日摸日日碰夜夜爽亚洲| 亚洲视频在线免费| 久久精品国产亚洲沈樵| 香蕉视频在线观看亚洲| 亚洲高清日韩精品第一区| 亚洲国产中文在线视频| 亚洲熟妇少妇任你躁在线观看| 日日摸日日碰夜夜爽亚洲| 亚洲中文无韩国r级电影| 在线观看亚洲天天一三视| 久久久久亚洲AV片无码| 亚洲国产人成在线观看| 亚洲AV无码成人网站在线观看| 亚洲精品第一国产综合境外资源 | 亚洲A∨无码一区二区三区| 亚洲国产美女视频| 亚洲国产AV一区二区三区四区 |