[譯]反-反組譯碼 & 混淆 #1: 蘋果沒有遵循自己制定的Mach-O規範?

來源:互聯網
上載者:User

標籤:style   c   class   code   http   ext   

原文地址:http://reverse.put.as/2012/02/02/anti-disassembly-obfuscation-1-apple-doesnt-follow-their-own-mach-o-specifications/

當想到這個特性時,我非常高興!因為我喜歡突破束縛,並且寫了一個CrackMe來展示這個有趣的特性。

產生問題的原因是:蘋果沒有遵循自己的文檔與標準(Mach-O方面的),但是逆向工具卻要遵循。

當逆向修改過Section資訊的Mach-O檔案時,IDA可能會崩潰、輸出錯誤的反組譯碼結果、混亂的字串,

LLDB輸出錯誤的反組譯碼結果(不是GDB),class-dump 會失敗,逆向工程師看到是無意義的Mach-O檔案頭。

最後,這是一個有趣的混淆手段。^_^

 

當你使用IDA載入CrackMe時,程式會報這樣的錯誤:負的Section大小或位移。

當Sections的資訊(位移或者大小)超過檔案大小時,otool也會輸出錯誤的結果。

 

造成這個問題的具體方法是:修改Mach-O的Section資訊。在32位下,Section的結構如下:

struct section { /* for 32-bit architectures */charsectname[16];/* name of this section */charsegname[16];/* segment this section goes in */uint32_taddr;/* memory address of this section */uint32_tsize;/* size in bytes of this section */uint32_toffset;/* file offset of this section */uint32_talign;/* section alignment (power of 2) */uint32_treloff;/* file offset of relocation entries */uint32_tnreloc;/* number of relocation entries */uint32_tflags;/* flags (section type and attributes)*/uint32_treserved1;/* reserved (for offset or index) */uint32_treserved2;/* reserved (for count or sizeof) */};

 

讓我們從最容易引起問題的offset欄位說起。根據標準offset的定義如下:指示當前Section在檔案中的位移值。

我的理解是:這個欄位用來指示代碼或者資料在檔案的位置。這麼理解沒錯吧?

既然是一個位移值,那麼理論上Section是沒有必要是按照順序排列的或者按照指定的循序排列(主要是指:沒有必要跟Section在Segment中順序一致)。這就開啟了錯誤之門。

 

如果我們將offset指向其他地址?比如:IDA需要根據offset指向的地址來讀取相應的資料。

我們來做一個測試,修改cstring setion的位移值,然後使用IDA載入修改後的檔案。

喔,現在程式中的字串被“混淆”了,因為IDA載入了錯誤的資料。

 

很有意思,是嗎?如果你修改Section資訊(將offset改成一個錯誤的值),然後運行對應的程式,程式的行為還完全正確!

同樣,修改 text section的便宜後,程式的中指令應該都錯了,但是程式還是可以正常運行。

 

為什麼程式還可以正確運行?這是非常有趣的。我認為主要的原因是:核心只是將檔案線性載入到記憶體而忽略了offset。

《Mac OS X Internal》812頁中對execve()系統調用的說明可以解釋問題原因。

exec_mach_imgact()函數(bsd/kern/kern_exec.c)會調用load_machfile()函數,

後者主要用來載入可執行檔,處理具體的Mach-O載入命令等。程式碼片段如下:

@bsd/kern/kern_exec.c

        /*         * Actually load the image file we previously decided to load.         */        lret = load_machfile(imgp, mach_header, thread, map, &load_result);

在load_machfile()內部會調用parse_machfile()函數來解析檔案,

@bsd/kern/mach_loader.c

        lret = parse_machfile(vp, map, thread, header, file_offset, macho_size,                              0, result);

在這裡我們可以看到有趣的注釋:

/* * The file size of a mach-o file is limited to 32 bits; this is because * this is the limit on the kalloc() of enough bytes for a mach_header and * the contents of its sizeofcmds, which is currently constrained to 32 * bits in the file format itself.  We read into the kernel buffer the * commands section, and then parse it in order to parse the mach-o file * format load_command segment(s).  We are only interested in a subset of * the total set of possible commands. */

 

在實現的下部,我們可以看到處理所有command的迴圈,其中section command是在segment(LC_SEGMENT/LC_SEGMENT_64)command下處理的。

因為我們需要看下load_segment()的實現。

在load_segment()內,我們發現對於可執行檔合法性的驗證只是做到了segment一層,並沒有驗證section。

這也造成我們沒法混淆segment :-))。

 

當parse_machfile()函數返回時,所有的解析工作已經完成,連結的庫被載入,程式的入口函數被調用。

程式的布局與其在檔案系統中一致(這就是我前面所說的線性),並且section資訊根本沒有被使用。

這是一種隱性的約定:可執行檔的格式是正確的。

 

這種行為(指核心載入可執行檔)正確嗎?我認為是錯誤的。因為核心並沒有遵循Mach-O標準,或者是我對標準理解有錯誤?

這又是一個信任不可信資料的例子,我們應該顯式的校正輸入資料。

 

我們應該繼續瞭解真箇載入過程,在CrackMe中還有另一個有趣的特性;-)。

 

我們還可以改變這些section結構的這些欄位:flags,size, section和segment的名字,section 的順序。

這樣可以迷惑工具和逆向工程師。這裡需要注意的是跟核心遵循同樣的隱式約定,忽略如上的欄位。

看起來有點怪異,是吧?

 

我希望你享受如上的分析過程,並且為你帶來閱讀xnu與dyld原始碼的動力。

 

Have fun,

fG!

 

更新 1:

如下是本文觀點的PoC。代碼是32位的、non-fat mach-o檔案、控制台程式。如果在Objective-C目標上應用這個特性,

會引起載入錯誤,因為並不是所有的 section 都可以被混淆。

manglemacho.c.gz

SHA256(manglemacho.c.gz)= d79a612b72130732d7e47b2925fba7fc0b63824622d05f08e7f33641d522a8b5

更新 2:

實際的情況是上section 的所有欄位都可以是0,並不會帶來什麼不利的影響(除了mod_init_func)。

我這樣試過,但是沒有做筆記。如果不做更深入的混淆,IDA有時還可以聰明得進行反組譯碼,

原因是入口地址是合法的。我們可以通過修改 size 和 offset 來對IDA進行更深入的迷惑。

通過設定如下工具的第二個參數可以將 section 的所有欄位都設定成0.

manglemacho_v0.3.c.gz
SHA256(manglemacho_v0.3.c.gz)= 4b33dc5f43bbb9114e6a8c18dba8894ca44b991cd69a5e5e54bfdcd03607fc9c

.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.