iOS逆向工程(九):ASLR

ASLR前言

以前我們用Xcode的LLDB指令打斷點時,可以用方法名打斷點,例如breakpoint set -n "[UIViewController touchBegin:]",但是我們想動態調試別人的App,就不能用方法名稱了,需要用到方法的內存地址才能打,例如breakpoint set --address 0x123123123
而想知道方法的內存地址就需要學習ASLR
一、什麼是ASLR?
    1. ASLR,全稱是Address Spce Layout Randomization,翻譯過來就是地址空間佈局隨機化,是一種針對緩衝區溢出的安全保護技術,通過對堆、棧、共享庫映射等線性區佈局的隨機化,增加了攻擊者預測目的地址的難度,防止攻擊者直接定位代碼位置,阻止溢出攻擊。
    1. 蘋果從iOS 4.3之後引入了ASLR技術,所以想要逆向別人的App,學會ASLR是必不可少的。
    1. ASLR的概念看着複雜,實際上非常簡單,其實就是當Mach-O文件載入虛擬內存的時候,起始地址不從0x00000000開始了,而是隨機增加一段,例如從0x50000開始,後面的函數地址都會增加0x50000
二、Mach-O文件的內部結構
    1. Mach-O文件的內部分爲三個區域:HeaderLoad CommandsData,如下圖所示:

    1. Header區,存放了CPU類型、Mach-O文件的具體類型、LoadCommands的數量、LoadCommands的大小等數據,如下所示:

    1. Load Commands區,存放了各段的名稱、各段的虛擬內存地址、各段的虛擬內存大小、各段的在Mac-O中的偏移量、各段的在Mac-O中的偏移大小等數據 ,如下圖所示,重點注意看VM Address、VM SizeFile Offset、File Size這兩組數據 。
    • VM Address、VM Size記錄這此段在虛擬內存的位置和大小

    • File Offset、File Size記錄着此段在Mach-O中的位置和大小。

    1. Data區,存放着各段數據
三、未使用ASLR時,Mach-O文件是如何載入內存的?
    1. 我們觀察Mach-O文件的Load Commands各段的描述信息,重點觀察VM Address、VM SizeFile Offset、File Size,就可以知道Mach-O在虛擬內存中是如何存放的了
    1. 例如下圖中的LC_SEGMENT_64(__PAGEZERO)段,我們可以看出來,PAGEZERO段在虛擬內存中是從0x0開始,大小是0x100000000PAGEZERO段在Mach-O中是從0x0開始,大小是0x0,也就是說PAGEZERO在Mach-O中實際不存在數據 ,只有加載到內存後纔會展開。

    1. 例如下圖中的__TEXT段,我們可以看出來,TEXT段在虛擬內存中從0x10000000開始,大小是0x6B8C000TEXT段在Mach-O中從0x0開始,大小是0x6B8C000

    1. 例如下圖中的__DATA段 ,我們可以看出來,DATA段在虛擬內存中從0x106B8C000開始,大小是0x1820000TEXT段在Mach-O中從0x6B8C000開始,大小是0x1350000

    1. 綜上所述 ,我們就可以繪製出比較直觀的圖來表示,如下圖所示:
四、使用ASLR時,Mach-O文件是如何載入內存的?
    1. ASLR會在虛擬內存中的最開始的位置產生了隨機偏移量,每次載入內存時,偏移量都會不同,導致後續各段的地址都會增加此偏移量,以增加攻擊者預測地址的難度
    1. 例如:ASLR產生的隨機偏移量是0x5000,那麼Mach-O載入虛擬內存中後,就如下圖所示:

    1. 蘋果從iOS 4.3之後引入了ASLR技術,也就說把Mach-O載入內存後,所有的地址都會經過ASLR偏移
    1. 我們使用MachOView工具靜態分析看到的VM Address,是未經過ASLR偏移的虛擬內存地址,也就是說MachOView中的VM Address加上ASLR偏移量纔是虛擬內存中的真正地址
    1. 總結一下:
    • Hopper、IDA、MachOView等工具中的看到的地址都是未使用ASLR的VM Address,所以要想知道虛擬內存中真正地址,就需要再加上ASLR偏移量

    • 虛擬內存中的真正地址 = ASLR偏移量 + PAGEZERO的大小 + Mach-O中的偏移量 (其中PAGEZERO的大小就是VM Size,Mach-O中的偏移量就是Offset,因爲PAGEZERO到內存中才會展開,所以要加上PAGEZERO的大小)

    • 虛擬內存中的真正地址 = ASLR偏移量 + 用工具看到的VM Address

    • 虛擬內存中的真正地址 = ASLR偏移量 + Mach-O文件中的VM Address

    • Mach-O文件中的File Offset = 虛擬內存中的真正地址 - ASLR偏移量 - PAGEZERO的大小

    1. 想要得到ASLR偏移量,可以在使用LLDB命令image list -o -f | grep Mach-O文件名稱,來查看加載到內存中的ASLR偏移量。(注意:ASLR是隨機的,每次加載到內存都不一樣)
五、如何給別人的App打斷點,進行調試
    1. 按照上一篇的方法,進入到WeChat的lldb環境
    1. 使用LLDB指令image list -o -f | grep Mach-O文件名稱,獲取ASLR偏移量,如下圖所示,本次載入內存的偏移量是0x27c0000

    1. 用Hopper等工具靜態分析出某個函數在虛擬內存中的函數地址,這裏的函數地址是靜待分析出來的,也就是未經過ASLR偏移的地址,並不能直接用於打斷點,如下圖所示,-[BaseMsgContentViewController SendTextMessageToolView:]函數的未ASLR偏移的函數地址是0x1002aec90

    1. 使用LLDB指令breakpoint set -a 函數地址,給某個函數打斷點,這裏的函數地址指的是虛擬內存中的真實函數地址,也就是說這裏的函數地址,是ASLR偏移量+靜待分析的函數地址,也就是0x1002aec90+0x27c0000,完整的LLDB指令就是 breakpoint set -a 0x1002aec90+0x27c0000,如下圖所示:

    1. 打完斷點之後,當App觸發此斷點時,就會卡住,以便我們輸入LLDB調試,例如,我這裏對微信的發送消息的方法-[BaseMsgContentViewController SendTextMessageToolView:]打了斷點,之後每次發消息時都會卡主,以便我們繼續輸入LLDB指令調試
    1. 如果不想要斷點了,可以用breakpoint delete 斷點編號刪除斷點;可以通過breakpoint list命令,列出所有的斷點編號
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章