【51CTO專稿】本文將具體介紹Android中的防緩衝區溢出技術的前因後果。html
一、什麼是ASLR?linux
ASLR(Address space layout randomization)是一種針對緩衝區溢出的安全保護技術,經過對堆、棧、共享庫映射等線性區佈局的隨機化。經過添加攻擊者預測目的地址的難度。防止攻擊者直接定位攻擊代碼位置,達到阻止溢出攻擊的目的。一般狀況下。黑客會利用某個特定函數或庫駐存在特定內存位置的這一事實。經過在操縱堆或其它內存錯誤時調用該函數來發動攻擊。ASLR則能夠避免這樣的狀況。因爲它能確保系統和應用程序的代碼每次被載入時不會出現在同一個存儲位置。shell
蘋果的iOS系統自iOS 4.3之後就支持ASLR技術;儘管Comex在7月份公佈的「iPhone越獄」軟件就已攻克這一防護措施。而Android已經在4.0中應用了ASLR技術。apache
據研究代表ASLR可以有效的減小緩衝區溢出攻擊的成功率,如今Linux、FreeBSD、Windows等主流操做系統都已採用了該技術。安全
二、緩衝區溢出攻擊原理網絡
緩衝區溢出是一種很廣泛、很危急的漏洞。在各類操做系統、應用軟件中普遍存在。利用緩衝區溢出攻擊,可以致使程序執行失敗、系統宕機、又一次啓動等後果。dom
更爲嚴重的是。可以利用它執行非受權指令。甚至可以取得系統特權。進而進行各類非法操做。分佈式
緩衝區溢出(圖1)是指當計算機向緩衝區內填充數據位數時超過了緩衝區自己的容量溢出的數據覆蓋在合法數據上,理想的狀況是程序檢查數據長度並不一樣意輸入超過緩衝區長度的字符,但是絕大多數程序都會若是數據長度老是與所分配的儲存空間相匹配,這就爲緩衝區溢出埋下隱患.操做系統所使用的緩衝區 又被稱爲"堆棧". 在各個操做進程之間,指令會被暫時儲存在"堆棧"其中,"堆棧"也會出現緩衝區溢出。函數
在當前網絡與分佈式系統安全中,被普遍利用的50%以上都是緩衝區溢出,當中最著名的樣例是1988年利用fingerd漏洞的蠕蟲。佈局
而緩衝區溢出中,最爲危急的是堆棧溢出,因爲入侵者可以利用堆棧溢出。在函數返回時改變返回程序的地址。讓其跳轉到隨意地址,帶來的危害一種是程序崩潰致使拒絕服務,第二種就是跳轉並且運行一段惡意代碼,比方獲得shell,而後隨心所欲。
歷史上最著名的緩衝區溢出攻擊可能要算是1988年11月2日的Morris Worm所攜帶的攻擊代碼了。
這個因特網蠕蟲利用了fingerd程序的緩衝區溢出漏洞,給用戶帶來了很是大危害。此後,愈來愈多的緩衝區溢出漏洞被發現。從bind、wu-ftpd、telnetd、apache等常用服務程序,到Microsoft、Oracle等軟件廠商提供的應用程序,都存在着彷佛永遠也彌補不完的緩衝區溢出漏洞。
圖1 緩衝區溢出攻擊示意
三、應用ASLR後的一個簡單對照樣例
如下使用一個比較典型的樣例來顯示使用ASLR先後的效果:
C源碼:
- #include <stdlib.h>
- #include <unistd.h>
- main()
- {
- char *i;
- char buff[20];
- i=malloc(20);
- sleep(1000);
- free(i);
- }
- #ps -aux|grep test
- Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
- aslr_test 8731 0.0 0.0 1632 332 pts/0 S+ 18:49 0:00 ./test
- aslr_test 8766 0.0 0.0 2884 748 pts/1 R+ 18:49 0:00 grep test
- aslr_test@aslr_test-laptop:~$ cat /proc/8731/maps
- 08048000-08049000 r-xp 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 08049000-0804a000 rw-p 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]
- b7e60000-b7e61000 rw-p b7e60000 00:00 0
- b7e61000-b7f9c000 r-xp 00000000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f9c000-b7f9d000 r--p 0013b000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f9d000-b7f9f000 rw-p 0013c000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f9f000-b7fa2000 rw-p b7f9f000 00:00 0
- b7fae000-b7fb0000 rw-p b7fae000 00:00 0
- b7fb0000-b7fc9000 r-xp 00000000 08:01 12195 /lib/ld-2.5.so
- b7fc9000-b7fcb000 rw-p 00019000 08:01 12195 /lib/ld-2.5.so
- bfe86000-bfe9c000 rw-p bfe86000 00:00 0 [stack]
- ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
- #ps -aux|grep test
- Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
- aslr_test 8781 0.0 0.0 1632 332 pts/0 S+ 18:49 0:00 ./test
- aslr_test 8785 0.0 0.0 2884 748 pts/1 R+ 18:49 0:00 grep test
- aslr_test@aslr_test-laptop:~$ cat /proc/8781/maps
- 08048000-08049000 r-xp 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 08049000-0804a000 rw-p 00000000 08:01 2256782 /home/aslr_test/Desktop/test
- 0804a000-0806b000 rw-p 0804a000 00:00 0 [heap]
- b7e1e000-b7e1f000 rw-p b7e1e000 00:00 0
- b7e1f000-b7f5a000 r-xp 00000000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f5a000-b7f5b000 r--p 0013b000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f5b000-b7f5d000 rw-p 0013c000 08:01 12116 /lib/tls/i686/cmov/libc-2.5.so
- b7f5d000-b7f60000 rw-p b7f5d000 00:00 0
- b7f6c000-b7f6e000 rw-p b7f6c000 00:00 0
- b7f6e000-b7f87000 r-xp 00000000 08:01 12195 /lib/ld-2.5.so
- b7f87000-b7f89000 rw-p 00019000 08:01 12195 /lib/ld-2.5.so
- bfe23000-bfe39000 rw-p bfe23000 00:00 0 [stack]
- ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
經過兩次執行後對照/proc下的進程信息能夠發現進程棧和共享庫映射的地址空間都有了較大的變化。這使得以往經過esp值來推測shellcode地址的成功率大大減小了。Phrack59期有一篇文章介紹過使用return-into-libc的方法突破ASLR保護。只是存在着較大的條件限制。milw0rm的一篇文章也介紹了經過搜索linux-gate.so.1中的jmp %esp指令從而轉向執行shellcode的方法,只是由於現在的編譯器將要恢復的esp值保存在棧中,所以也不能繼續使用。總的來講,ASLR技術能夠很是好地保證Android代碼及執行安全。