第八章 ARM 利用
作者:Aditya Gupta
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
在本章中,我們將了解 ARM 處理器的基礎(chǔ)知識(shí)侈离,和 ARM 世界中存在的不同類型的漏洞覆醇。 我們甚至?xí)^續(xù)利用這些漏洞吵取,以便對(duì)整個(gè)場(chǎng)景有個(gè)清晰地了解藕夫。 此外昌屉,我們將研究不同的 Android root 攻擊和它們?cè)诼┒蠢弥械幕韭┒础?考慮到目前大多數(shù) Android 智能手機(jī)都使用基于 ARM 的處理器丸凭,對(duì)于滲透測(cè)試人員來(lái)說(shuō)福扬,了解 ARM 及其附帶的安全風(fēng)險(xiǎn)至關(guān)重要。
8.1 ARM 架構(gòu)導(dǎo)論
ARM 是基于精簡(jiǎn)指令集(RISC)的架構(gòu)惜犀,這意味著其指令比基于復(fù)雜指令集(CISC)的機(jī)器少得多铛碑。 ARM 處理器幾乎遍布我們周?chē)乃性O(shè)備,如智能手機(jī)虽界,電視汽烦,電子書(shū)閱讀器和更多的嵌入式設(shè)備。
ARM 總共有 16 個(gè)可見(jiàn)的通用寄存器莉御,為 R0-R15撇吞。 在這 16 個(gè)中,有 5 個(gè)用于特殊目的礁叔。 以下是這五個(gè)寄存器及其名稱:
- R11: 幀指針 (FP)
- R12: 過(guò)程內(nèi)寄存器 (IP)
- R13: 棧指針 (SP)
- R14: 鏈接寄存器 (LR)
- R15: 程序計(jì)數(shù)器 (PC)
下面的圖展示了 ARM 架構(gòu):
在五個(gè)里面牍颈,我們會(huì)特別專注于這三個(gè),它們是:
- 堆棧指針(SP):這是保存指向堆棧頂部的指針的寄存器
- 鏈接寄存器(LR):當(dāng)程序進(jìn)入子過(guò)程時(shí)存儲(chǔ)返回地址
- 程序計(jì)數(shù)器(PC):存儲(chǔ)要執(zhí)行的下一條指令
注意
這里要注意的一點(diǎn)是琅关,PC 將總是指向要執(zhí)行的指令煮岁,而不是簡(jiǎn)單地指向下一條指令。 這是由于被稱為流水線的概念涣易,指令按照以下順序操作:提取画机,解碼和執(zhí)行。 為了控制程序流新症,我們需要控制 PC 或 LR 中的值(后者最終引導(dǎo)我們控制 PC)步氏。
執(zhí)行模式
ARM 有兩種不同的執(zhí)行模式:
- ARM 模式:在 ARM 模式下,所有指令的大小為 32 位
- Thumb 模式:在 Thumb 模式下账劲,指令大部分為 16 位
執(zhí)行模式由 CPSR 寄存器中的狀態(tài)決定。 還存在第三模式金抡,即 Thumb-2 模式瀑焦,它僅僅是 ARM 模式和 Thumb 模式的混合。 我們?cè)诒菊虏粫?huì)深入了解 ARM 和 Thumb 模式之間的區(qū)別梗肝,因?yàn)樗隽吮緯?shū)的范圍榛瓮。
8.2 建立環(huán)境
在開(kāi)始利用 ARM 平臺(tái)的漏洞之前,建議你建立環(huán)境巫击。 即使 Android SDK 中的模擬器可以通過(guò)模擬 ARM 平臺(tái)來(lái)運(yùn)行禀晓,大多數(shù)智能手機(jī)也是基于 ARM 的精续,我們將通過(guò)配置 QEMU(它是一個(gè)開(kāi)源硬件虛擬機(jī)和模擬器)開(kāi)始 ARM 漏洞利用。
為了在 Android 模擬器/設(shè)備上執(zhí)行以下所有步驟粹懒,我們需要下載 Android NDK 并使用 Android NDK 中提供的工具為 Android 平臺(tái)編譯我們的二進(jìn)制文件重付。 但是,如果你使用 Mac 環(huán)境凫乖,安裝 QEMU 相對(duì)容易确垫,可以通過(guò)鍵入brew install qemu
來(lái)完成。 現(xiàn)在讓我們?cè)?Ubuntu 系統(tǒng)上配置 QEMU帽芽。 遵循以下步驟:
-
第一步是通過(guò)安裝依賴來(lái)下載并安裝 QEMU删掀,如圖所示:
sudo apt-get build-dep qemu wget http://wiki.qemu-project.org/download/qemu- 1.7.0.tar.bz2
-
接下來(lái),我們只需要配置QEMU导街,指定目標(biāo)為 ARM披泪,最后充分利用它。 因此搬瑰,我們將簡(jiǎn)單地解壓縮歸檔文件款票,訪問(wèn)該目錄并執(zhí)行以下命令:
./configure --target-list=arm-softmmu make && make install
一旦QEMU成功安裝,我們可以下載 ARM 平臺(tái)的 Debian 鏡像來(lái)進(jìn)行利用練習(xí)跌捆。 所需下載列表位于
http://people.debian.org/~aurel32/qemu/armel/
徽职。-
這里我們將下載格式為
qcow2
的磁盤(pán)映像,它是基于 QEMU 的操作系統(tǒng)映像格式佩厚,也就是我們的操作系統(tǒng)為debian_squeeze_armel_standard.qcow2
姆钉。 內(nèi)核文件應(yīng)該是vmlinuz-2.6.32-5-versatile
,RAM 磁盤(pán)文件應(yīng)該是initrd.img-2.6.32-versatile
抄瓦。 一旦我們下載了所有必要的文件潮瓶,我們可以通過(guò)執(zhí)行以下命令來(lái)啟動(dòng) QEMU 實(shí)例:qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.32-5- versatile -initrd initrd.img-2.6.32-5-versatile -hda debian_squeeze_armel_standard.qcow2 -append "root=/dev/sda1" --redir tcp:2222::22
-
redir
命令只是在登錄遠(yuǎn)程系統(tǒng)時(shí)使用端口 2222 啟用 ssh。
一旦配置完成钙姊,我們可以使用以下命令登錄到 Debian 的 QEMU 實(shí)例:ssh root@[ip address of Qemu] -p 2222
登錄時(shí)會(huì)要求輸入用戶名和密碼毯辅,默認(rèn)憑據(jù)是
root:root
。一旦我們成功登錄煞额,我們將看到類似如下所示的屏幕截圖:
8.3 基于棧的簡(jiǎn)單緩沖區(qū)溢出
簡(jiǎn)單來(lái)說(shuō)思恐,緩沖區(qū)是存儲(chǔ)任何類型的數(shù)據(jù)的地方。 當(dāng)緩沖區(qū)中的數(shù)據(jù)超過(guò)緩沖區(qū)本身的大小時(shí)膊毁,會(huì)發(fā)生溢出胀莹。 然后攻擊者可以執(zhí)行溢出攻擊,來(lái)獲得對(duì)程序的控制和執(zhí)行惡意載荷婚温。
讓我們使用一個(gè)簡(jiǎn)單程序的例子描焰,看看我們?nèi)绾卫盟?在下面的截圖中,我們有一個(gè)簡(jiǎn)單的程序栅螟,有三個(gè)函數(shù):weak
荆秦,ShouldNotBeCalled
和main
篱竭。 以下是我們?cè)噲D利用的程序:
在整個(gè)程序運(yùn)行期間,從不調(diào)用ShouldNotBeCalled
函數(shù)步绸。
漏洞函數(shù)簡(jiǎn)單地將參數(shù)復(fù)制到名為buff
的緩沖區(qū)掺逼,大小為 10 字節(jié)。
一旦我們完成程序編寫(xiě)靡努,我們可以使用gcc
編譯它坪圾,如下一個(gè)命令所示。 此外惑朦,我們將在這里禁用地址空間布局隨機(jī)化(ASLR)兽泄,只是為了使場(chǎng)景稍微簡(jiǎn)單一些。 ASLR 是由 OS 實(shí)現(xiàn)的安全技術(shù)漾月,來(lái)防止攻擊者有效地確定載荷的地址并執(zhí)行惡意指令病梢。 在 Android 中,ASLR 的實(shí)現(xiàn)始于 4.0梁肿。 你可以訪問(wèn)http://www.duosecurity.com/blog/exploit-mitigations-in-android-jelly-bean-4-1
了解所有 Android 安全實(shí)施蜓陌。
echo 0 > /proc/sys/kernel/randomize_va_space
gcc -g buffer_overflow.c -o buffer_overflow
接下來(lái),我們可以簡(jiǎn)單將二進(jìn)制文件加載到 GNU 調(diào)試器吩蔑,簡(jiǎn)稱 GDB钮热,然后開(kāi)始調(diào)試它,如下面的命令所示:
gdb -q buffer_overflow
現(xiàn)在我們可以使用disass
命令來(lái)反匯編特定的函數(shù)烛芬,這里是ShouldNotBeCalled
隧期,如下面的截圖所示:
正如我們?cè)谏厦娴慕貓D中可以看到的,ShouldNotBeCalled
函數(shù)從內(nèi)存地址0x00008408
開(kāi)始赘娄。 如果我們查看main
函數(shù)的反匯編仆潮,我們看到漏洞函數(shù)在0x000084a4
被調(diào)用并在0x000084a8
返回。 因此遣臼,由于程序進(jìn)入漏洞函數(shù)并使用易受攻擊的strcpy
性置,函數(shù)不檢查要復(fù)制的字符串的大小,并且如果我們能夠在程序進(jìn)入漏洞函數(shù)時(shí)控制子過(guò)程的 LR 揍堰,我們就能夠控制整個(gè)程序流程鹏浅。
這里的目標(biāo)是估計(jì)何時(shí) LR 被覆蓋,然后放入ShouldNotBeCalled
的地址屏歹,以便調(diào)用ShouldNotBeCalled
函數(shù)隐砸。 讓我們開(kāi)始使用一個(gè)長(zhǎng)參數(shù)運(yùn)行程序,如下面的命令所示西采,看看會(huì)發(fā)生什么凰萨。 在此之前继控,我們還需要在漏洞函數(shù)和strcpy
調(diào)用的地址設(shè)置斷點(diǎn)械馆。
b vulnerable
b *<address of the strcpy call>
一旦我們?cè)O(shè)置了斷點(diǎn)胖眷,我們可以使用參數(shù)AAAABBBBCCCC
來(lái)運(yùn)行我們的程序,看看它是如何被覆蓋的霹崎。 我們注意到它在漏洞函數(shù)的調(diào)用處命中了第一個(gè)斷點(diǎn)珊搀,之后在strcpy
調(diào)用處命中了下一個(gè)斷點(diǎn)。 一旦它到達(dá)斷點(diǎn)尾菇,我們可以使用x
命令分析堆棧境析,并指定來(lái)自 SP 的地址,如下面的截圖所示:
我們可以看到派诬,堆棧已經(jīng)被我們輸入的緩沖區(qū)覆蓋(ASCII:41 代表 A劳淆,42 代表 B,等等)默赂。 從上面的截圖中沛鸵,我們看到,我們?nèi)匀恍枰膫€(gè)更多的字節(jié)來(lái)覆蓋返回地址缆八,在這種情況下是0x000084a8
曲掰。
所以,最后的字符串是 16 字節(jié)的垃圾奈辰,然后是ShouldNotBeCalled
的地址栏妖,如下面的命令所示:
r `printf "AAAABBBBCCCCDDDD\x38\x84"`
我們可以在下面的截圖中看到,我們已經(jīng)將IShouldNeverBeCalled
的起始地址添加到了參數(shù)中:
請(qǐng)注意奖恰,由于這里是小端結(jié)構(gòu)吊趾,字節(jié)以相反的順序?qū)懭搿?一旦我們運(yùn)行它,我們可以看到程序ShouldNotBeCalled
函數(shù)被調(diào)用房官,如下面的截圖所示:
8.4 返回導(dǎo)向編程
在大多數(shù)情況下趾徽,我們不需要調(diào)用程序本身中存在的另一個(gè)函數(shù)。 相反翰守,我們需要在我們的攻擊向量中放置 shellcode孵奶,這將執(zhí)行我們?cè)?shellcode 中指定的任何惡意操作。 但是蜡峰,在大多數(shù)基于 ARM 平臺(tái)的設(shè)備中了袁,內(nèi)存中的區(qū)域是不可執(zhí)行的,這會(huì)阻止我們放置并執(zhí)行 shellcode湿颅。
因此载绿,攻擊者必須依賴于所謂的返回導(dǎo)向編程(ROP),它是來(lái)自內(nèi)存不同部分的指令片段的簡(jiǎn)單鏈接油航,最終它會(huì)執(zhí)行我們的 shellcode崭庸。 這些片段也稱為 ROP gadget。 為了鏈接 ROP gadget,我們需要找到存在跳轉(zhuǎn)指令的 gadget怕享,這將允許我們跳到另一個(gè)位置执赡。
例如,如果我們?cè)趫?zhí)行程序時(shí)反匯編seed48()
函筋,我們將注意到以下輸出:
如果我們查看反匯編沙合,我們將注意到它包含一個(gè) ADD 指令,后面跟著一個(gè) POP 和 BX 指令跌帐,這是一個(gè)完美的 ROP gadget首懈。 這里,攻擊者可能會(huì)想到谨敛,為了將其用作 ROP gadget究履,首先跳到控制 r4 的 POP 指令,然后將比/bin/sh
的地址小 6 的值放入 r4 中脸狸,將 ADD 指令的值放入 LR 中挎袜。 因此,當(dāng)我們跳回到 ADD 也就是R0 = R4 + 6
時(shí)肥惭,我們就擁有了/bin/sh
的地址盯仪,然后我們可以為 R4 指定任何垃圾地址并且為 LR 指定system()
的地址。
這意味著我們將最終跳轉(zhuǎn)到使用參數(shù)/bin/sh
的system()
蜜葱,這將執(zhí)行 shell全景。 以同樣的方式,我們可以創(chuàng)建任何 ROP gadget牵囤,并使其執(zhí)行我們所需要的任何東西爸黄。 由于 ROP 是開(kāi)發(fā)中最復(fù)雜的主題之一,因此強(qiáng)烈建議你自己嘗試揭鳞,分析反匯編代碼并構(gòu)建漏洞炕贵。
8.5 Android root 利用
從早期版本的 Android 開(kāi)始,Android root 漏洞開(kāi)始出現(xiàn)于每個(gè)后續(xù)版本和不同的 Android 設(shè)備制造商的版本中野崇。 Android root 簡(jiǎn)單來(lái)說(shuō)是獲得對(duì)設(shè)備的訪問(wèn)特權(quán)称开,默認(rèn)情況下設(shè)備制造商不會(huì)將其授予用戶。 這些 root 攻擊利用了 Android 系統(tǒng)中存在的各種漏洞乓梨。 以下是其中一些的列表鳖轰,帶有漏洞利用所基于的思想:
- Exploid:基于 udev 中的 CVE-2009-1185 漏洞,它是 Android 負(fù)責(zé) USB 連接的組件扶镀,它驗(yàn)證 Netlink 消息(一種負(fù)責(zé)將 Linux 內(nèi)核與用戶連接的消息)是否源自原始來(lái)源或是由攻擊者偽造蕴侣。因此,攻擊者可以簡(jiǎn)單地從用戶空間本身發(fā)送 udev 消息并提升權(quán)限臭觉。
- Gingerbreak:這是另一個(gè)漏洞昆雀,基于 vold 中存在的漏洞辱志,類似于 Exploid 中的漏洞。
- RageAgainstTheCage:此漏洞利用基于
RLIMIT_NPROC
狞膘,它指定在調(diào)用setuid
函數(shù)時(shí)可為用戶創(chuàng)建的進(jìn)程的最大數(shù)目荸频。 adb 守護(hù)程序以 root 身份啟動(dòng);然后它使用setuid()
調(diào)用來(lái)解除特權(quán)。但是客冈,如果根據(jù)RLIMIT_NPROC
達(dá)到了最大進(jìn)程數(shù),程序?qū)o(wú)法調(diào)用setuid()
來(lái)解除特權(quán)稳强,adb 將繼續(xù)以 root 身份運(yùn)行场仲。 - Zimperlich:使用與 RageAgainstTheCage 的相同概念,但它依賴于 zygote 進(jìn)程解除 root 權(quán)限退疫。
- KillingInTheNameOf:利用了一個(gè)稱為
ashmem
(共享內(nèi)存管理器)接口的漏洞渠缕,該漏洞用于更改ro.secure
的值,該值確定設(shè)備的 root 狀態(tài)褒繁。
這些是一些最知名的 Android 漏洞利用亦鳞,用于 root Android 設(shè)備。
總結(jié)
在本章中棒坏,我們了解了 Android 利用和 ARM 利用的不同方式燕差。 希望本章對(duì)于任何想要更深入地利用 ARM 的人來(lái)說(shuō),都是一個(gè)好的開(kāi)始坝冕。
在下一章中徒探,我們將了解如何編寫(xiě) Android 滲透測(cè)試報(bào)告。