<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          深入理解MachO數(shù)據(jù)解析規(guī)則

          共 12009字,需瀏覽 25分鐘

           ·

          2021-04-06 19:57

          我們知道Apple設(shè)備可執(zhí)行文件的存儲(chǔ)格式是MachO,一個(gè)二進(jìn)制文件。通常在做逆向或者靜態(tài)分析的時(shí)候都會(huì)用到這個(gè)文件,分析MachO的常用工具是MachOView[1]。今天借助于MachOView,主要分析Code Signature的存儲(chǔ)規(guī)則。

          本篇文章同時(shí)也是圍繞這幾個(gè)問(wèn)題展開(kāi)的:

          1、MachOView是如何確認(rèn)MachO內(nèi)容的。

          2、二進(jìn)制數(shù)據(jù)是如何存儲(chǔ)的,如何確認(rèn)位置。

          3、字節(jié)碼含義如何解析。

          前置準(zhǔn)備

          1、二進(jìn)制文件其實(shí)簡(jiǎn)單理解就是通過(guò)二進(jìn)制形式進(jìn)行存儲(chǔ)內(nèi)容的文件,它可以原封不動(dòng)的讀到內(nèi)存中用于完成各種處理。比如數(shù)值3.1415927,文本文件需要9個(gè)字節(jié)進(jìn)行存儲(chǔ):3 . 1 4 1 5 9 2 7 這 9 個(gè) ASCII 值,而如果是二進(jìn)制的話4個(gè)字節(jié)就夠了:DB 0F 49 40。

          2、二進(jìn)制文件讀到內(nèi)存中通常是連續(xù)存儲(chǔ)的,它不需要額外的處理,原本怎樣,在內(nèi)存里就是怎樣的。

          3、每個(gè)進(jìn)程都會(huì)被分配一個(gè)虛擬地址空間,進(jìn)程尋址的范圍就是在這個(gè)虛擬地址空間進(jìn)行的,虛擬地址到物理地址之間有一個(gè)映射表進(jìn)行管理。

          4、可以簡(jiǎn)單理解:虛擬地址 = 隨機(jī)基址(ASLR)+ 邏輯地址(段內(nèi)偏移)。

          后面的內(nèi)容也會(huì)出現(xiàn)很多偏移量(offset)的概念,它的含義很簡(jiǎn)單就是相對(duì)某一位置偏移多少字節(jié)。關(guān)鍵是需要確認(rèn)它是相對(duì)哪個(gè)位置進(jìn)行的偏移,在不同的數(shù)據(jù)段,這個(gè)相對(duì)的錨點(diǎn)是不一樣的。但通常來(lái)說(shuō)偏移量都是相對(duì)于當(dāng)前的數(shù)據(jù)段來(lái)說(shuō)的。

          5、FAT格式的MachO可以理解為多個(gè)架構(gòu)的順序組合,所以分析某個(gè)架構(gòu)時(shí),還需要加上對(duì)應(yīng)架構(gòu)的偏移量。

          6、uint32_t占4個(gè)字節(jié),uint8_t占1個(gè)字節(jié),char占一個(gè)字節(jié)。

          Mach-O格式

          格式分析

          可以簡(jiǎn)單看下Mach-O的數(shù)據(jù)結(jié)構(gòu):

          Mach-O文件大致分為三部分:

          Header

          表示當(dāng)前的Mach-O文件整體信息,包含CPU架構(gòu)、子版本、文件類型、加載命令數(shù)等內(nèi)容。數(shù)字內(nèi)容好表示,那CPU架構(gòu)這樣的類別是如何表示的呢?二進(jìn)制數(shù)據(jù)說(shuō)到底也是數(shù)字,這些類別信息也只能通過(guò)數(shù)字表示,但需要一個(gè)具有特殊含義的數(shù)字,這個(gè)數(shù)字通常叫magic(魔數(shù))。比如0xCAFEBABE表示FAT,0xFEEDFACF表示ARM64。

          Header的定義地址:https://opensource.apple.com/source/xnu/xnu-792/EXTERNAL_HEADERS/mach-o/loader.h.auto.html

          Load Commands

          記錄各個(gè)數(shù)據(jù)段的信息和位置,只是類別和標(biāo)記的介紹,包含一些信息的偏移地址、文件大小等內(nèi)容。

          Data

          記錄具體的內(nèi)容信息。不同類別的信息對(duì)應(yīng)不同的數(shù)據(jù)含義。注意上圖右側(cè)由Load Commands到Data的箭頭,Data的位置是由Load Commands指定的。

          他們?nèi)叩年P(guān)系如果用一本書表示的話就是:Header是封面,Load Commands是目錄,Data是書的內(nèi)容。

          尋找Code Signature

          本節(jié)的重點(diǎn)是找到Code Signature(代碼簽名)這部分內(nèi)容,它沒(méi)被MachOView解析,還是原始的數(shù)據(jù)形態(tài),是一個(gè)比較好的分析案例。

          分析文件是系統(tǒng)的ls,它的路徑在/bin/ls,把它放到MachOView里。ls是一個(gè)FAT文件,它包含兩個(gè)架構(gòu),F(xiàn)at Header里記錄了各個(gè)架構(gòu)的類別、偏移量、大小等信息。

          我們只關(guān)注X86_64架構(gòu)下的內(nèi)容,展開(kāi)這個(gè)架構(gòu)下的Load Commands,找到代表代碼簽名的LC_CODE_SIGNATURE信息:

          右側(cè)是真實(shí)的數(shù)據(jù)內(nèi)容,MachOView已經(jīng)幫我們對(duì)應(yīng)好了字段描述:

          Data Offset:代表數(shù)據(jù)偏移 53808,換成16進(jìn)制就是0xD230

          Data Size:代表文件大小 5728,換成16進(jìn)制就是0x1660

          這倆16進(jìn)制值其實(shí)就是Data對(duì)應(yīng)的內(nèi)容,Value是MachOView幫我們做的處理。

          這里的偏移跟上面Fat Header的偏移含義已經(jīng)不一樣了,F(xiàn)at Header說(shuō)的是總文件偏移,這里的偏移則是針對(duì)X86文件的偏移。所以實(shí)際的偏移應(yīng)該是:0xD230 + 0x4000 = 0x11230。

          找到Data部分的Code Signature內(nèi)容:

          這里pFile就是相對(duì)當(dāng)前文件的偏移量(也可以理解為邏輯偏移量),它的起始位置正是上面計(jì)算得的:0x11230。由大小0x1660,我們還可以計(jì)算得出Code Signature最后一個(gè)字節(jié)所在位置是:0x11230 + 0x1660 - 0x1 = 0x1288F。

          解析Code Signature

          CS_SuperBlob

          我們已經(jīng)找到了代碼簽名位置,現(xiàn)在開(kāi)始解析它吧。解析的第一步就是需要找到數(shù)據(jù)定義,有了定義才能分析出數(shù)據(jù)含義。Code Signature相關(guān)內(nèi)容的定義在這里:https://opensource.apple.com/source/xnu/xnu-3789.51.2/bsd/sys/codesign.h.auto.html

          整個(gè)簽名的頭部是一個(gè)CS_SuperBlob結(jié)構(gòu)體,它的定義如下:

          typedef struct __SC_SuperBlob {
           uint32_t magic;     /* magic number */
           uint32_t length;    /* total length of SuperBlob */
           uint32_t count;     /* number of index entries following */
           CS_BlobIndex index[];   /* (count) entries */
           /* followed by Blobs in no particular order as indicated by offsets in index */
          } CS_SuperBlob; 

          這個(gè)結(jié)構(gòu)體第一個(gè)參數(shù)是magic,它的定義如下:

          /*
           * Magic numbers used by Code Signing
           */

          enum {
           CSMAGIC_REQUIREMENT = 0xfade0c00,  /* single Requirement blob */
           CSMAGIC_REQUIREMENTS = 0xfade0c01,  /* Requirements vector (internal requirements) */
           CSMAGIC_CODEDIRECTORY = 0xfade0c02,  /* CodeDirectory blob */
           CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0/* embedded form of signature data */
           CSMAGIC_EMBEDDED_SIGNATURE_OLD = 0xfade0b02/* XXX */
           CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171/* embedded entitlements */
           CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1/* multi-arch collection of embedded signatures */
           CSMAGIC_BLOBWRAPPER = 0xfade0b01/* CMS Signature, among other things */
            //...
          }

          第二個(gè)參數(shù)是length,表示整個(gè)SuperBlob的長(zhǎng)度。

          第三個(gè)參數(shù)是count,表示index實(shí)體條目的數(shù)量。

          第四個(gè)參數(shù)是為CS_BlobIndex的一個(gè)結(jié)構(gòu)體。

          大端小端

          1、這個(gè)是64位架構(gòu)的二進(jìn)制數(shù)據(jù),其實(shí)有兩種64位架構(gòu),他們分別表示為大端64位和小端64位,上面MachOView分析的X86 Header中的魔數(shù)是0xFEEDFACF,代表的就是當(dāng)前二進(jìn)制文件是小端64位格式。

          2、比如0x1234這個(gè)數(shù)據(jù),在小端情況下,12會(huì)存放在低字節(jié)處,34會(huì)放于高字節(jié)處,大端則相反。

          數(shù)據(jù)解析

          我們把Code Signature的第一個(gè)行數(shù)據(jù)拿出來(lái)分析:

          這里注意Data部分,有兩個(gè)標(biāo)簽:Data LO和Data HI,是用于表示當(dāng)前的字節(jié)序列,前面是低字節(jié),后面是高字節(jié)。這樣按照小端的規(guī)則,我們就可以按自然順序取數(shù)據(jù)了,所以可以得出以下內(nèi)容:

          magic

          為0xFADE0CC0,對(duì)應(yīng)CSMAGIC_EMBEDDED_SIGNATURE,代表嵌入的代碼簽名數(shù)據(jù)。

          length

          是0x1486,我們可以計(jì)算得出最后一個(gè)字節(jié)位置:0x11230 + 0x1486 - 0x1 = 0x126B5

          紅色標(biāo)記的字節(jié)就是Code Signature結(jié)束的地方,在這之后的內(nèi)容全部由0x00填充,就非實(shí)體內(nèi)容了。

          count

          是3,表示接下來(lái)有3個(gè)實(shí)體內(nèi)容,這個(gè)實(shí)體對(duì)應(yīng)的是結(jié)構(gòu)體:CS_BlobIndex。

          CS_BlobIndex

          我們來(lái)看下CS_BlobIndex這個(gè)結(jié)構(gòu)體:

          /*
           * Structure of an embedded-signature SuperBlob
           */


          typedef struct __BlobIndex {
           uint32_t type;     /* type of entry */
           uint32_t offset;    /* offset of entry */
          } CS_BlobIndex;

          它有兩個(gè)成員變量,type表示實(shí)體類型,offset表示實(shí)體偏移量。

          一般表示類型的肯定有特殊數(shù)字對(duì)應(yīng)的含義,這里的type也是一樣的,這個(gè)type在上面的magic在一個(gè)enum里定義。

          CSSLOT_CODEDIRECTORY = 0,    /* slot index for CodeDirectory */
          CSSLOT_INFOSLOT = 1,
          CSSLOT_REQUIREMENTS = 2,
          CSSLOT_RESOURCEDIR = 3,
          CSSLOT_APPLICATION = 4,
          CSSLOT_ENTITLEMENTS = 5,

          CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000/* first alternate CodeDirectory, if any */
          CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5,  /* max number of alternate CD slots */
          CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX, /* one past the last */

          CSSLOT_SIGNATURESLOT = 0x10000,   /* CMS Signature */

          數(shù)據(jù)解析

          我們?cè)倩氐綌?shù)據(jù)部分,根據(jù)上面結(jié)構(gòu)體進(jìn)行分析:

          能夠解析出三條CS_BlobIndex數(shù)據(jù):

          typetype含義offset
          0x00CSSLOT_CODEDIRECTORY0x24
          0x02CSSLOT_REQUIREMENTS0x261
          0x10000CSSLOT_SIGNATURESLOT0x29D

          這里又出現(xiàn)了一個(gè)offset,這個(gè)offset存在于Code Signature的最外部,所以它表示的就是相對(duì)Code Signature的偏移量。

          這個(gè)表相當(dāng)于又提供了一個(gè)目錄,它告訴我們,之后的內(nèi)容有三部分(三個(gè)結(jié)構(gòu)體)組成,各個(gè)部分的頁(yè)碼是什么。

          CS_CodeDirectory

          我們先分析CSSLOT_CODEDIRECTORY,它對(duì)應(yīng)的是CS_CodeDirectory結(jié)構(gòu)體:

          /*
           * C form of a CodeDirectory.
           */

          typedef struct __CodeDirectory {
           uint32_t magic;     /* magic number (CSMAGIC_CODEDIRECTORY) */
           uint32_t length;    /* total length of CodeDirectory blob */
           uint32_t version;    /* compatibility version */
           uint32_t flags;     /* setup and mode flags */
           uint32_t hashOffset;   /* offset of hash slot element at index zero */
           uint32_t identOffset;   /* offset of identifier string */
           uint32_t nSpecialSlots;   /* number of special hash slots */
           uint32_t nCodeSlots;   /* number of ordinary (code) hash slots */
           uint32_t codeLimit;    /* limit to main image signature range */
           uint8_t hashSize;    /* size of each hash in bytes */
           uint8_t hashType;    /* type of hash (cdHashType* constants) */
           uint8_t platform;    /* platform identifier; zero if not platform binary */
           uint8_t pageSize;    /* log2(page size in bytes); 0 => infinite */
           uint32_t spare2;    /* unused (must be zero) */
           /* Version 0x20100 */
           uint32_t scatterOffset;    /* offset of optional scatter vector */
           /* Version 0x20200 */
           uint32_t teamOffset;    /* offset of optional team identifier */
           /* followed by dynamic content as located by offset fields above */
          } CS_CodeDirectory;

          數(shù)據(jù)解析

          我們先把這段數(shù)據(jù)拿出來(lái),然后根據(jù)結(jié)構(gòu)體進(jìn)行分析:

          這里僅挑一些重要的內(nèi)容進(jìn)行分析。

          magic是0xFADE0C02,作為標(biāo)記存在,代表CodeDirectory

          length是0x23D,表示數(shù)據(jù)段長(zhǎng)度

          identoffset是0x30,表示identifier字符串的偏移量,這里的identifier對(duì)應(yīng)的就是我們的bundleId

          需要提醒的是當(dāng)前的CodeDirectory是數(shù)據(jù)SuperBlob的內(nèi)部結(jié)構(gòu)體,所以這里的offset就變成了結(jié)構(gòu)體內(nèi)部偏移了,這里的起始位置也即是0xFADE0C02所在的位置是0x11254,所以可以算出indentoffset的文件偏移量是:

          identoffset地址為:0x11254 + 0x30 = 0x11284

          這里你可能會(huì)疑惑,只有偏移量怎么確認(rèn)從哪結(jié)束呢,這里并沒(méi)有提供數(shù)據(jù)大小。其實(shí)字符串是不需要知道大小也可以確認(rèn)它到哪結(jié)束的,字符里面有結(jié)束位\0啊,在ASCII碼里結(jié)束位就是0x00。

          可以解析得出ls的bundleId是com.apple.ls

          這里再補(bǔ)充一點(diǎn):MachO里字符串的編碼不是通過(guò)ASCII,而是使用UTF-8進(jìn)行編碼的,只不過(guò)UTF-8兼容了ASCII,所以我們當(dāng)做ASCII也能解析出正確的內(nèi)容。

          CS_GenericBlob

          我們現(xiàn)在來(lái)看下證書的解析,查上面記錄的偏移表,CSSLOT_SIGNATURESLOT對(duì)應(yīng)的結(jié)構(gòu)體是CS_Generic_Blob:

          typedef struct __SC_GenericBlob {
           uint32_t magic;    /* magic number */
           uint32_t length;   /* total length of blob */
           char data[];
          } CS_GenericBlob;

          上個(gè)表格我們記錄了它的offset是0x29D位置,所以它的起始位置就是:0x11230 + 0x29D = 0x114CD,找到這個(gè)位置,帶入結(jié)構(gòu)體進(jìn)行解析:

          magic是0xFADE0B01,對(duì)應(yīng)了CSSLOT_SIGNATURESLOT值。

          數(shù)據(jù)長(zhǎng)度是0x11E9(4585字節(jié)),這表示的CS_GenericBlob的大小,而在這之后的內(nèi)容都是data,表示的就是證書部分。

          我們可以計(jì)算出證書data結(jié)束的最后一個(gè)字節(jié)位置:0x114CD + 0x11E9 - 0x8 - 0x1 = 0x126AD。

          說(shuō)明:根據(jù)《iOS應(yīng)用逆向與安全》一書說(shuō)明,借助于010 Editor等二進(jìn)制工具,我們把data部分的數(shù)據(jù)復(fù)制出來(lái)(需要借助于Hooper這類工具),保存為cer格式,就能獲取到一個(gè)證書文件。但對(duì)ls的測(cè)試并不能成功,推測(cè)這里的data可能還有其余內(nèi)容,需要拆分。

          Jtool

          只要有了對(duì)應(yīng)數(shù)據(jù)結(jié)構(gòu),簽名部分的所有信息我們都是可以解析出來(lái)的。但每次都逐字節(jié)分析,顯然很費(fèi)事,能不能寫個(gè)程序,用于上述內(nèi)容解析呢?當(dāng)然是可以的,已經(jīng)有這樣的工具了,就是Jtool[2]。jtool比otool功能更強(qiáng)大,解析的數(shù)據(jù)也更詳細(xì)。可以通過(guò)homebrew進(jìn)行安裝:

          $ brew install jtool

          如果通過(guò)jtool查看上面x86_64架構(gòu)的簽名信息,可以這樣:

          $ jtool -arch x86_64 --sig /bin/ls

          輸出結(jié)果為:

          Blob at offset: 53808 (5728 bytes) is an embedded signature
          Code Directory (573 bytes)
            Version:     20100
            Flags:       none
            Platform Binary
            CodeLimit:   0xd230
            Identifier:  com.apple.ls (0x30)
            CDHash:      46cc1da7c874a5853984a286ffecb48daf2f65f023d10258a31118acfc8a3697 (computed)
            # of Hashes: 14 code + 2 special
            Hashes @125 size: 32 Type: SHA-256
          Requirement Set (60 bytes) with 1 requirement:
           0: Designated Requirement (@20, 28 bytes): SIZE: 28
            Ident: (com.apple.ls) AND Apple Anchor
          Blob Wrapper (4585 bytes) (0x10000 is CMS (RFC3852) signature)
          CA: Apple Certification Authority CN: Apple Root CA
          CA: Apple Certification Authority CN: Apple Code Signing Certification Authority
          CA: Apple Certification Authority CN: Apple Root CA
          CA: Apple Certification Authority CN: Apple Root CA
          CA: Apple Certification Authority CN: Apple Code Signing Certification Authority
          CA: Apple Software CN: Software Signing
          Time: 201222002625Zi

          第一行里的offset 53808 對(duì)應(yīng)16進(jìn)制是0xD230,就是LC_CODE_SIGNATURE里記錄的偏移量。

          根據(jù)輸出信息也能得出code signature由三部分內(nèi)容組成:Code Diretory、Requeirement Set、Blob Wrapper。證書部分解析出了6個(gè)證書,說(shuō)明這里應(yīng)該還有別的結(jié)構(gòu)體可以拆分。

          回顧

          如果你看到這里,可以回顧下開(kāi)始講到的三個(gè)問(wèn)題,用于檢驗(yàn)?zāi)愕睦斫獬潭取?/p>

          1、MachOView是如何確認(rèn)MachO內(nèi)容的。

          2、二進(jìn)制數(shù)據(jù)是如何存儲(chǔ)的,如何確認(rèn)位置。

          3、字節(jié)碼含義如何解析。

          參考資料

          [1]

          MachOView: https://github.com/fangshufeng/MachOView

          [2]

          jtool: http://newosxbook.com/tools/jtool.html


          瀏覽 41
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月天丁香花 | 在线观看黄色免费视频 | 日本A片视频 | 不用播放器的AV网站 | 不卡操逼 |