1. 程式人生 > >Android 地址空間隨機化(ALSR)緩解技術

Android 地址空間隨機化(ALSR)緩解技術

出發點

常規的緩衝區溢位利用技術以及其衍生的Ret2libs和ROP利用技術在利用棧緩衝區溢位漏洞進行攻擊時,需要事先熟悉被攻擊程序的虛擬地址空間佈局以便採用硬編碼方式佈局棧記憶體。由於作業系統每次載入程序和動態連結庫時,基地址都載入到固定虛擬記憶體地址處,使緩衝區溢位漏洞易於劫持程式流程跳轉到佈局在棧記憶體的shellcode,即使開啟XN緩解技術,採用ROP也很容易定位到系統庫中的gadget,並劫持程式執行流跳轉到gadget chain。

基於上述緩衝區溢位漏洞的利用特點,地址空間佈局隨機化機制(ALSR)將熵引入到程序記憶體地址空間中,使程序的多個區域(系統呼叫使用的區域、棧記憶體空間等)在載入時隨機分配虛擬地址空間,這樣可以有效的阻止Ret2libs和ROP等利用技術。如果和XN技術結合啟用將在最大程度上保護系統不受記憶體破壞漏洞的攻擊。

原理

早期的ASLR技術主要是在程序載入時在程序棧上預先填充隨機大小的位元組(將棧頂指標減去隨機大小位元組),從而達到程序基地址載入的地址空間隨機化佈局,但由於隨機化的記憶體地址區域單一(棧記憶體),無法應對其他形式的記憶體攻擊,eg,堆緩衝區溢位攻擊,並且由於填充的隨機位元組數太少很容被暴力破解掉,只是在一定程度上緩解了緩衝區溢位漏洞攻擊。

隨著ASLR技術的逐步完善,ASLR技術趨於成熟。其中PaX的技術方案就是ASLR的成熟代表。PaX通過對核心打補丁的方式,實現了對棧基址、主程式基址和共享庫的載入隨機化。在程序載入時對棧基址的4-27位進行隨機化,對主程式的程式碼區、靜態資料區、堆三個連續區域基地址的12-27位進行隨機化,對共享庫載入地址的12-27位進行隨機化,這樣對存在記憶體破壞的各種記憶體區域都進行了強隨機化,大大降低了緩衝區溢位攻擊的成功率。

和PaX不同,TRR通過修改程序載入器的方式來實現ASLR,避免了修改核心,其隨機化方法基本和PaX類似。但TRR增加了對GOT表的隨機化功能,TRR通過修改程序載入器,在程序載入時將GOT表移動到隨機位置,並用二進位制程式碼修改工具修改了程式碼段PLT中對GOT表的索引使其正確指向GOT,從而實現了對GOT表的隨機化。GOT表隨機化可以有效的阻止修改GOT表中函式指標指向惡意程式碼的攻擊方式。

android

與其他作業系統一樣,Android對ASLR機制的支援也是分階段完成的,最早在4.0版本引入,僅僅實現了對nmap系統呼叫所建立的區域(包括動態連結庫)的隨機化。在4.0.3實現了對

空間的隨機化,但是動態聯結器(linker)本身的隨機化並未實現,4.1.1為linker和所有其他的系統二進位制檔案進行了隨機化,目前Android系統已經完全支援了ASLR機制。

ALSR機制有這樣的一個特點或者說“缺陷”:當程序啟動時,隨機化會生效,但如果程序是由一個程式fork而來,則不會再次隨機化。使用fork系統呼叫後,新程序的地址空間佈局會和原來的程序完全一樣。這種情況在Android上的例子就是Zygote。

Zygote利用fork機制來啟動所有應用程序,這些應用程式擁有一個巨大的、共享的、預先填充的虛擬記憶體地址空間,並利用寫時複製技術(copy-on-write)儘可能延遲記憶體頁的複製,從而減少了新程序的記憶體使用量和建立時間。但同時這樣的設計也使Android裝置上的任何應用程式都可以洩漏記憶體地址。

例如,下面是Android中兩個由Zygote fork啟動的應用程式,

