Linux ASLR的實現


ASLR大家都會聽說過,但是Linux平台下應用程序的ASLR的情況是怎么樣的呢?我在這里將ASLR分為幾個小的部分來闡述,包括了棧的隨機化,堆的隨機化,mmap的隨機化,以及pie程序運行時的主模塊隨機化。目的是為了知道隨機化了哪些比特,隨機了多少比特。

我在這里以Linux 4.11.4進行分析,以x64為代表,分析通過靜態觀察內核的源代碼和動態調試內核源代碼結合。在這里分析的是用戶態程序的ASLR,由於用戶態程序的ASLR是在程序加載執行過程中完成的,所以分析的起點應該是程序的加載執行。程序的加載執行從execve系統調用開始,到do_execve,到do_exeveat_common[1],因此就沿着這條主線一直走下去。

按照這個主線看下去,第一個見到的隨機化是mmap的隨機化[2],mmap有兩種方式,早期是從低地址空間向高地址空間分配,如今是從高地址空間向低地址空間分配。mmap隨機的位數由mmap_rnd_bits表示,在64位下是28比特,經過計算在64位平台下mmap的基地址是:page_align(0x7ffbf8000000-rand),而其中的rand在是28比特的數字左移12位。當mmap的基地址確定后,在各個系統中,程序運行起來時各個模塊(不包括pie程序的主模塊、但包括各個動態鏈接庫)與mmap的基地址的偏移是固定的,因此這些模塊加載地址的隨機化也在28比特。

緊接着是棧的隨機化,棧的隨機化在3個地方有涉及。第一是[3],在這里將STACK_TOP進行了隨機化。沒隨機化前的STACK_TOP的值是0x00007ffffffff000L,棧的隨機化的位數由STACK_RND_MASK決定,STACK_RND_MASK在x64下是0x3fffff,也就是說棧的隨機位數是22比特,經過計算,這里將STACK_TOP的值隨機化為page_align(0x00007ffffffff000L-rand),而其中rand是22比特的隨機數左移12位(即0到0x3fffff個頁大小)。第二是[4],這里將STACK_TOP減去0或者1個頁大小。第三個是[5],將棧內存高地址隨機減去了0到8192,並進行了16字節對齊[5]。下圖是一個程序運行中棧布局的圖,1和2分別是兩處隨機化。

如果程序是pie的,那么程序主模塊也會被隨機化,見[8],這里主模塊基地址被隨機化為ELF_PAGESTART(0x555555554aaa+rand),rand由arch_mmap_rnd生成,和mmap隨機化的位數是一樣的,都是28比特。

下面是堆的隨機化,堆空間的位置由start_brk和brk確定[6],程序運行最初start_brk和brk指向同一個位置,即data/bss段的下一個頁面。堆的隨機化的實現在[7],start_brk被隨機化[old_start_brk, old_start_brk+0x02000000)中頁面對齊的值。

調試內核使用的是qemu,關於如何調試Linux內核網上有很多的文章。前期的准備就是一個編譯好的Linux kernel、一個已經安裝了Linux系統的硬盤鏡像和一個gdb調試器。關於編譯Linux kernel,盡可能少的編譯優化對於調試會有不少幫助,但是Linux kernel並不能整體在-O0下編譯,但是可以對單個源碼文件或者單個函數以-O0形式進行編譯,我們針對性地選擇哪些不要優化[9][10]。關於准備安裝了Linux系統的硬盤鏡像,一種是自己手動創建硬盤並進行安裝系統[12],例外一種就是使用網上已經存在的硬盤鏡像,我用的是網上已經存在的Ubuntu Cloud Images[11]。關於gdb調試器,依賴於guest系統是什么系統,如果guest系統是ARM Linux,那么就需要一個ARM平台下的GDB。一種方法是手動的交叉編譯,另外一種就是安裝gdb-multiarch,它支持多種平台下的GDB。

附一下我用的命令行:qemu-system-x86_64 -s -S -hda xenial-server-cloudimg-amd64.img -initrd initrd.img-4.4.0-78-generic -kernel arch/x86/boot/bzImage -drive file=fat:rw:/media/sf_E_DRIVE/tools/mykey/ -redir tcp:5555::22 -append 'root=/dev/sda rw init=/usr/lib/cloud-init/uncloud-init ds=nocloud mem=1024M'

 

[1] http://elixir.free-electrons.com/linux/v4.11.4/source/fs/exec.c#L1660

[2] http://elixir.free-electrons.com/linux/v4.11.4/source/arch/x86/mm/mmap.c#L101

[3] http://elixir.free-electrons.com/linux/v4.11.4/source/fs/binfmt_elf.c#L875

[4] http://elixir.free-electrons.com/linux/v4.11.4/source/fs/exec.c#L696

[5] https://lwn.net/Articles/631631/

[6] https://sploitfun.wordpress.com/2015/02/11/syscalls-used-by-malloc/

[7] http://elixir.free-electrons.com/linux/v4.11.4/source/fs/binfmt_elf.c#L1078

[8] http://elixir.free-electrons.com/linux/v4.11.4/source/fs/binfmt_elf.c#L939

[9] http://www.alterawiki.com/wiki/Debug_Kernel

[10] https://stackoverflow.com/questions/29151235/how-to-de-optimize-the-linux-kernel-to-and-compile-it-with-o0

[11] http://cloud-images.ubuntu.com/

[12] https://stackoverflow.com/questions/29151235/how-to-de-optimize-the-linux-kernel-to-and-compile-it-with-o0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM