標籤:

以三星為例,如何對TrustZone進行逆向工程和漏洞利用(上篇)

譯文聲明本文是翻譯文章,文章原作者Daniel Komaromy,文章來源:medium.com

原文地址:https://medium.com/taszksec/unbox-your-phone-part-i-331bbf44c30c ; https://medium.com/taszksec/unbox-your-phone-part-ii-ae66e779b1d6

一、前言

本文主要講解了如何對三星的TrustZone進行逆向工程和漏洞利用,受字數所限,將會分為上下兩篇。在上篇中,主要涵蓋了關於架構的基礎知識。儘管這些基礎知識都來源於公開的信息,並沒有不為人知的內容,但它們卻分布在各種出版物上,非常零碎,所以我想將其整合成完整且連貫的內容。本篇文章部分技術細節來源於Trustonic和三星的官方文檔,部分來源於開源軟體,還有一部分來源於此前研究者所公開的研究成果。

在本系列的後面,我還對逆向工程的成果進行了總結,並詳細展現我所發現的漏洞。

二、簡介

目前,已經有很多關於TrustZone的研究。在去年以前,大家主要側重於對高通和華為產品的研究工作。此前這些關於可信執行環境(TEE)的研究都有一個共同的主題,就是其單點失效的特點(Single-point-of-failure Nature)。在這些可信執行環境中,普遍缺乏對特權的分隔,這也就意味著某一個漏洞會直接導致整個系統的淪陷,甚至是反覆淪陷。

下面8篇漏洞詳情,就是反覆淪陷最好的證明,大家可以參考閱讀:

blackhat.com/docs/us-14 bits-please.blogspot.hu blackhat.com/docs/us-15 pacsec.jp/psj14/PSJ2014 bits-please.blogspot.hu slideshare.net/GeekPwnK microsoftrnd.co.il/Pres theroot.ninja/disclosur

然而,三星所使用的可信執行環境則有所不同。三星的環境是由Trustonic開發,Trustonic是一個專註於研究可信操作系統的公司,他們對可信執行環境解決方案的研發已經進行了15年之久。儘管在去年,Trustonic已經將他們的TEE OS更名為Kinibi,但我還是更習慣使用「T-Base」作為可信執行環境的名稱。同樣,此前Trustonic公司曾使用過MobiCore和Giesecke&Devrient這兩個名稱,儘管如今已經更名,但還是有一些地方會使用舊名稱,請各位讀者注意這一點。

最近,我在Ekoparty安全大會上就這一主題發表了演講,我的演講主要聚焦於如何對T-base微內核的逆向工程,以及T-Base的內部工作原理,並沒有側重於講解Trustlets提供的實際功能和攻擊面。這裡的Trustlets是指在可信執行環境中運行的「可信應用程序」,基本上都是安全的操作系統中的用戶空間進程。

我演講的視頻請參見: youtube.com/watch?

我演講的PPT請參見: github.com/puppykitten/

在我發表演講的時候,三星還沒有完成全部漏洞的修復工作,這也是為什麼我會將演講的重點放在逆向工程的原因之一。終於,他們已經在2018年1月的安全通告中,完成了最後一個漏洞的修復。終於,我們可以放心地討論這些漏洞,我也要感謝大家的耐心等待。

根據我的經驗,如果你發現某個架構設計得很差,那麼隨之而來的很可能就是一些重大的漏洞,特別是在嵌入式領域。

三、三星的KNOX和T-Base

由於我的研究都是基於三星的環境下完成的,那麼我要解決的第一個問題,就是可信執行環境如何與三星的KNOX安全架構結合在一起。這一點非常重要,因為在早期版本的TrustZone中,它幾乎只用於進行數字版權管理(DRM),所以從終端用戶的角度來看,對其進行攻擊的意義並不是太大。而現在,時代已經改變。

針對TrustZone技術,三星公司已經發布了非常多的文檔。其中,有兩篇文檔已經詳細說明了其所具有的功能,我在這裡就不再贅述,大家可以參考閱讀:

developer.samsung.com/t developer.samsung.com/t

可信執行環境主要有下面三種用途:

  1. 將安全敏感功能移入可信執行環境。這樣一來,即使安卓環境受到了威脅,也不會對可信執行環境產生影響。例如:KeyStore證書、數字版權管理、證書管理、可信PIN、可信UI、移動設備管理遠程認證。
  2. 可信執行環境會對安卓系統中的功能進行監管,以緩解對Trustlets的漏洞利用嘗試。例如:TIMA任意內核模塊認證繞過、基於Trustlets的Kill-Switch勒索病毒。
  3. 僅允許從可信執行環境訪問硬體設備,從而緩解針對硬體的攻擊。例如:指紋感測器、用於非接觸式支付的磁信號安全傳輸技術(MST)等。

上述的所有內容,都有一個共同的特點:每一個功能都是由一個(或多個)Trustlet實現。這就充分說明,如果要對實際功能方面進行研究,我們應該關注Trustlet。但如果我們想要了解這些Trustlet的安全性(例如:在安全內核和不安全內核之間,它們是如何相互隔離的),我們就需要深入了解T-Base。

在這裡,我想要說明的是,儘管本文中涉及一些Trustlet的實際功能,但更多是用於向大家展現這些漏洞的存在。

四、T-Base的結構

如果你想閱讀廠商關於T-Base的介紹(更側重於產品營銷目的),請參考: trustonic.com/solutions

在最一開始,我們可以輕而易舉地通過各種資料來熟知T-Base的結構——既有抽象層面的圖示,又有大量的可用信息,同時還有三星和Trustonic共同公開的源代碼可以參考。

這一切的核心,是安卓進程(應用程序)通過世界共享內存(World Shared Memory)與Trustlet通信。剩下的只有安卓、Linux內核和T-Base內核所提供的抽象層與安全邊界層。

我們從T-Base架構的一張經典圖示開始,來了解T-Base的結構。

4.1 ATF:ARM可信固件

