亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

APP漏洞掃描用地址空間隨機化

LinkedME2016 / 998人閱讀

摘要:同時,阿里聚漏洞掃描器有一個檢測項叫未使用地址空間隨機化技術該檢測項會分析中包含的文件判斷它們是否使用了該項技術。在版本上線前使用阿里聚安全漏洞掃描系統(tǒng)進行安全掃描,將安全隱患阻擋在發(fā)布之前。

前言

我們在前文《APP漏洞掃描器之本地拒絕服務檢測詳解》了解到阿里聚安全漏洞掃描器有一項靜態(tài)分析加動態(tài)模糊測試的方法來檢測的功能,并詳細的介紹了它在針對本地拒絕服務的檢測方法。

同時,阿里聚漏洞掃描器有一個檢測項叫未使用地址空間隨機化技術, 該檢測項會分析APP中包含的ELF文件判斷它們是否使用了該項技術。如果APP中存在該項漏洞則會降低緩沖區(qū)溢出攻擊的門檻。

本文主要介紹該項技術的原理和掃描器的檢測方法。由于PIE的實現(xiàn)細節(jié)較復雜,本文只是介紹了大致的原理。想深入了解細節(jié)的同學可以參看潘愛民老師的書籍《程序員的自我修養(yǎng)》。

PIE是什么

PIE(position-independent executable)是一種生成地址無關可執(zhí)行程序的技術。如果編譯器在生成可執(zhí)行程序的過程中使用了PIE,那么當可執(zhí)行程序被加載到內存中時其加載地址存在不可預知性。

PIE還有個孿生兄弟PIC(position-independent code)。其作用和PIE相同,都是使被編譯后的程序能夠隨機的加載到某個內存地址。區(qū)別在于PIC是在生成動態(tài)鏈接庫時使用(Linux中的so),PIE是在生成可執(zhí)行文件時使用。

PIE的作用

安全性

PIE可以提高緩沖區(qū)溢出攻擊的門檻。它屬于ASLR(Address space layout randomization)的一部分。ASLR要求執(zhí)行程序被加載到內存時,它其中的任意部分都是隨機的。包括
Stack, Heap ,Libs and mmap, Executable, Linker, VDSO。通過PIE我們能夠實現(xiàn)Executable 內存隨機化

節(jié)約內存使用空間

除了安全性,地址無關代碼還有一個重要的作用是提高內存使用效率。

一個共享庫可以同時被多個進程裝載,如果不是地址無關代碼(代碼段中存在絕對地址引用),每個進程必須結合其自生的內存地址調用動態(tài)鏈接庫。導致不得不將共享庫整體拷貝到進程中。如果系統(tǒng)中有100個進程調用這個庫,就會有100份該庫的拷貝在內存中,這會照成極大的空間浪費。

相反如果被加載的共享庫是地址無關代碼,100個進程調用該庫,則該庫只需要在內存中加載一次。這是因為PIE將共享庫中代碼段須要變換的內容分離到數據段。使得代碼段加載到內存時能做到地址無關。多個進程調用共享庫時只需要在自己的進程中加載共享庫的數據段,而代碼段則可以共享。

PIE工作原理簡介

我們先從實際的例子出發(fā),觀察PIE和NO-PIE在可執(zhí)行程序表現(xiàn)形式上的區(qū)別。管中窺豹探索地址無關代碼的實現(xiàn)原理。

例子一

定義如下C代碼:

#include 

int global;