[email protected]:/ # cat /proc/1380/maps                                        
4004c000-40051000 r-xp 00000000 b3:19 1424       /system/bin/app_process
40051000-40052000 r--p 00004000 b3:19 1424       /system/bin/app_process
40052000-40053000 rw-p 00005000 b3:19 1424       /system/bin/app_process
40053000-40062000 r-xp 00000000 b3:19 125        /system/bin/linker
40062000-40063000 r--p 0000e000 b3:19 125        /system/bin/linker
40063000-40064000 rw-p 0000f000 b3:19 125        /system/bin/linker
40064000-40067000 rw-p 00000000 00:00 0 
40067000-40068000 r--p 00000000 00:00 0 
40068000-40069000 rw-p 00000000 00:00 0          [anon:libc_malloc]
40069000-4006c000 r-xp 00000000 b3:19 791        /system/lib/liblog.so
4006c000-4006d000 r--p 00002000 b3:19 791        /system/lib/liblog.so
4006d000-4006e000 rw-p 00003000 b3:19 791        /system/lib/liblog.so
4006e000-400b5000 r-xp 00000000 b3:19 711        /system/lib/libc.so
400b5000-400b6000 ---p 00000000 00:00 0 
400b6000-400b8000 r--p 00047000 b3:19 711        /system/lib/libc.so
400b8000-400bb000 rw-p 00049000 b3:19 711        /system/lib/libc.so
400bb000-400c9000 rw-p 00000000 00:00 0 
400c9000-400ca000 r-xp 00000000 b3:19 880        /system/lib/libstdc++.so
......
be91d000-be93e000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

============================================================================

[email protected]:/ # cat /proc/1367/maps
4004c000-40051000 r-xp 00000000 b3:19 1424       /system/bin/app_process
40051000-40052000 r--p 00004000 b3:19 1424       /system/bin/app_process
40052000-40053000 rw-p 00005000 b3:19 1424       /system/bin/app_process
40053000-40062000 r-xp 00000000 b3:19 125        /system/bin/linker
40062000-40063000 r--p 0000e000 b3:19 125        /system/bin/linker
40063000-40064000 rw-p 0000f000 b3:19 125        /system/bin/linker
40064000-40067000 rw-p 00000000 00:00 0 
40067000-40068000 r--p 00000000 00:00 0 
40068000-40069000 rw-p 00000000 00:00 0          [anon:libc_malloc]
40069000-4006c000 r-xp 00000000 b3:19 791        /system/lib/liblog.so
4006c000-4006d000 r--p 00002000 b3:19 791        /system/lib/liblog.so
4006d000-4006e000 rw-p 00003000 b3:19 791        /system/lib/liblog.so
4006e000-400b5000 r-xp 00000000 b3:19 711        /system/lib/libc.so
400b5000-400b6000 ---p 00000000 00:00 0 
400b6000-400b8000 r--p 00047000 b3:19 711        /system/lib/libc.so
400b8000-400bb000 rw-p 00049000 b3:19 711        /system/lib/libc.so
400bb000-400c9000 rw-p 00000000 00:00 0 
400c9000-400ca000 r-xp 00000000 b3:19 880        /system/lib/libstdc++.so
......
be91d000-be93e000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

bypass

雖然ASLR機制可以有效地緩解了緩衝區溢位漏洞的利用,但也僅僅是增加了漏洞利用的開發難度,並未能完全防禦。下面列出了常用的對抗ASLR技巧:

  • 最簡單的方法是利用尚未被隨機化的區域,目前Android上已完全隨機化,這種方法不適用於Android。

  • 利用堆噴技術使攻擊者控制的資料到達記憶體中可預測的位置。

  • 利用資訊洩漏漏洞更加精準有效的獲取程序地址空間佈局。

  • 利用Android應用程序由Zygote fork啟動的特點,可以預先在手機中植入惡意應用程式,並由該程式來洩漏記憶體地址佈局。

--------------------- 本文來自 杏林小軒 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/txx_683/article/details/53487522?utm_source=copy