【技术分享】如何解锁高通骁龙660上的安卓引导加载程序
本文是我們?cè)贒EF CON
29大會(huì)上的演示視頻的配套文章,視頻的鏈接地址為https://www.youtube.com/watch?v=z4gIxdFfJDg。
要想在安卓手機(jī)上獲得root權(quán)限,通常需要解鎖引導(dǎo)加載程序,禁用手機(jī)的簽名驗(yàn)證,這樣的話,我們就可以部署一個(gè)修改過(guò)的安卓引導(dǎo)映像了。在Qualcomm芯片組上,這是一個(gè)標(biāo)準(zhǔn)化的過(guò)程,可以使用安卓引導(dǎo)加載程序中的命令來(lái)執(zhí)行解鎖。智能手機(jī)制造商經(jīng)常修改引導(dǎo)加載程序以增加特定的限制,但是,這通常要求使用他們自家的工具。
這些自定義的限制通常包括:強(qiáng)迫創(chuàng)建一個(gè)用戶賬戶來(lái)請(qǐng)求解鎖,并在允許解鎖之前強(qiáng)制等待一段時(shí)間,等等。
那么,手機(jī)制造商為什么要添加這些限制呢?原因如下所示:
? 防止沒(méi)有經(jīng)驗(yàn)的用戶因?yàn)槭茯_而削弱手機(jī)的安全性;
? 防止第三方在售前給設(shè)備加載惡意軟件(如供應(yīng)鏈攻擊);
? 制造商可以跟蹤是誰(shuí)解鎖了他們的引導(dǎo)加載程序。
我購(gòu)買的手機(jī)就有這些限制,要求我等待七天后才能獲得設(shè)備的root權(quán)限。由于這個(gè)原因,我決定調(diào)查我是否可以繞過(guò)同一制造商生產(chǎn)的舊智能手機(jī)的等待期。我給自己設(shè)定了一個(gè)挑戰(zhàn),即在七天等待期結(jié)束前繞過(guò)引導(dǎo)加載程序的保護(hù)。
標(biāo)準(zhǔn)繞過(guò)方法
實(shí)際上,現(xiàn)在已經(jīng)有一些標(biāo)準(zhǔn)方法可以繞過(guò)這些限制,然而,它們都具有相應(yīng)的風(fēng)險(xiǎn)。
其中,最常用的方法就是進(jìn)入高通公司緊急下載模式。這是一種低級(jí)別的緊急狀態(tài)啟動(dòng)模式,可以使用診斷工具將具有簽名的“加載器”有效載荷上傳至芯片,這樣,就可以直接修改設(shè)備的分區(qū)了。雖然這種方法是有效的,但這要求用戶先引導(dǎo)進(jìn)入該模式(并非所有用戶都可以直接進(jìn)入該模式),并且需要訪問(wèn)可能無(wú)法用于該設(shè)備的已簽名加載程序ELF文件。
第二種常見(jiàn)的方法是在硬件層面上攻擊設(shè)備。通過(guò)拆卸手機(jī),并連接電路板上的EMMC芯片,就能在配置分區(qū)中設(shè)置“解鎖”位,從而獲得解鎖權(quán)限。現(xiàn)在,已經(jīng)有一些這方面的公開(kāi)資料,其中說(shuō)明了應(yīng)該連接到哪些引腳,但是這通常需要一些硬件知識(shí)和動(dòng)手能力。此外,硬件一旦受到物理?yè)p壞,手機(jī)就可能永遠(yuǎn)變磚了。
因此,我可不想使用這兩種方法,相反,我的目標(biāo)是攻擊第二階段的引導(dǎo)加載程序。這是因?yàn)?#xff0c;雖然通過(guò)第一階段的引導(dǎo)加載程序可以進(jìn)入緊急下載模式,但是在引導(dǎo)過(guò)程的下一個(gè)階段,卻可以獲得額外的診斷和管理工具。
SDM660安卓手機(jī)
目標(biāo)設(shè)備是2017年發(fā)布的一款中檔手機(jī),它使用Qualcomm Snapdragon 660作為核心芯片組。
對(duì)制造商實(shí)現(xiàn)的自定義解鎖功能的分析表明,它會(huì)將一個(gè)較小的唯一值從手機(jī)發(fā)送到解鎖工具,并在其服務(wù)器上生成一個(gè)簽名。七天后,這個(gè)簽名將被發(fā)送到手機(jī)上并進(jìn)行驗(yàn)證,從而完成解鎖。我是借助于Windows主機(jī)和USBPCAP USB分析軟件對(duì)這個(gè)過(guò)程進(jìn)行分析的。
我發(fā)現(xiàn),對(duì)唯一值的請(qǐng)求、簽名的發(fā)送以及對(duì)引導(dǎo)加載程序解鎖的請(qǐng)求,都是通過(guò)安卓引導(dǎo)加載程序的Fastboot界面完成的。通過(guò)手機(jī)上的ADB重新啟動(dòng)到引導(dǎo)加載程序模式,或者在啟動(dòng)時(shí)按住音量下降鍵,就可以訪問(wèn)這個(gè)界面。然后,我們可以使用命令行工具“fastboot”,通過(guò)USB訪問(wèn)該界面。
Fastboot工具
這個(gè)工具能夠簡(jiǎn)化對(duì)標(biāo)準(zhǔn)和定制的功能的訪問(wèn),包括閃存分區(qū)、獲得OEM特定的數(shù)據(jù),或引導(dǎo)至不同的模式。對(duì)這個(gè)工具的分析表明,fastboot協(xié)議非常簡(jiǎn)單,可以用基本的C++代碼和LibUSB進(jìn)行實(shí)現(xiàn)。
分析表明,這個(gè)工具的所有的命令都是通過(guò)一個(gè)USB端點(diǎn)以ASCII文本形式發(fā)送的,而對(duì)命令的響應(yīng)則是由另一個(gè)端點(diǎn)異步發(fā)送的。同時(shí),雖然可以借助于某些程序庫(kù)來(lái)簡(jiǎn)化對(duì)fastboot界面的訪問(wèn),但是,我還是決定使用LibUSB,因?yàn)檫@樣能夠更好地控制通信過(guò)程。
ABL引導(dǎo)加載程序
實(shí)際上,fastboot界面是由安卓引導(dǎo)加載程序提供的,它屬于第二階段的引導(dǎo)加載程序,存儲(chǔ)在手機(jī)的“abl”分區(qū)中。這個(gè)引導(dǎo)加載程序的作用,就是驗(yàn)證和加載手機(jī)的安卓映像和恢復(fù)映像,以實(shí)現(xiàn)其標(biāo)準(zhǔn)功能,或接收f(shuō)astboot命令。需要說(shuō)明的是,這個(gè)引導(dǎo)加載程序的高通版本是完全開(kāi)源的,以便于手機(jī)制造商對(duì)其進(jìn)行修改。
由于我想攻擊這個(gè)引導(dǎo)加載程序,所以,我希望從底層分析其功能。另外,由于手機(jī)制造商添加的自定義命令不會(huì)出現(xiàn)在源代碼中,所以,我決定直接分析編譯后的引導(dǎo)加載程序。為此,我們可以下載最新的OTA更新文件,然后解壓縮,并訪問(wèn)存儲(chǔ)在其中的“abl.img”文件,這樣,我們就能夠訪問(wèn)手機(jī)“abl”分區(qū)的內(nèi)容了。通過(guò)對(duì)這個(gè)映像進(jìn)行分析發(fā)現(xiàn),雖然這是一個(gè)ELF文件,但是其中并沒(méi)有包含任何可執(zhí)行代碼。
相反,通過(guò)文件分析工具“binwalk”對(duì)該文件的分析結(jié)果表明,該ELF文件包含一個(gè)EFI系統(tǒng)分區(qū)。這是一種用于在嵌入式和非嵌入式設(shè)備上啟動(dòng)操作系統(tǒng)的標(biāo)準(zhǔn)格式,并且,我們可以使用“uefi-firmware-parser”工具將其提取出來(lái)。
實(shí)際上,存儲(chǔ)在其中的“LinuxLoader”文件是一個(gè)PE格式的可執(zhí)行文件,其內(nèi)容就是引導(dǎo)加載程序的代碼。這種標(biāo)準(zhǔn)的格式可以直接加載到IDA中,并進(jìn)行反匯編。
對(duì)該引導(dǎo)加載程序的簡(jiǎn)單分析表明,所有的fastboot命令都存儲(chǔ)在一個(gè)表中,該表由ASCII命令和該命令的函數(shù)回調(diào)組成。通過(guò)這個(gè)表,不僅可以快速分析任何潛在的隱藏命令,同時(shí),還有助于分析具體的功能。我們還發(fā)現(xiàn),該引導(dǎo)加載程序中包含大量的調(diào)試字符串,這使得對(duì)代碼的理解更加容易。
我的主要目標(biāo)是找到一個(gè)內(nèi)存損壞漏洞,以便通過(guò)它繞過(guò)解鎖限制。為此,我決定把重點(diǎn)放在“flash:”命令上。我之所以選擇這個(gè)命令,是因?yàn)樗枰獜腜C主機(jī)接收大型有效載荷,并將其保存到閃存設(shè)備分區(qū)。
傳統(tǒng)上,當(dāng)引導(dǎo)加載程序被鎖定時(shí),“flash:”命令是不允許對(duì)設(shè)備上的分區(qū)執(zhí)行寫操作的,但是我注意到,制造商已經(jīng)修改了他們的引導(dǎo)加載程序,以允許在鎖定狀態(tài)下刷寫特定的、自定義的分區(qū)。由于這些分區(qū)對(duì)上傳的數(shù)據(jù)進(jìn)行了額外的解析,因此,這就增加了存在缺陷的可能性。
因?yàn)槲沂菑哪嫦蚬こ痰慕嵌葋?lái)研究fastboot協(xié)議的,而不是通過(guò)閱讀文檔來(lái)了解它的,因此,我對(duì)數(shù)據(jù)上傳的方式做了一些假設(shè)。上傳的正確順序如下所示:
?download:< payload size >
?< send full payload >
?flash:< partition >
但是,我嘗試的是以下順序:
?flash:< partition >
?< send payload >
除此之外,我在代碼中的這個(gè)序列后面,故意放入了一個(gè)額外的“flash:”命令。因此,當(dāng)運(yùn)行這個(gè)序列時(shí),將導(dǎo)致引導(dǎo)加載程序在執(zhí)行第二個(gè)“flash:”命令后發(fā)生崩潰,從而導(dǎo)致USB接口不再接收任何命令。
崩潰分析
將設(shè)備從USB端口上拔下來(lái),再插回去,我們發(fā)現(xiàn)它就不再通過(guò)USB進(jìn)行枚舉了,這意味著它完全無(wú)法正常工作了。按住電源和音量減弱按鈕10秒鐘,導(dǎo)致硬重啟,我們發(fā)現(xiàn)上述操作并沒(méi)有對(duì)設(shè)備產(chǎn)生永久性的損壞。
為了確認(rèn)我偶然發(fā)現(xiàn)的是一個(gè)有效的緩沖區(qū)溢出,我決定嘗試一個(gè)較小的有效載荷大小。我從一個(gè)10兆字節(jié)的有效載荷開(kāi)始,并嘗試用4千字節(jié)的有效載荷進(jìn)行同樣的序列。這個(gè)較小的有效載荷并沒(méi)有使手機(jī)崩潰,它繼續(xù)正常運(yùn)行。
在閱讀了如何在fastboot中使用“download:”命令上傳數(shù)據(jù)之后,我猜測(cè)可能是發(fā)生了緩沖區(qū)溢出,因?yàn)槲野l(fā)送的大量有效載荷被視為fastboot命令,而不是要上傳的分區(qū)。這意味著崩潰是由于高通引導(dǎo)加載程序的命令處理功能的漏洞所致,而不是由手機(jī)制造商實(shí)現(xiàn)的任何自定義功能所致。
為了確認(rèn)我偶然發(fā)現(xiàn)的是一個(gè)有效的緩沖區(qū)溢出漏洞,我決定嘗試一個(gè)較小的有效載荷長(zhǎng)度。我從一個(gè)10兆字節(jié)的有效載荷開(kāi)始,并嘗試了長(zhǎng)度為4千字節(jié)的相同序列的有效載荷。這個(gè)較小的有效載荷并沒(méi)有導(dǎo)致手機(jī)崩潰,相反,手機(jī)一切正常。
由于較小的有效載荷不會(huì)導(dǎo)致崩潰,所以,我選擇進(jìn)行二分搜索,以確定不會(huì)使手機(jī)崩潰的最大有效載荷。我把要發(fā)送的有效載荷的長(zhǎng)度設(shè)為最小值和最大值之間的中間值,然后更具手機(jī)是否崩潰,來(lái)減少有效載荷長(zhǎng)度的最大值,或增加有效載荷長(zhǎng)度的最小值。這使我找到了不會(huì)使設(shè)備崩潰的最大有效載荷,其長(zhǎng)度為0x11bae0(1161952)字節(jié)。
由于這是一個(gè)不尋常的內(nèi)存大小,這讓我相信這肯定是某種類型的緩沖區(qū)溢出,然而,由于我無(wú)法接觸到內(nèi)部硬件,無(wú)法進(jìn)行調(diào)試,對(duì)內(nèi)存的映射情況一無(wú)所知,所以,具體是哪種類型的溢出,我還是拿不準(zhǔn)。另外我注意到,引導(dǎo)加載程序使用隨機(jī)值實(shí)現(xiàn)了堆棧金絲雀,這意味著如果我溢出堆棧并擊中了金絲雀,那么,這種溢出漏洞很可能是無(wú)法利用的。
我決定發(fā)送一個(gè)長(zhǎng)度為0x11bae1(1161953)字節(jié)的有效載荷,并將最后一個(gè)字節(jié)的值從0x00遞增為0xff。如果手機(jī)沒(méi)有因?yàn)槠渲心硞€(gè)特定的值而崩潰,那就說(shuō)明并沒(méi)有碰到堆棧金絲雀,而是找到了序列中的下一個(gè)字節(jié)。在這個(gè)位置,我們發(fā)現(xiàn)有效字節(jié)的值是0xff。
通過(guò)不斷地循環(huán)加電,尋找有效的字節(jié)值,然后移動(dòng)到序列中的下一個(gè)字節(jié),就可以生成該位置上內(nèi)存中數(shù)據(jù)的合理表示。當(dāng)然,它不一定是準(zhǔn)確的數(shù)據(jù),但會(huì)足夠接近,并且不會(huì)使引導(dǎo)加載程序崩潰。一旦生成這個(gè)序列,就有可能使用它來(lái)在引導(dǎo)加載程序中執(zhí)行代碼,但是如果不能自動(dòng)化的話,這將是一個(gè)非常漫長(zhǎng)的過(guò)程。
實(shí)現(xiàn)自動(dòng)循環(huán)加電
實(shí)際上,加電循環(huán)的自動(dòng)化可以通過(guò)拆除手機(jī)電池,使用主機(jī)PC供電,并使用USB繼電器不斷切斷電源來(lái)實(shí)現(xiàn)自動(dòng)化,但這需要拆卸手機(jī)并去除外殼周圍的膠水。另外,如果我拆解手機(jī),我可以直接進(jìn)入EMMC,用基于硬件的方法解鎖引導(dǎo)加載程序。
在尋找解決方案的時(shí)候,我不斷按住手機(jī)的電源和音量下降按鈕。這導(dǎo)致手機(jī)處于引導(dǎo)循環(huán)狀態(tài):它將重新啟動(dòng)并加載引導(dǎo)加載程序幾秒鐘,然后再次重新啟動(dòng)。我注意到,在這個(gè)過(guò)程中,USB接口會(huì)工作一段時(shí)間,并且這段時(shí)間足以讓我發(fā)送fastboot命令。
于是,我在導(dǎo)致引導(dǎo)循環(huán)的兩個(gè)按鈕上纏了一條發(fā)帶,并發(fā)現(xiàn)這種方法非常管用,所以,這樣就實(shí)現(xiàn)了這一過(guò)程的自動(dòng)化。
然后,我修改了自己編寫的fastboot工具,以便于內(nèi)存轉(zhuǎn)儲(chǔ)。它將等待USB接口出現(xiàn),嘗試這個(gè)序列,然后驗(yàn)證引導(dǎo)加載程序是否崩潰,以及是否收到了 “Flashing is not allowed ”響應(yīng)。我們對(duì)這兩件事情進(jìn)行了驗(yàn)證,因?yàn)檫@更有可能獲得準(zhǔn)確的內(nèi)存轉(zhuǎn)儲(chǔ)。每次嘗試都需要10-30秒,這意味著內(nèi)存轉(zhuǎn)儲(chǔ)將需要一段時(shí)間。
于是,我讓手機(jī)連夜嘗試這種內(nèi)存轉(zhuǎn)儲(chǔ)方法,并發(fā)現(xiàn)了0x34字節(jié)不會(huì)導(dǎo)致引導(dǎo)加載程序發(fā)生崩潰的數(shù)據(jù):
FF 43 02 51 60 02 00 0C 60 02 00 0C 60 02 00 0C 60 02 00 0C E8 00 00 B0 34 00 00 10 01 00 00 0A 08 0D 40 F9 00 00 00 08 C0 00 04 0B 60 02 00 0A D3 9F FF 97
我注意到其中有許多重復(fù)的值,但這些值與默認(rèn)的堆棧金絲雀值0xC0C0C0C0并不一致,這意味著它們可能是不相關(guān)的。另外,這些數(shù)據(jù)看起來(lái)并不像在堆棧中常見(jiàn)的東西,但是我們發(fā)現(xiàn)每個(gè)32位的字都是一個(gè)有效的ARM64操作碼。
這些操作碼中的大多數(shù)雖然有效,但不一定與引導(dǎo)加載程序中的操作碼相同,但是所有的堆棧管理和分支操作必須相當(dāng)準(zhǔn)確,這樣引導(dǎo)加載程序才不會(huì)崩潰。我試圖利用IDA在引導(dǎo)加載程序的反匯編代碼中搜索“Sub WSP”和“BL”指令,但是,并沒(méi)可有找到它們。
當(dāng)然,導(dǎo)致這種情況的原因有多種。例如,ARM64操作碼通常具有相同或類似的功能,即使操作碼中的位被翻轉(zhuǎn),寄存器也可以在32位(Wx)和64位(Xx)模式下被訪問(wèn),同時(shí),分支指令也可能帶有某些條件,而現(xiàn)在蠻力攻擊恰好無(wú)法滿足這些條件。
由于這些外觀上的差異,我決定嘗試尋找類似的操作碼,選擇我已經(jīng)確定的“BL”指令,因?yàn)檫@依賴于相對(duì)尋址,而且地址必須相當(dāng)相似,才能正確執(zhí)行分支。我對(duì)操作碼的32位值進(jìn)行了文本搜索,但刪除了第一個(gè)四位組。這樣的話,就可以在前面試圖刷寫到那個(gè)分區(qū)的解析器中尋找類似的分支,并確定了一條有效的指令。
對(duì)其他操作碼的進(jìn)一步檢查表明,這些操作也極其相似。這意味著,我的引導(dǎo)加載程序緩沖區(qū)的溢出內(nèi)容正在覆蓋緩沖器溢出本身。這也意味著引導(dǎo)加載程序是從EFI文件系統(tǒng)中提取并從RAM中執(zhí)行的。
對(duì)所用地址的進(jìn)一步分析表明,引導(dǎo)加載程序代碼在0x101000字節(jié)之后被覆蓋了,并允許使用從PE可執(zhí)行文件中提取的代碼覆蓋整個(gè)引導(dǎo)加載程序,即用引導(dǎo)加載程序覆蓋其自身。這樣做的好處是可以防止隨后的崩潰,并可以通過(guò)修補(bǔ)引導(dǎo)加載程序本身來(lái)修改所需的任何功能,包括引導(dǎo)加載程序的解鎖代碼。
解鎖引導(dǎo)加載程序
找到引導(dǎo)加載程序代碼是為了驗(yàn)證解鎖工具提供的RSA簽名,以便進(jìn)行解鎖。我想跳過(guò)這個(gè)驗(yàn)證,直接進(jìn)行解鎖。我注意到引導(dǎo)加載程序的解鎖功能是通過(guò)轉(zhuǎn)移并連接指令(Branch and Link instruction)實(shí)現(xiàn)的,它是由編譯器為函數(shù)調(diào)用而生成的,因此,我決定修改最初用于緩沖區(qū)溢出的代碼,直接跳轉(zhuǎn)到這個(gè)指令。我為它生成了正確的相對(duì)地址,并使用一個(gè)在線ARM64編譯器生成了適當(dāng)?shù)腂L指令。然后,我把它添加到引導(dǎo)加載程序中,以實(shí)現(xiàn)這個(gè)跳轉(zhuǎn)。
雖然很難調(diào)試這個(gè)過(guò)程,但成功解鎖是顯而易見(jiàn)的:手機(jī)會(huì)重新啟動(dòng),擦除用戶數(shù)據(jù)分區(qū),并引導(dǎo)至解鎖狀態(tài)。這說(shuō)明該方法的確是有效的,因?yàn)樵O(shè)備成功解鎖了。
漏洞的影響
現(xiàn)在,我可以在不借助制造商的工具的情況下,對(duì)我的舊手機(jī)進(jìn)行刷機(jī),也不必等待七天。然而,試圖對(duì)較新的設(shè)備進(jìn)行類似的攻擊是無(wú)效的。因此,我認(rèn)為它只適用于基于SDM660的設(shè)備。
當(dāng)然,如果對(duì)引導(dǎo)加載程序進(jìn)行額外的修補(bǔ)的話,則可以實(shí)現(xiàn)更多的功能,例如為調(diào)試目的從設(shè)備上轉(zhuǎn)儲(chǔ)一些有限的RAM,但是由于引導(dǎo)加載程序可以訪問(wèn)的RAM區(qū)域是受限的,所以,這無(wú)法實(shí)現(xiàn)冷啟動(dòng)攻擊。
此外,高通芯片還可以對(duì)手機(jī)的“userdata”分區(qū)進(jìn)行加密,并且無(wú)需用戶輸入密碼或個(gè)人識(shí)別碼(PIN)。所以,這將阻止未簽名的Android映像和解鎖的引導(dǎo)加載程序直接訪問(wèn)它,這意味著即使執(zhí)行了此攻擊,用戶的數(shù)據(jù)仍將受到保護(hù)。此外,在默認(rèn)情況下,引導(dǎo)加載程序會(huì)解鎖并擦除此分區(qū)。
復(fù)現(xiàn)漏洞
為了證實(shí)我的理論,即所有SDM660設(shè)備都可能出現(xiàn)這種情況,我購(gòu)買了一部由不同制造商生產(chǎn)的、但具有相同芯片組的手機(jī)。這部手機(jī)的發(fā)布時(shí)間比第一部晚了好幾年,并且已經(jīng)完全禁用了引導(dǎo)器解鎖功能。
制造商通過(guò)類似于第一臺(tái)設(shè)備上發(fā)現(xiàn)的引導(dǎo)器解鎖的簽名保護(hù)機(jī)制來(lái)實(shí)現(xiàn)這一點(diǎn),但沒(méi)有發(fā)布相關(guān)的工具。
我使用新設(shè)備的OTA映像來(lái)提取引導(dǎo)加載程序,具體如前所述。
我試圖重現(xiàn)與以前相同的緩沖區(qū)溢出,不幸的是,這次并沒(méi)有成功。相反,通過(guò)發(fā)送一個(gè)更大的有效載荷,新設(shè)備確實(shí)崩潰了。通過(guò)使用與之前相同的二分搜索方法,可以確定這個(gè)引導(dǎo)加載程序的內(nèi)容是在0x403000字節(jié)之后被覆蓋的,而第一個(gè)引導(dǎo)加載程序被覆蓋的內(nèi)容位于第0x101000字節(jié)之后。有了這些信息,就可以迅速地開(kāi)發(fā)出一個(gè)解鎖的引導(dǎo)加載程序。
我找到了一條分支指令,如果簽名未通過(guò)驗(yàn)證,該指令將跳過(guò)解鎖過(guò)程。
通過(guò)使用一個(gè)NOP操作碼,這個(gè)分支可以被移除,從而在設(shè)備上實(shí)現(xiàn)引導(dǎo)加載程序解鎖。
由于該漏洞可能存在于所有基于SDM660的手機(jī)上,因此,我們直接向Qualcomm公司報(bào)告了該漏洞。
對(duì)于不允許用戶進(jìn)行解鎖的情況下,由于無(wú)需引導(dǎo)加載程序的訪問(wèn)權(quán)限,因此,可以完全禁止針對(duì)fastboot的訪問(wèn),以防止針對(duì)它的攻擊。然后,可以通過(guò)主安卓系統(tǒng)中的工程應(yīng)用程序重新激活fastboot。實(shí)際上,禁止消費(fèi)者解鎖引導(dǎo)器的制造商經(jīng)常使用這種方法。
繞過(guò)Qualcomm公司的用戶數(shù)據(jù)保護(hù)
如前所述,Qualcomm公司的芯片支持對(duì)“userdata”分區(qū)進(jìn)行加密,這樣就可以通過(guò)使用內(nèi)部密鑰來(lái)保護(hù)用戶數(shù)據(jù),而不需要在啟動(dòng)時(shí)輸入密碼。這個(gè)特性的好處在于,可以防止攻擊者通過(guò)chip-off分析,進(jìn)而通過(guò)未簽名的安卓映像訪問(wèn)數(shù)據(jù)。我想試試是否能繞過(guò)這種保護(hù),即通過(guò)修改引導(dǎo)加載程序的功能來(lái)訪問(wèn)用戶數(shù)據(jù)分區(qū)。
我使用Qualcomm公司的源代碼來(lái)確定如何訪問(wèn)加密密鑰和解密分區(qū)。我發(fā)現(xiàn),他們是故意不讓引導(dǎo)加載程序訪問(wèn)這些密鑰的,相反,要想訪問(wèn)密鑰,必須使用相應(yīng)的內(nèi)部API,而這個(gè)API并沒(méi)有被前面的攻擊所修改。實(shí)際上,這個(gè)API是用來(lái)驗(yàn)證引導(dǎo)安卓的映像的,以及驗(yàn)證引導(dǎo)加載程序是否被解鎖。
我注意到,這個(gè)函數(shù)調(diào)用并沒(méi)有引導(dǎo)相應(yīng)的映像,這意味著驗(yàn)證引導(dǎo)安卓映像的函數(shù)與實(shí)際啟引導(dǎo)系統(tǒng)的函數(shù)是相互獨(dú)立的。
我決定研究一下fastboot命令“boot”,該命令用于引導(dǎo)并執(zhí)行從主機(jī)上傳的Android映像。我注意到,驗(yàn)證映像和開(kāi)始執(zhí)行映像的函數(shù),實(shí)際上是兩個(gè)不同的函數(shù)。
然后,我決定看看能否可以修改引導(dǎo)加載程序,以便在這兩個(gè)調(diào)用之間交換已簽名和未簽名的Android映像。如果成功,我將能夠執(zhí)行一個(gè)未簽名的Android映像,而無(wú)需解鎖引導(dǎo)加載程序,從而獲得對(duì)加密的userdata分區(qū)的完全訪問(wèn)權(quán)。
修改boot命令
命令“boot”可以通過(guò)fastboot的“download:”命令接收一個(gè)完整的Android“boot”映像,然后,在RAM中驗(yàn)證并執(zhí)行該映像。我決定修改這個(gè)工具,使其可以接收多個(gè)Android映像。
我修改了fastboot工具,使它不再發(fā)送一個(gè)映像,而是發(fā)送:
? 一個(gè)四字節(jié)的、相對(duì)于未簽名映像的偏移量;
? 一個(gè)已簽名的映像;
? 一個(gè)經(jīng)過(guò)修改的未簽名映像。
完成上述任務(wù)之后,我還需要修補(bǔ)引導(dǎo)加載程序,以便使其可以正確使用這個(gè)有效載荷。我需要做的第一件事,就是繞過(guò)解鎖檢查。傳統(tǒng)上,“boot”命令只在引導(dǎo)加載程序被解鎖的情況下,才會(huì)引導(dǎo)上傳的映像,即使該映像已經(jīng)簽名。我決定在代碼中用一個(gè)操作碼來(lái)覆蓋這個(gè)檢查,將新的有效載荷的指針向上移動(dòng)四個(gè)字節(jié)——將其指向已簽名的Android映像。
這將導(dǎo)致在代碼到達(dá)“LoaderImageAndAuth”函數(shù)時(shí)對(duì)已簽名的映像進(jìn)行驗(yàn)證。
在此之后,我需要在這個(gè)函數(shù)和“bootlinux”函數(shù)之間留出足夠的空間,以便交換映像。我注意到,在這兩者之間調(diào)用的函數(shù)只是出于內(nèi)部管理的目的,提供“OK”響應(yīng)并關(guān)閉引導(dǎo)加載程序的某些功能,一旦Android映像啟動(dòng),這些功能就將被禁用。因此,我決定用交換映像所需的少量操作碼來(lái)覆蓋它們。
為此,我只需要在這些指令的基礎(chǔ)之上另外添加四條即可,這意味著有足夠的空間來(lái)做我需要的事情。具體來(lái)說(shuō),這四條指令及其作用如下所示:
? 將指針移回有效載荷的起點(diǎn)位置:sub x19, x19, 4;
? 讀取偏移值:ldr w22, [x19];
? 將偏移值添加到映像的指針中:add x19, x19, x22;
? 將新的指針值壓入“Info”結(jié)構(gòu)體的“ImageBuffer”指針中:str x19, [x21,#0xa0]。
這足以讓指針從已簽名的映像指向未簽名的映像,這將有助于從檢查時(shí)間到使用時(shí)間的攻擊,并允許在不解鎖引導(dǎo)加載程序的情況下運(yùn)行無(wú)簽名的映像。
通過(guò)鎖定的引導(dǎo)器來(lái)運(yùn)行未簽名的代碼
在許多情況下,我們都希望能在自己的設(shè)備上運(yùn)行未簽名的安卓映像,尤其是希望獲得Tethered的root權(quán)限的時(shí)候。通過(guò)使用Magisk引導(dǎo)未簽名的映像,人們可以隨意訪問(wèn)其設(shè)備上的全部數(shù)據(jù),包括他們的照片、信息和聯(lián)系人,而不需要備份、刪除和恢復(fù)這些數(shù)據(jù)。此外,這將允許研究人員以root權(quán)限對(duì)其個(gè)人設(shè)備進(jìn)行安全研究,然后,通過(guò)重啟移除權(quán)限,再引導(dǎo)至已簽名的映像。這種做法的好處在于,幾乎沒(méi)有證據(jù)表明他們獲得了訪問(wèn)該設(shè)備的特權(quán)。
這不僅對(duì)研究而言很有用,同時(shí),攻擊者也可以利用這一點(diǎn)來(lái)發(fā)動(dòng)攻擊。例如,通過(guò)這個(gè)漏洞和一個(gè)自定義的映像,攻擊者就可以訪問(wèn)用戶的所有文件,或只是禁用鎖屏就能訪問(wèn)用戶的應(yīng)用程序。具有物理訪問(wèn)權(quán)限的攻擊者也可以獲得與用戶獲得的綁定型root訪問(wèn)權(quán)限(tethered root access)相同的訪問(wèn)權(quán)限。
最后,安卓允許用戶通過(guò)開(kāi)發(fā)者選項(xiàng)菜單進(jìn)一步對(duì)手機(jī)進(jìn)行加密。這就增加了一個(gè)額外的保護(hù)層,要求在引導(dǎo)時(shí)輸入PIN碼或密碼,以便解密用戶數(shù)據(jù)分區(qū)。這與設(shè)備的解鎖屏幕不同,后者只在軟件層面保護(hù)設(shè)備。
雖然這這種方法確實(shí)能夠保護(hù)用戶數(shù)據(jù),但它無(wú)法保護(hù)核心的安卓引導(dǎo)映像,一個(gè)獲得臨時(shí)物理訪問(wèn)某人的手機(jī)的攻擊者可以很容易地上傳一個(gè)后門,一旦用戶輸入了他們的密碼,這個(gè)后門就會(huì)被激活。雖然這不是一種非常可行的攻擊,但的確很有趣。
小結(jié)
在引導(dǎo)加載程序中發(fā)現(xiàn)的所有漏洞都已披露給Qualcomm公司,并與進(jìn)行了協(xié)調(diào)后才給予披露。雖然這些漏洞確實(shí)使SDM660面臨風(fēng)險(xiǎn),但在打補(bǔ)丁之前,我沒(méi)有發(fā)現(xiàn)任何其他Qualcomm Snapdragon芯片是易受攻擊的。目前,所有使用該芯片的設(shè)備都已部署了補(bǔ)丁,因此,該漏洞已不復(fù)存在。
最后,該漏洞被分配的CVE編號(hào)為CVE-2021-1931。
最后
我在網(wǎng)上整理了相關(guān)的資料與工具,有需要的可以call me!!!
【資料詳細(xì)】
總結(jié)
以上是生活随笔為你收集整理的【技术分享】如何解锁高通骁龙660上的安卓引导加载程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【安全】免密登陆SQLSERVER 之
- 下一篇: 【网安干货】MySQL8新特性注入技巧