void main()
{
    printf("global address = %x
", &global);
}

程序中定義了一個全局變量global并打印其地址。我們先用普通的方式編譯程序。

gcc -o sample1 sample1.c

運行程序可以觀察到global加載到內存的地址每次都一樣。

$./sample1
global address = 6008a8
$./sample1
global address = 6008a8
$./sample1
global address = 6008a8

接著用PIE方式編譯 sample1.c

gcc -o sample1_pie sample1.c -fpie -pie

運行程序觀察global的輸出結果:

./sample1_pie
global address = 1ce72b38
./sample1_pie
global address = 4c0b38
./sample1_pie
global address = 766dcb38

每次運行地址都會發(fā)生變換,說明PIE使執(zhí)行程序每次加載到內存的地址都是隨機的。

例子二

在代碼中聲明一個外部變量global。但這個變量的定義并未包含進編譯文件中。

#include 

extern int global;

void main()
{
    printf("extern global address = %x
", &global);
}

首先使用普通方式編譯 extern_var.c。在編譯選項中故意不包含有global定義的源文件。

gcc -o extern_var extern_var.c

發(fā)現(xiàn)不能編譯通過, gcc提示:

/tmp/ccJYN5Ql.o: In function `main":
extern_var.c:(.text+0xa): undefined reference to `global"
collect2: ld returned 1 exit status

編譯器在鏈接階段有一步重要的動作叫符號解析與重定位。鏈接器會將所有中間文件的數據,代碼,符號分別合并到一起,并計算出鏈接后的虛擬基地址。比如 “.text”段從 0x1000開始,”.data”段從0x2000開始。接著鏈接器會根據基址計算各個符號(global)的相對虛擬地址。

當編譯器發(fā)現(xiàn)在符號表中找不到global的地址時就會報出 undefined reference to `global`. 說明在靜態(tài)鏈接的過程中編譯器必須在編譯鏈接階段完成對所有符號的鏈接。

如果使用PIE方式將extern_var.c編譯成一個share library會出現(xiàn)什么情況呢?

gcc -o extern_var.so extern_var.c -shared -fPIC

程序能夠順利編譯通過生成extern_var.so。但運行時會報錯,因為裝載時找不到global符號目標地址。這說明-fPIC選項生成了地址無關代碼。將靜態(tài)鏈接時沒有找到的global符號的鏈接工作推遲到裝載階段。

那么在編譯鏈接階段,鏈接器是如何將這個缺失的目標地址在代碼段中進行地址引用的呢?

鏈接器巧妙的用一張中間表GOT(Global Offset Table)來解決被引用符號缺失目標地址的問題。如果在鏈接階段(jing tai)發(fā)現(xiàn)一個不能確定目標地址的符號。鏈接器會將該符號加到GOT表中,并將所有引用該符號的地方用該符號在GOT表中的地址替換。到裝載階段動態(tài)鏈接器會將GOT表中每個符號對應的實際目標地址填上。

當程序執(zhí)行到符號對應的代碼時,程序會先查GOT表中對應符號的位置,然后根據位置找到符號的實際的目標地址。

地址無關代碼的生成方式

所謂地址無關代碼要求程序被加載到內存中的任意地址都能夠正常執(zhí)行。所以程序中對變量或函數的引用必須是相對的,不能包含絕對地址。

比如如下偽匯編代碼:

PIE方式:代碼可以運行在地址100或1000的地方

100: COMPARE REG1, REG2
101: JUMP_IF_EQUAL CURRENT+10
...
111: NOP

Non-PIE: 代碼只能運行在地址100的地方

100: COMPARE REG1, REG2
101: JUMP_IF_EQUAL 111
...
111: NOP

因為可執(zhí)行程序的代碼段只有讀和執(zhí)行屬性沒有寫屬性,而數據段具有讀寫屬性。要實現(xiàn)地址無關代碼,就要將代碼段中須要改變的絕對值分離到數據段中。在程序加載時可以保持代碼段不變,通過改變數據段中的內容,實現(xiàn)地址無關代碼。

PIE和Non-PIE程序在內存中映射方式

在Non-PIE時程序每次加載到內存中的位置都是一樣的。

執(zhí)行程序會在固定的地址開始加載。系統(tǒng)的動態(tài)鏈接器庫ld.so會首先加載,接著ld.so會通過.dynamic段中類型為DT_NEED的字段查找其他需要加載的共享庫。并依次將它們加載到內存中。注意:因為是Non-PIE模式,這些動態(tài)鏈接庫每次加載的順序和位置都一樣。

而對于通過PIE方式生成的執(zhí)行程序,因為沒有絕對地址引用所以每次加載的地址也不盡相同。

不僅動態(tài)鏈接庫的加載地址不固定,就連執(zhí)行程序每次加載的地址也不一樣。這就要求ld.so首先被加載后它不僅要負責重定位其他的共享庫,同時還要對可執(zhí)行文件重定位。

PIE與編譯器選項

GCC編譯器用于生成地址無關代碼的參數主要有-fPIC, -fPIE, -pie。

其中-fPIC, -fPIE屬于編譯時選項,分別用于生成共享庫和可執(zhí)行文件。它們能夠使編譯階段生成的中間代碼具有地址無關代碼的特性。但這并不代表最后生成的可執(zhí)行文件是PIE的。還需要在鏈接時通過-pie選項告訴鏈接器生成地址無關代碼的可執(zhí)行程序。

一個標準的PIE程序編譯設置如下:

gcc -o sample_pie sample.c -fPIE -pie

在gcc中使用編譯選項與是否生成PIE可執(zhí)行文件對應關系如下:

Type為DYN的程序支持PIE,EXEC類型不支持。DYN, EXEC與PIE對應關系詳見后文。

ASLR在Android中的應用

PIE屬于ASLR的一部分,如上節(jié)提到ASLR包括對Stack, Heap, Libs and mmap, Executable, Linker, VDSO的隨機化。

而支持PIE只表示對Executable實現(xiàn)了ASLR。隨著Android的發(fā)展對ASLR的支持也逐漸增強。

ASLR in Android 2.x

Android對ASLR的支持是從Android 2.x開始的。2.x只支持對Stack的隨機化。

ASLR in Android 4.0

而在4.0,即其所謂的支持ASLR的版本上,其實ASLR也僅僅增加了對libc等一些shared libraries進行了隨機化,而對于heap, executable和linker還是static的。

對于heap的隨機化來說,可以通過

echo 2 > /proc/sys/kernel/randomize_va_space

來開啟。

而對于executable的隨機化,由于大部分的binary沒有加GCC的-pie -fPIE選項,所以編譯出來的是EXEC,而不是DYN這種shared object file,因此不是PIE(Position Independent Executable),所以沒有辦法隨機化;

同樣的linker也沒有做到ASLR。

ASLR in Android 4.1

終于,在4.1 Jelly Bean中,Android支持了所有內存的ASLR。在Android 4.1中,基本上所有binary都被編譯和連接成了PIE模式(可以通過readelf查看其Type)。所以,相比于4.0,4.1對Heap,executable和linker都提供了ASLR的支持。

ASLR in Android 5.0

5.0中Android拋棄了對non-PIE的支持,所有的進程均是ASLR的。如果程序沒有開啟PIE,在運行時會報錯并強制退出。

PIE程序運行在Android各版本

支持PIE的可執(zhí)行程序只能運行在4.1+的版本上。 在4.1版本之前運行會出現(xiàn)crash。而Non-PIE的程序,在5.0之前的版本能正常運行,但在5.0上會crash。

如何檢測是否開啟PIE

未開啟PIE的執(zhí)行程序用readelf查看其文件類型應顯示EXEC(可執(zhí)行文件),開啟PIE的可執(zhí)行程序的文件類型為DYN(共享目標文件)。另外代碼段的虛擬地址總是從0開始。

為什么檢測DYN就可以判斷是否支持PIE?

DYN指的是這個文件的類型,即共享目標文件。那么所有的共享目標文件一定是開啟了PIE的嗎?我們可以從源碼中尋找答案。查看glibc/glibc-2.16.0/elf/dl-load.c中的代碼。

從源碼可知,如果加載類型不為ET_DYN時調用mmap加載文件時會傳入MAP_FIXED標志。將程序映射到固定地址。

阿里聚安全開發(fā)中建議

針對Android 2.x-4.1之前的系統(tǒng)在編譯時不要使用生成PIE的選項。

在Android 4.1以后的版本必須使用PIE生成Native程序,提高攻擊者中的攻擊成本。

在版本上線前使用阿里聚安全漏洞掃描系統(tǒng)進行安全掃描,將安全隱患阻擋在發(fā)布之前。

Reference

https://en.wikipedia.org/wiki...

http://www.openbsd.org/papers...

https://source.android.com/se...

http://ytliu.info/blog/2012/1...

https://codywu2010.wordpress....

http://www.cnblogs.com/huxiao...

http://stackoverflow.com/ques...

作者:呆狐@阿里聚安全 ,更多Android、iOS技術文章,請訪問阿里聚安全博客

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/11205.html

相關文章

  • 阿里90后工程師利ARM硬件特性開啟安卓8終端“上帝模式”

    摘要:然而,處理器的某些特殊硬件特性能夠打破這種保護,使得普通程序在用戶態(tài)能夠直接訪問內核空間,直接打破內核空間與用戶空間的隔離,修改內核代碼,開啟上帝模式。假設某臺安卓終端擁有內存。至此,上帝模式已經開啟。 文/圖 阿里安全潘多拉實驗室 團控 編者按:團控,阿里安全潘多拉實驗室研究人員,該實驗室主要聚焦于移動安全領域,包括對iOS和Android系統(tǒng)安全的攻擊和防御技術研究。團控的主攻方向...

    RayKr 評論0 收藏0
  • SpringCloud(第 007 篇)電影微服務,使定制 Ribbon 在客戶端進行負載均衡不

    摘要:中的名稱,一定要是服務中注冊的名稱。添加這個的注解,主要是因為定義的時候報錯,也就是說明沒有被實例化。采用隨機分配的策略。添加訪問層添加電影微服務啟動類電影微服務,使用定制化在客戶端進行負載均衡,使用不同服務不同配置策略。 SpringCloud(第 007 篇)電影微服務,使用定制化 Ribbon 在客戶端進行負載均衡,使用 RibbonClient 不同服務不同配置策略 - 一、大...

    scola666 評論0 收藏0
  • 細數iOS上的那些安全防護

    摘要:序隨著蘋果對系統(tǒng)多年的研發(fā),上的安全防護機制也是越來越多,越來越復雜。代碼簽名為了保護開發(fā)者的版權以及防止盜版應用,蘋果系統(tǒng)擁有非常嚴格的簽名保護機制。除了傳統(tǒng)的簽名機制以外,蘋果還額外增加了的安全防護措施,用來增強系統(tǒng)的安全性。 0x00 序 隨著蘋果對iOS系統(tǒng)多年的研發(fā),iOS上的安全防護機制也是越來越多,越來越復雜。這對于剛接觸iOS安全的研究人員來說非常不友好,往往不知從何入...

    shengguo 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<