首先,我們需要在硬體層面上,連接安全的世界(與不安全的世界。這一點是通過ARM上的SMC指令(Secure Monitor Call)來實現的,它會將執行過程從安全世界切換到不安全世界,就像是SVC將執行過程從EL0切換到EL1一樣。但是,我們並沒有真正地使用這樣的指令跳轉到一個安全世界EL1中的Handler,而是執行跳轉到所謂的監視模式(Monitor Mode,ARM的EL3)之中。就像是一個代理,其目標是將安全世界與不安全世界之間的SMC組織起來。在Trustonic中,它並不是T-Base的一部分,而是單獨實現的。關於ARM EL的更多信息,請參考:infocenter.arm.com/help

三星(包括其他使用Trustonic的廠商,例如部分使用聯發科晶元的小米手機)就在使用ATF(ARM可信固件)來實現監控模式。上述實現基本上是參考了ARM的開源文檔。此外,Quarkslab針對ATF逆向方面寫了一篇非常不錯的文章,大家可以參考閱讀:

blog.quarkslab.com/reve blog.quarkslab.com/reve

需要注意的一點是,Linux內核不僅要使用SMC調用(通過ATF)來到達T-Base,並且T-Base內核還藉助於SMC調用來實現與ATF的通信。上述內容實際上是一個黑盒問題,我們並不知道其具體原理,將會在下一篇文章中進一步學習探討。

在這裡,我要補充一句,不僅ATF會藉助SMC調用來到達T-Base,有些SMC調用也可以讓ATF實現命令。其中一部分是開源ATF代碼中包含的命令,一部分是廠商自定義的命令。但這些並不是此次研究的重點。

4.2 T-Base:微內核

在圖中的右側,就是我們的安全世界,T-Base也在安全世界中。起初,我們認為共包含三個部分:微內核、安全驅動和Trustlet。但在後續研究中,我們意識到這個假設是錯誤的。圖中的「運行管理(Runtime Management)」,實際上既不是Trustlet,也不是驅動,更不是微內核。關於這一點會在本篇文章的後面進行介紹。現在,我們假設在T-Base操作系統中,如果一件事不是由Trustlet和安全驅動來完成,那就一定是微內核完成的。

因此,在我們研究Trustlet之前,我們想首先了解如何通過微內核來實現對Trustlet的管理(例如載入)。

為了充分掌握原理,我們必須對微內核進行逆向工程。三星將T-Base固件存儲在一個不顯眼的位置——打包在sboot映像中。Gal Beniamini已經發表過一種用來提取該映像的方法,詳情請參考他博客文章中「Kinibi Revocation」一節:googleprojectzero.blogspot.hu ,在本篇文章後面,也會詳細進行介紹。

儘管我們必須進行逆向才能知道微內核實現Trustlet管理的具體方式,但我們可以通過公開的文檔了解到微內核相當多的管理介面。

T-Base將其稱為MobiCore控制協議(MCP)介面(MCI)。這是建立在SMC調用之上的,接下來我們就做具體的分析。

至此,如果你已經閱讀了Gal的文章,那麼想必就一定知道,在三星S8之前,T-Base並沒有在Trustlet載入過程中被用於回滾保護。

4.3 T-Base:SMC快速調用

如果你已經習慣了其他的可信執行環境實現,你可能會希望每個管理功能(例如:載入Trustlet、與Trustlet共享內存、打開到Trustlet的連接等)都能是另一個微內核實現的管理程序調用,可以通過將正確的參數傳遞給SMC調用來直接觸發,就像Linux中的ioctl調用一樣。

實際上,Trustonic採取了一種完全不同的方式,保證了微內核「微」的這一特點。這一實現,可以從Linux內核源代碼中詳細了解,具體請參閱drivers/gud/gud-exynos8890/MobiCoreDriver/*.c。

(附註:源代碼中,驅動程序文件夾名稱為「gud」,就是因為原來的公司名稱是「Giesecke and Devrient」。)

在Linux內核中,總共有5個SMC快速調用。其中,MC_FC_INIT用於配置隊列,MC_FC_INFO可以從T-Base中獲取版本信息等信息,MC_FC_SWAP_CPU可用於將T-Base移動到特定的CPU核心中,MC_FC_YIELD和MC_FC_NSIQ用於調度T-Base的運行。

fastcall.c源代碼如下:

/* fast call init */ union mc_fc_init {

union mc_fc_generic as_generic;

struct {

u32 cmd;

u32 base;

u32 nq_info;

u32 mcp_info;

} as_in;

struct {

u32 resp;

u32 ret;

u32 flags;

u32 rfu;

} as_out;

};

/* fast call info parameters */
union mc_fc_info {

union mc_fc_generic as_generic;

struct {

u32 cmd;

u32 ext_info_id;

u32 rfu[2];

} as_in;

struct {

u32 resp;

u32 ret;

u32 state;

u32 ext_info;

} as_out;

};

#ifdef TBASE_CORE_SWITCHER
/* fast call switch Core parameters */ union mc_fc_swich_core {

union mc_fc_generic as_generic;

struct {

u32 cmd;

u32 core_id;

u32 rfu[2];

} as_in;

struct {

u32 resp;

u32 ret;

u32 state;

u32 ext_info;

} as_out;

};

#endif

fastcall2.c源代碼如下:

int mc_fc_nsiq(void) {

union mc_fc_generic fc;

int ret;

memset(&fc, 0, sizeof(fc));

fc.as_in.cmd = MC_SMC_N_SIQ;

mc_fastcall(&fc);

ret = convert_fc_ret(fc.as_out.ret);

if (ret)

mc_dev_err("failed: %dn", ret);

return ret;

}

int
mc_fc_yield(void) {

union mc_fc_generic fc;

int ret;

memset(&fc, 0, sizeof(fc));

fc.as_in.cmd = MC_SMC_N_YIELD;

mc_fastcall(&fc);

ret = convert_fc_ret(fc.as_out.ret);

if (ret)

mc_dev_err("failed: %dn", ret);

return ret;

}

這些命令都是通過_smc()函數來執行,該函數的作用是將參數存儲在寄存器中,並生成一個SMC。所以我們知道,如果我們想根據VBAR的設置來尋找T-Base微內核的SMC處理程序,那我們應該只能找到這一簡單的實現,後面必須要對微內核中未記錄的解決方案進行逆向工程,來確定代碼實際處理MCP命令的位置所在。當然,上述過程也不是完整的,Linux內核需要在T-Base被響應時得到通知。實際上,這一點是通過中斷來實現的:內核驅動在系統上註冊一個終端,T-Base通過MC_FC_INIT命令獲知到中斷的發生。

4.4 T-Base:MobiCore控制協議

MCP是基於共享緩衝區的協議,因此SMC唯一可以做的,就是設置MCP隊列,通知T-Base隊列中有新的輸入,並安排在安全世界中運行。其中,有兩個隊列:命令隊列是不安全世界可以載入MCP命令的地方;通知隊列是不安全世界可以載入Trustlet標識符的地方,以便通知特定的Trustlet有一條命令在等待它。

MCP命令的作用在於:我們可以載入/掛起/恢復Trustlet,並且可以映射/取消映射其他共享內存到Trustlet實例的地址空間。MCP命令列表可以在Linux內核源代碼中找到,具體請參見drivers/gud/gud-exynos8890/MobiCoreDriver/mci/mcimcp.h。

/** Possible MCP Command IDs

* Command ID must be between 0 and 0x7FFFFFFF.

*/
enum cmd_id {

/** Invalid command ID */

MC_MCP_CMD_ID_INVALID = 0x00,

/** Open a session */

MC_MCP_CMD_OPEN_SESSION = 0x01,

/** Close an existing session */

MC_MCP_CMD_CLOSE_SESSION = 0x03,

/** Map WSM to session */

MC_MCP_CMD_MAP = 0x04,

/** Unmap WSM from session */

MC_MCP_CMD_UNMAP = 0x05,

/** Prepare for suspend */

MC_MCP_CMD_SUSPEND = 0x06,

/** Resume from suspension */

MC_MCP_CMD_RESUME = 0x07,

/** Get MobiCore version information */

MC_MCP_CMD_GET_MOBICORE_VERSION = 0x09,

/** Close MCP and unmap MCI */

MC_MCP_CMD_CLOSE_MCP = 0x0A,

/** Load token for device attestation */

MC_MCP_CMD_LOAD_TOKEN = 0x0B,

/** Check that TA can be loaded */

MC_MCP_CMD_CHECK_LOAD_TA = 0x0C,

/** Map multiple WSMs to session */

MC_MCP_CMD_MULTIMAP = 0x0D,

/** Unmap multiple WSMs to session */

MC_MCP_CMD_MULTIUNMAP = 0x0E,

};

儘管該功能非常簡單,但不意味著以安全的方式來實現該功能也是非常簡單的。事實上,幾乎所有的安卓可信執行環境廠商,都存在安全問題,更多詳情可以參見UCSB研究人員發表的《BOOMERANG》文章:https://www.cs.ucsb.edu/~vigna/publications/2017_NDSS_Boomerang.pdf 。從Linux內核的角度來看,這些功能是通過實現mc_user_fops操作(該操作在drivers/gud/gud-exynos8890/MobiCoreDriver/user.c中定義)的/dev/mobicore設備節點過程中暴露的。

4.5 T-Base:Trustlet和安全驅動

接下來,讓我們一起來看看Trustlet。首先要提到的是,在去年,Gal Beniamini的一篇博客文章( googleprojectzero.blogspot.hu )中對T-Base Trustlet的實現給出了非常棒的觀點,我覺得大家有必要首先閱讀一下。

更詳細的內容,請繼續閱讀本文。

根據Tim Newsham此前的研究( thenewsh.blogspot.hu/20 ),我們知道,Trustlet二進位文件可以在設備的/system/app/mcRegistry或/data/app/mcRegistry中找到,或者從三星FOTA映像中裝載了sim2img的system.img的APP目錄下找到。

我們還需要知道MobiCore載入器格式(MCLF,Truslet和安全驅動的文件格式):在內核源代碼中,請查看諸如gud/gud-exynos8890/MobiCoreDriver/mci/mcloadformat.h這樣路徑下的源文件。這是一個由Gassan Idriss編寫的IDA載入程序,可供參考:github.com/ghassani/mcl 。此外,Tim Newsham還寫了另一套工具( pastebin.com/ea7BG6cjpastebin.com/DPwcmrK2 ),用於將MCLF轉換成ELF。

在Trustlet中區分驅動非常簡單,可以根據MCLF中的版本欄位來判斷。或者還有一種更快的方法:名稱以「ffffffff00」開頭的是Trustlet,名稱以「ffffffffd0」開頭的是安全驅動。另一方面,由於這些名稱是以他們的UUID命名的,而不是一個有意義的名字,因此想要知道哪些二進位文件中隱藏了什麼功能並不容易。我們可以使用逆向工程的方式來實現這一點。

儘管其載入過程是在不安全世界中進行的解析,但MCLF格式在安卓內核源代碼中還是有意義的,但更令人驚訝的是,所謂的tlApi和drApi也在某些來源中被定義。我不知道這是否是一個錯誤的定義,並且也不是在每個發布的三星內核源代碼中都能找到該路徑,但至少我在GitHub的源代碼中發現了一個存在的樣例。

這些是Trustlet與安全驅動分別用來與T-Base微內核通信的API。其中包括與不安全世界中應用程序進行交互的功能、允許安全世界中進程(Trustlet/安全驅動)相互通信的功能,以及對通常由內核處理的功能的調用(例如映射內存地址空間)。

正如Tim Newsham和Gal Beniamini的博客文章中所述,Trustlet通過一個調用門(Call-Gate,類似於ELF的GOT,除了對所有API調用都有單個跳轉目標之外)調用這些API。也就是說,這些調用並沒有編譯成Trustlet二進位文件。由此,我們就又產生了另一個資料都未能解答的疑問——這些API實際上都在哪裡,並且是如何實現的?我們可以推測,這些API實際上會以某種方式被SVC調用包裝,並在T-Base微內核中實現系統調用處理程序。但我們並不清楚其中的細節。同樣,我們也沒有tlApi或drApi中所有調用的信息。此外,Tim的博客文章是幾年之前寫的,其中所列出的API調用列表也是不完整的。

關於安全驅動,除了這些頭文件之外,我沒有找到太多的公開資料。就目前而言,理解了安全驅動能夠訪問各種硬體就已經足夠了。此外,加密驅動會與加密引擎進行通信。安全SPI驅動一方面會通過SPI介面與指紋感測器進行通信,另一方面通過SPI介面與安全支付的嵌入式安全元件(Samsung Pay)進行通信。上述所提及內容,均在三星官方文檔( developer.samsung.com/t )中有詳細說明。

關於Trustlet和tlApi,我們可以找到一些公開信息,例如Trustonic的Jan-Erik Ekberg的演示( usmile.at/sites/default)。根據他PPT上面的一張截圖,我們可以看到:

Trustlet的基本行為非常簡單。在IPC部分(與安全驅動通信)有些複雜,但就介面的Trustlet而言,只有tlApi調用tlApi_callDriver(),其工作原理與Linux的ioctl有些相似,它將一個命令ID和一個指向命令結構的指針作為參數。這裡也是,並沒有在Linux內核源代碼中體現,但我們在GitHub上卻至少可以找到一個源代碼是使用了這樣的頭文件。

如果你已經閱讀了Jan-Erik的幻燈片,你應該已經了解到有一個名為GP(Global Platform)的標準化可信執行環境,它為不同的可信執行環境創建了一個通用的API。Trustonic支持GP標準,因此他們也有相應的API可以實現通用標準。他們所做的,就是增加了一些特性,將相應內容變成T-Base特定的API。然而比較不錯的是,三星似乎在Trustlet中使用了傳統的API,所以我們不用擔心這一點。

五、T-Base與安卓

現在,我們來研究安卓層面。這裡仍然有Trustonic編寫的代碼,他們創建了一個用戶控制項守護進程mcDriverDaemon,向用戶空間的應用程序開放介面。由於某種原因,以前版本的代碼曾經開源過,因此理解這個驅動程序的驅動就變得非常簡單。

這個守護進程通過libMcClient.so訪問內核設備節點,其命令清晰地映射到MCP命令中,請參考: github.com/Trustonic/tr

Trustonic這一設計目的在於,只有mcDriverDaemon能夠訪問設備節點,並且通過UNIX本地套接字開放介面。Trustonic將該介面命名為TLC(Trustlet連接器)。

在三星的具體場景下,這一情況更為複雜。一方面,設備節點使用DAC和MAC(SELinux)進行限制,但仍有許多特權進程可以對其進行訪問,其中有一些無需通過mcDriverDaemon即可對其進行操作。同樣,UNIX本地套接字只能由特權進程訪問。事實上,三星想要分為直接(libtlc_direct_comm.so)和代理(libtlc_proxy_comm.so)這兩種方式,但有一些進程同時使用了這兩種方式。

至此,我們的研究過程還並不完整。很顯然,三星使用這樣的配置,使得安卓系統中一些TrustZone支持的功能能夠完全在特權模式下進行,例如system_server。但還有一種功能,可以將特權進程擴展到應用程序中,完全無需許可權,或是可以通過常規的應用程序來獲取到許可權。

這是通過將Binder介面添加到各種特權進程中來實現的。安卓會藉助API來允許進程在其Binder介面上進行訪問控制,因此我們非常希望三星也能夠實現這一點。但是,我們必須要深入進行逆向工程,因為目前沒有相關文檔或相關的現有技術。

Gal曾經寫過一個otp_server代理。同樣,還有很多其他的代理。舉例來說,這個例子是針對Samsung Pay場景下實現的: blackhat.com/docs/eu-17。在我們的研究中,我專註於使用tlc_server,目前暫時還沒有嘗試過其他情況。

六、與Trustlet的通信

在對這一架構的細節進行研究的過程中,我們注意到一個明顯的漏洞。

儘管我們已經知道如何在安卓中設置WSM(TCI緩衝區)來向一個Trustlet發送命令,但是我們並不知道該命令的固定格式,也沒有找到任何用於實現常見任務的指導(或者相關的庫)。那從事實上看,每一個Trustlet都有自己的方式嗎?

儘管目前,公開資料中並沒有用於Trustlet通信的通用命令結構,但是Trustonic可能會與合作商分享開發人員指南。那對於我們來說,就只能通過逆向工程來實現了。

劇透警告:在最後,通過對Trustlet進行逆向,我發現三星Trustlet的命令看上去是使用了通用頭部格式,但實際上不一定是通用的。並且,對於Trustlet之間的命令有效載荷,它並不會擴展到任意種類的標準結構。

七、小結

接下來,讓我們回顧一下該結構的各個層級:

  1. 三星Sboot遵循ATF模型。Sboot會載入EL3固件(ATF)和操作系統運行在安全世界的EL0+EL1(T-Base)。在載入完成後,bootloader會將處理器切換成不安全世界模式,並載入應用程序,當然也會載入安卓系統。
  2. ATF會捕獲到全部世界中EL1的SMC調用,並在二者之間進行代理。
  3. Linux內核會設置用作MCP命令隊列和通知隊列的共享緩衝區,並通過快速調用(在寄存器中傳遞帶有參數的SMC指令)來初始化與T-Base微內核的通信。
  4. Linux內核使用另一個快速調用來通知(進行調度)T-Base。T-Base使用Linux內核中註冊的中斷,在處理命令完成後通知不安全世界。
  5. Linux內核實現了MCP,這些命令允許通過Trustlet實例來載入並共享內存,並通過/dev/mobicore和/dev/mobicore-user設備的ioctl介面對外開放。它包括在WSM範圍之內的完整性檢查,用於確保用戶空間無法請求可能導致不安全世界內部Linux內核損壞/內核特權提升的內存區域。(此前發現,這種健全性的檢查是不充分的。)
  6. libMcClient.so庫負責ioctl介面的用戶空間實現。
  7. 用戶空間進程通過不同的libtlc_*共享庫來實現對庫的利用。擁有足夠特權的進程,可以直接使用能夠載入libMcClient.so的變體,其他進程需要通過mcDriverDaemon來獲得訪問許可權。在這裡,通過普通的UNIX套接字暴露了MCP介面,但後面增加了健全性檢查,就可以防止客戶端進行類似於Linux內核的非法MCP行為。
  8. 套接字仍然受MAC和DAC機制的限制,因此非特權應用程序無法訪問它們。而與之相反,三星增加了各種代理進程(比如tlc_server),通過Binder進一步暴露了mcDriverDaemon介面,從而允許具有足夠許可權的應用程序通過訪問特定的Binder界面的方式來與T-Base進行交互,以及載入Trustlet並與之通信。

八、T-Base映像提取

要提取所有嵌入到Sboot映像中的T-Base固件(例如:微內核、運行時間管理器、tlLibrary、加密驅動等),需要使用字元串標記「t-base」來查找提取表:

ROM:00147000 tbase_extract_table DCB "t-base ",0 ; descriptor struct: ROM:00147000 ; char name[8] ROM:00147000 ; int offset ROM:00147000 ; int size ROM:00147000 ; char padding[0x10] ROM:00147000 ; ROM:00147000 ; real start offset: 0x132000 ROM:00147000 ; ROM:00147000 ; Mtk: 0->0x147000 -> the Microkernel image itself -> go back 0x15000 from "t-base" ROM:00147000 ; Image_h: 0x147000 -> 0x148000 -> so thats this ROM:00147000 ; Rtm: 0x148000 -> RTM is the Run-Time Manager (aka S0CB) ROM:00147000 ; ROM:00147000 ; drcrypt: 0x167000 -> MCLF file (Crypto Driver) ROM:00147000 ; tlproxy: 0x17A000 -> MCLF file (SFS Trustlet) ROM:00147000 ; sth2: 0x17B000 -> MCLF file (SFS Driver) ROM:00147000 ; mclib: 0x183000 -> tlLib (runtime library for Trustlets and Drivers) ROM:00147008 DCD 0 ROM:0014700C DCD 0x5D000 ROM:00147010 ALIGN 0x20 ROM:00147020 aMtk DCB "mtk ",0 ROM:00147028 DCD 0 ROM:0014702C DCD 0x15000 ROM:00147030 ALIGN 0x20 ROM:00147040 aImage_h DCB "image_h",0 ROM:00147048 DCD 0x15000 ROM:0014704C DCD unk_1000 ROM:00147050 ALIGN 0x20 ROM:00147060 aRtm DCB "rtm ",0 ROM:00147068 DCD 0x16000 ROM:0014706C DCD 0x1F000 ROM:00147070 ALIGN 0x20 ROM:00147080 aDrcrypt DCB "drcrypt",0 ROM:00147088 DCD 0x35000 ROM:0014708C DCD 0x13000 ROM:00147090 ALIGN 0x20 ROM:001470A0 aTlproxy DCB "tlproxy",0 ROM:001470A8 DCD 0x48000 ROM:001470AC DCD 0x1000 ROM:001470B0 DCD 0 ROM:001470B4 DCD 0 ROM:001470B8 DCD 0 ROM:001470BC DCD 0 ROM:001470C0 aSth2 DCB "sth2 ",0 ROM:001470C8 DCD 0x49000 ROM:001470CC DCD unk_8000 ROM:001470D0 ALIGN 0x20 ROM:001470E0 aMclib DCB "mclib ",0 ROM:001470E8 DCD 0x51000 ROM:001470EC DCD unk_C000 ROM:001470F0 ALIGN 0x1000 ROM:00148000 S0CB_HDR DCB "S0CB",0 ; Rtm offset points here ROM:00148005 DCB 0x10, 0, 0 ROM:00148008 DCD unk_C000 ROM:0014800C DCD dword_D000 ROM:00148010 DCD 0 ROM:00148014 DCD 0x11960 ROM:00148018 DCD 0xB295 ROM:0014801C DCD 0x3F ROM:00148020 DCD 0x6A ROM:00148024 aMccb DCB "MCCB",0 ROM:00148029 DCD 0 ROM:0014802D DCD 0

九、T-Base SMC

目前,我已經確定了以下T-Base與通過ATF調用的SMC的對應關係:

0x1:從不安全世界中進行快速調用,並通過ATF返回到不安全世界中;

0xB2000002:將VBAR值發送給ATF(因此ATF知道SMC處理程序的位置);

0xB2000003:寫入字元(用於通過ATF記錄消息);

0xB2000004:將T-Base初始化狀態發送給ATF。

ROM:00133054 tbase_smc_send_VBAR ; CODE XREF: config_tbase_and_tell_aft_the_vbar+E↑p ROM:00133054 LDR R0, =0xB2000002 ROM:00133058 MOV R1, #1 ROM:0013305C LDR R2, =0x7F00000 ; normal VBAR address ROM:00133060 SMC #0 ROM:00133064 BX LR ROM:00133064 ; End of function tbase_smc_send_VBAR ROM:00133064 ROM:00133068 ROM:00133068 ; =============== S U B R O U T I N E ======================================= ROM:00133068 ROM:00133068 ; Attributes: noreturn ROM:00133068 ROM:00133068 tbase_smc_fastcall_status_then_ret_to_nonSW ROM:00133068 ; CODE XREF: sub_1343AA:loc_1354C8↓p ROM:00133068 ; translate_MSMBase_to_VA+46↓p ROM:00133068 LDR R0, =0xB2000004 ROM:0013306C MOV R1, #1 ROM:00133070 MOV R2, #1 ROM:00133074 SMC #0 ROM:00133078 LDR R0, =0x2000001 ROM:0013307C SMC #0 ROM:00133080 ROM:00133080 loc_133080 ; CODE XREF: tbase_smc_fastcall_status_then_ret_to_nonSW:loc_133080↓j ROM:00133080 B loc_133080 ROM:00133080 ; End of function tbase_smc_fastcall_status_then_ret_to_nonSW ROM:00133080 ROM:00133084 ROM:00133084 ; =============== S U B R O U T I N E ======================================= ROM:00133084 ROM:00133084 ROM:00133084 tbase_smc_fastcall_status ; CODE XREF: sub_1343AA+31C6↓p ROM:00133084 LDR R0, =0xB2000004 ROM:00133088 MOV R1, #1 ROM:0013308C MOV R2, #3 ROM:00133090 SMC #0 ROM:00133094 BX LR ROM:00133094 ; End of function tbase_smc_fastcall_status ROM:00133094 ROM:00133098 ROM:00133098 ; =============== S U B R O U T I N E ======================================= ROM:00133098 ROM:00133098 ROM:00133098 tbase_smc_fastcall_print ROM:00133098 MOV R2, R0 ROM:0013309C LDR R0, =0xB2000003 ROM:001330A0 MOV R1, #1 ROM:001330A4 SMC #0 ROM:001330A8 BX LR ROM:001330A8 ; End of function tbase_smc_fastcall_print

(...)

十、T-Base系統調用

.tbase_mem_data:07F0D86C ; =========================================================================== .tbase_mem_data:07F0D86C .tbase_mem_data:07F0D86C ; Segment type: Pure data .tbase_mem_data:07F0D86C AREA .tbase_mem_data, DATA, ALIGN=0 .tbase_mem_data:07F0D86C ; ORG 0x7F0D86C .tbase_mem_data:07F0D86C syscall_table DCD svc_0_nop+1 ; DATA XREF: invoke_syscall_from_table+40↑o .tbase_mem_data:07F0D86C ; invoke_syscall_from_table:syscall_table_ptr↑o .tbase_mem_data:07F0D870 DCD svc_1_init_process+1 .tbase_mem_data:07F0D874 DCD svc_2_nop+1 .tbase_mem_data:07F0D878 DCD svc_3_nop+1 .tbase_mem_data:07F0D87C DCD svc_4+1 ; Did not find this invoked anywhere in {RTM,tlLib} .tbase_mem_data:07F0D880 DCD svc_5_start_process+1 .tbase_mem_data:07F0D884 DCD svc_exit+1 .tbase_mem_data:07F0D888 DCD svc_mmap+1 .tbase_mem_data:07F0D88C DCD svc_8_munmap+1 .tbase_mem_data:07F0D890 DCD svc_9_start_thread+1 .tbase_mem_data:07F0D894 DCD svc_A_stop_thread+1 .tbase_mem_data:07F0D898 DCD svc_B_return_0xD+1 .tbase_mem_data:07F0D89C DCD svc_C_modify_thread_registers+1 .tbase_mem_data:07F0D8A0 DCD svc_D_mprotect+1 .tbase_mem_data:07F0D8A4 DCD svc_E_resume_thread+1 .tbase_mem_data:07F0D8A8 DCD svc_F+1 .tbase_mem_data:07F0D8AC DCD svc_10_set_thread_prio+1 .tbase_mem_data:07F0D8B0 DCD svc_11_ipc+1 .tbase_mem_data:07F0D8B4 DCD svc_12_int_attach+1 .tbase_mem_data:07F0D8B8 DCD svc_13_int_detach+1 .tbase_mem_data:07F0D8BC DCD svc_14_sigwait+1 .tbase_mem_data:07F0D8C0 DCD svc_15_signal+1 .tbase_mem_data:07F0D8C4 DCD svc_16+1 ; Did not find this invoked anywhere in {RTM,tlLib} .tbase_mem_data:07F0D8C8 DCD svc_tbase_smc_fastcall_input+1 .tbase_mem_data:07F0D8CC DCD svc_18_log_char+1 .tbase_mem_data:07F0D8D0 DCD svc_19_get_secure_timestamp+1 .tbase_mem_data:07F0D8D4 DCD svc_1A_control+1 ; includes a lot, such as: .tbase_mem_data:07F0D8D4 ; - driver shmem map/unmap .tbase_mem_data:07F0D8D4 ; - get/set exception info .tbase_mem_data:07F0D8D4 ; - get MCP queue info .tbase_mem_data:07F0D8D4 ; - get IPCH phys address values .tbase_mem_data:07F0D8D4 ; - cache control .tbase_mem_data:07F0D8D4 ; - virt2phys, phys2virt translation .tbase_mem_data:07F0D8D4 ; - set custom fastcall, call custom fastcall .tbase_mem_data:07F0D8D4 ; .tbase_mem_data:07F0D8D4 ; Known sub-handlers: .tbase_mem_data:07F0D8D4 ; .tbase_mem_data:07F0D8D4 ; -0x8F: getting/setting fastcall configuration values .tbase_mem_data:07F0D8D4 ; - 0xC: get S0CB PA .tbase_mem_data:07F0D8D4 ; - 0xA: notify (nSW - trigger interrupt) .tbase_mem_data:07F0D8D4 ; - 0xB: notify driver (drTriggerIntr) .tbase_mem_data:07F0D8D4 ; - 0xD: get fc_init perm flags .tbase_mem_data:07F0D8D4 ; - 0x1: set exception info .tbase_mem_data:07F0D8D4 ; - 0x2: get fault info .tbase_mem_data:07F0D8D4 ; - 0x4,0x5,0x6,0x7: get MCP queue info .tbase_mem_data:07F0D8D4 ; (mci_buffer_addr, nq_length, mcp_queue_addr, mcp_queue_len) .tbase_mem_data:07F0D8D4 ; - 0x9: map mcp cmd queue (in kernel) .tbase_mem_data:07F0D8D4 ; -0x90 -> more control .tbase_mem_data:07F0D8D4 ; - 5: read info for exception .tbase_mem_data:07F0D8D4 ; - 7: translate VA to PA .tbase_mem_data:07F0D8D4 ; -0x91 virt-to-phys and also virt-to-phys64 .tbase_mem_data:07F0D8D4 ; -0x92 -> I-cache clean/invalidate, D-cache clean/invalidate .tbase_mem_data:07F0D8D4 ; -0x81:map, 0x83: unmap, 0x85:map. .tbase_mem_data:07F0D8D4 ; - Difference in 81/85: map in

十一、RTM IPC

請注意,在這裡我們稱RTM為「S0CB」,是由於其文件格式的魔術值(Magic Value)。根據Sboot固件中的提示,更加準確的一個名稱應該是RTM(Run Time Manager,運行時間管理器)。

這是T-Base中一個強大的用戶空間進程,始終最先啟動,並負責啟動和管理所有其他進程(Trustlet)。與Linux上的init類似,它負責三個功能:

  1. 實現MCP;
  2. 當請求從不安全世界到達時,通知Trustlet;
  3. 實現T-Base的IPC機制。

    其中,MCP命令都可以從公開渠道獲知。對於IPC,前12個IPC命令可以在這裡找到源代碼:searchcode.com/codesear 。在這裡,我參考了相關的命名約定,對於其餘部分,具體如下:

/** Possible message types/event types of the system. */ typedef enum {

MSG_NULL = 0, // Used for initializing state machines /***************/

MSG_RQ = 1, /**< Request; client -> server; */

MSG_RS = 2, /**< Response; server -> client */

MSG_RD = 3, /**< Ready; server -> IPCH */

MSG_NOT = 4, /**< Notification; client -> IPCH; */

MSG_CLOSE_TRUSTLET = 5, /**< Close Trustlet; MSH -> IPCH; IPCH -> all servers */

MSG_CLOSE_TRUSTLET_ACK = 6, /**< Close Trustlet Ack; servers -> IPCH */

MSG_MAP = 7, /**< Map; driver <-> IPCH; */

MSG_ERR_NOT = 8, /**< Error Notification; EXCH/SIQH -> IPCH; */

MSG_CLOSE_DRIVER = 9, /**< Close driver; MSH -> IPCH; IPCH -> driver */

MSG_CLOSE_DRIVER_ACK = 10, /**< Close driver Ack; driver -> IPCH; IPCH -> MSH */

MSG_GET_DRIVER_VERSION = 11, /**< GetDriverVersion; client <--> IPCH */

MSG_GET_DRAPI_VERSION = 12, /**< GetDrApiVersion; driver <--> IPCH */

MSG_SET_NOTIFICATION_HANDLER = 13, // Driver <-> IPCH

MSG_DRV_NOT = 15, // Driver -> Trustlet

MSG_SET_FASTCALL_HANDLER = 16, // Driver <-> IPCH

MSG_GET_CLIENT_ROOT_AND_SP_ID = 17, // Driver <-> IPCH

MSG_CALL_FASTCALL = 25, // DRIVER -> IPCH -> Kernel

MSG_GET_CLI_UUID = 26, // Driver <-> IPCH

MSG_RQ_2 = 27, // Client -> Server

MSG_MAP_VA_DIRECT = 31, // DRIVER <-> IPCH

MSG_MAP_PY_DIRECT = 32, // DRIVER <-> IPCH

MSG_UNMAP_PY_DIRECT = 33, // DRIVER <-> IPCH

MSG_GET_MEM_TYPE = 34, // DRIVER <-> IPCH

MSG_UNMAP_VA_DIRECT = 35
// DRIVER <-> IPCH

} message_t;

十二、tlApi

ROM:07D0BE38 tlApi_syscall_table DCD tlApiNOP+1 ; 0

ROM:07D0BE38
DCD tlApiGetVersion+1 ; 1

ROM:07D0BE38
DCD tlApiGetMobicoreVersion+1; 2

ROM:07D0BE38
DCD tlApiGetPlatformInfo+1; 3

ROM:07D0BE38
DCD tlApiExit+1 ; 4

ROM:07D0BE38
DCD tlApiLogvPrintf+1 ; 5

ROM:07D0BE38
DCD tlApiWaitNotification+1; 6

ROM:07D0BE38
DCD tlApiNotify+1 ; 7

ROM:07D0BE38
DCD tlApi_callDriver+1 ; 8

ROM:07D0BE38
DCD tlApiWrapObjectExt+1; 9

ROM:07D0BE38
DCD tlApiUnwrapObjectExt+1; 10

ROM:07D0BE38
DCD tlApiGetSuid+1 ; 11

ROM:07D0BE38
DCD tlApiSecSPICmd+1 ; 12

ROM:07D0BE38
DCD tlApiCrAbort+1 ; 13

ROM:07D0BE38
DCD tlApiRandomGenerateData+1; 14

ROM:07D0BE38
DCD tlApiGenerateKeyPair+1; 15

ROM:07D0BE38
DCD tlApiCipherInitWithData+1; 16

ROM:07D0BE38
DCD tlApiCipherUpdate+1 ; 17

ROM:07D0BE38
DCD tlApiCipherDoFinal+1; 18

ROM:07D0BE38
DCD tlApiSignatureInitWithData+1; 19

ROM:07D0BE38
DCD tlApiSignatureUpdate+1; 20

ROM:07D0BE38
DCD tlApiSignatureSign+1; 21

ROM:07D0BE38
DCD tlApiSignatureVerify+1; 22

ROM:07D0BE38
DCD tpiApiMessageDigestInitWithData+1; 23

ROM:07D0BE38
DCD tlApiMessageDigestUpdate+1; 24

ROM:07D0BE38
DCD tlApiMessageDigestDoFinal+1; 25

ROM:07D0BE38
DCD tlApiGetVirtMemType+1; 26

ROM:07D0BE38
DCD tlApiDeriveKey+1 ; 27

ROM:07D0BE38
DCD tlApiMalloc+1 ; 28

ROM:07D0BE38
DCD tlApiRealloc+1 ; 29

ROM:07D0BE38
DCD tlApiFree+1 ; 30

(...)

ROM:07D0BE38
DCD tlApiGetIDs+1 ; 43

(...)

ROM:07D0BE38
DCD tlApiRandomGenerateData_wrap+1; 83

ROM:07D0BE38
DCD tlApiCrash+1 ; 84

ROM:07D0BE38
DCD tlApiEndorse+1 ; 85

ROM:07D0BE38
DCD tlApiTuiGetScreenInfo+1; 86

ROM:07D0BE38
DCD tlApiTuiOpenSession+1; 87

ROM:07D0BE38
DCD tlApiTuiCloseSession+1; 88

ROM:07D0BE38
DCD tlApiTuiSetImage+1 ; 89

ROM:07D0BE38
DCD tlApiTuiGetTouchEvent+1; 90

ROM:07D0BE38
DCD tlApiTuiGetTouchEventsLoop+1; 91

ROM:07D0BE38
DCD tlApiDrmProcessContent+1; 92

ROM:07D0BE38
DCD tlApiDrmOpenSession+1; 93

ROM:07D0BE38
DCD tlApiDrmCloseSession+1; 94

ROM:07D0BE38
DCD tlApiDrmCheckLink+1 ; 95

ROM:07D0BE38
DCD tlApiDeriveKey_wrapper+1; 96

ROM:07D0BE38
DCD tlApiUnwrapObjectExt_wrapper+1; 97

ROM:07D0BE38
DCD tlApiGetSecureTimestamp+1; 98

十三、drApi

ROM:07D0C114 ; int drApi_syscall_table[62] ROM:07D0C114 drApi_syscall_table DCD drApiGetVersion+1 ; 0

ROM:07D0C114 ; DATA
XREF: get_syscall_fn+30↑o ROM:07D0C114 ; ROM:off_7D0A9F8↑o ROM:07D0C114 DCD drApiExit+1 ; 1

ROM:07D0C114
DCD drApiMapPhys+1 ; 2

ROM:07D0C114
DCD drApiUnmap+1 ; 3

ROM:07D0C114
DCD drApiMapPhysPage4KBWithHardware+1; 4

ROM:07D0C114
DCD drApiMapClient+1 ; 5

ROM:07D0C114
DCD drApiMapClientAndParams+1; 6

ROM:07D0C114
DCD drApiAddrTranslateAndCheck+1; 7

ROM:07D0C114
DCD drApiGetTaskid+1 ; 8

ROM:07D0C114
DCD drApiTaskidGetThreadid+1; 9

ROM:07D0C114
DCD drApiGetLocalThreadId+1; 10

ROM:07D0C114
DCD drApiStartThread+1 ; 11

ROM:07D0C114
DCD drApiStopThread+1 ; 12

ROM:07D0C114
DCD drApiResumeThread+1 ; 13

ROM:07D0C114
DCD drApiThreadSleep+1 ; 14

ROM:07D0C114
DCD drApiSetThreadPriority+1; 15

ROM:07D0C114
DCD drApiIntrAttach+1 ; 16

ROM:07D0C114
DCD drApiIntrDetach+1 ; 17

ROM:07D0C114
DCD drApiWaitForIntr+1 ; 18

ROM:07D0C114
DCD drApiTriggerIntr+1 ; 19

ROM:07D0C114
DCD drApiIpcWaitForMessage+1; 20

ROM:07D0C114
DCD drApiIpcCallToIPCH+1; 21

ROM:07D0C114
DCD drApiIpcSignal+1 ; 22

ROM:07D0C114
DCD drApiIpcSigWait+1 ; 23

ROM:07D0C114
DCD drApiNotify+1 ; 24

ROM:07D0C114
DCD drApiSystemCtrl+1 ; 25

ROM:07D0C114
DCD sub_7D0A2CE+1 ; 26

ROM:07D0C114
DCD drApiVirt2Phys+1 ; 27

ROM:07D0C114
DCD drApiCacheDataClean+1; 28

ROM:07D0C114
DCD drApiCacheDataCleanAndInvalidate+1; 29

ROM:07D0C114
DCD drApiNotifyClient+1 ; 30

ROM:07D0C114
DCD drApiThreadExRegs+1 ; 31

ROM:07D0C114
DCD drApiInstallFc+1 ; 32

ROM:07D0C114
DCD drApiIpcUnknownMessage+1; 33

ROM:07D0C114
DCD drApiIpcUnknownException+1; 34

ROM:07D0C114
DCD drApiGetPhysMemType+1; 35

ROM:07D0C114
DCD drApiGetClientRootAndSpId+1; 36

ROM:07D0C114
DCD drApiCacheDataCleanRange+1; 37

ROM:07D0C114
DCD drApiCacheDataCleanAndInvalidateRange+1; 38

ROM:07D0C114
DCD drApiMapPhys64+1 ; 39

ROM:07D0C114
DCD drApiMapPhys64_2+1 ; 40

ROM:07D0C114
DCD drApiVirt2Phys64+1 ; 41

ROM:07D0C114
DCD drApiGetPhysMemType64+1; 42

ROM:07D0C114
DCD drApiUpdateNotificationThread+1; 43

ROM:07D0C114
DCD drApiRestartThread+1; 44

ROM:07D0C114
DCD drApiGetSecureTimestamp+1; 45

ROM:07D0C114
DCD drApiFastCall+1 ; 46

ROM:07D0C114
DCD drApiGetClientUuid+1; 47

ROM:07D0C114
DCD sub_7D0A2AC+1 ; 48

ROM:07D0C114
DCD drApiMapVirtBuf+1 ; 49

ROM:07D0C114
DCD drApiUnmapPhys2+1 ; 50

ROM:07D0C114
DCD drApiMapPhys2+1 ; 51

ROM:07D0C114
DCD drApiUnmapVirtBuf2+1; 52

ROM:07D0C114
DCD sub_7D07D76+1 ; 53

ROM:07D0C114
DCD sub_7D0A558+1 ; 54

ROM:07D0C114
DCD sub_7D0A574+1 ; 55

ROM:07D0C114
DCD sub_7D0A5D6+1 ; 56

ROM:07D0C114
DCD sub_7D0A738+1 ; 57

ROM:07D0C114
DCD sub_7D0A1BA+1 ; 58

ROM:07D0C114
DCD sub_7D0A1C8+1 ; 59

ROM:07D0C114
DCD sub_7D0A5F4+1 ; 60

ROM:07D0C114
DCD sub_7D0A60C+1 ; 61

十四、沙盒機制

  1. 內核和RTM都會維持其自身到Trustlet或驅動的進程實例映射,並維持進程的虛擬地址空間映射。
  2. 內核會對SVC調用者的類型進行檢查,限制於驅動。RTM也會對IPC調用者的類型進行檢查,同樣限制於驅動。上述並不是一個核心機制,但必須針對每個案例正確執行。這一點,類似於Linux上的access_ok()檢查。
  3. 這二者共同防止了將其他Trustlet的虛擬內存或任何物理內存(包括不安全世界)映射到驅動的可能性。但驅動仍然不能映射RWX內存,也不能在自己的代碼頁映射任何內容。
  4. 驅動程序可以使用SVC,從內核獲取並得到發出當前請求Trustlet的UUID。這樣可以用來過濾哪些客戶端(Trustlet)應該被允許訪問驅動的功能。
  5. 驅動可以使用SVC,將不安全世界或安全世界的物理內存映射到其地址空間,也可以使用SVC來註冊自定義的快速調用處理器,使其能夠直接從安全世界的EL1執行代碼。實際上,這使得驅動擁有和安全世界EL1一樣的特權。

十五、漏洞利用緩解措施(Trustlet和驅動)

  1. 分為RX代碼頁和RW數據頁;
  2. 使棧/bss段/堆之間沒有界限;
  3. 映射到Trustlet的WSM和映射到驅動的Trustlet內存,應該存儲於獨立的內存區域中;
  4. 關閉Stack Canaries保護機制,關閉ASLR保護機制。

原文鏈接:

[1] medium.com/taszksec/unb

[2] medium.com/taszksec/unb


推薦閱讀:

如何優雅地做一個使用OS X的黑客?
青蛙旅行 — Unity3d類安卓遊戲逆向分析初探
威鋒網友寫的 360 App 逆向分析結果可信么?
CTF逆向題中的編程技巧

TAG:逆向工程 |