日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

农民斗地主——Binder fuzz安全研究

發(fā)布時間:2025/3/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 农民斗地主——Binder fuzz安全研究 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

扣吧力作,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明來自colbert337.github.io

最近扣吧忙成狗了,好久沒更新博客,對不住大家了,今天趁天氣暖和點(diǎn),來一篇干貨。

由于好久沒搞Android了,寫得不專業(yè)的地方,請見諒哈。

0.為什么要研究Binder fuzz

以目前最熱門的指紋方案為例。

TZ:Trustzone(請自行百度)
CA:Trustzone框架中的Clinet App
TA:Trustzone框架中的Trustzone APP

上層APP通過Binder機(jī)制調(diào)用keystore和FingerprintService兩個底層系統(tǒng)服務(wù),來獲取密鑰存儲和指紋的能力。底層服務(wù)再通過CA跟TZ驅(qū)動通信,調(diào)用TZ中TA提供的服務(wù),如指紋識別等安全性要求較高的服務(wù)。

我們今天只看Android側(cè)的Binder體系。

Binder其實(shí)是提供了一種進(jìn)程間通信(IPC)的功能。這些系統(tǒng)服務(wù),通過binder協(xié)議抽象出一個個的“接口”,供其他進(jìn)程調(diào)用,是一個重要的潛在的攻擊面。如果沒有做好權(quán)限控制,會讓低權(quán)限的第三方應(yīng)用/病毒/木馬利用,后果不堪設(shè)想。

其次,做Android的同學(xué)都知道,Binder是android一個非常重要的機(jī)制,夸張一點(diǎn)可以說是“Android的靈魂”,非常有必要進(jìn)行細(xì)致的分析和漏洞挖掘。

插播一個扣吧總結(jié)的知識點(diǎn),系統(tǒng)服務(wù)的分類

1.Binder體系的java服務(wù)(有Stub接口,也就是AIDL封裝)
2.Binder體系的Native服務(wù)
3.socket體系的init服務(wù)(通常見于init.rc)
4.其他服務(wù)

OK,再談?wù)劄槭裁词褂胒uzz技術(shù)呢?

總的來說,是因?yàn)閒uzz在協(xié)議和接口安全測試中比較簡單粗暴,試錯成本低。所以,“不管什么接口,先fuzz一把看看”。

Fuzzing是一種基于缺陷注入的自動軟件測試技術(shù)。通過編寫fuzzer工具向目標(biāo)程序提供某種形式的輸入并觀察其響應(yīng)來發(fā)現(xiàn)問題,這種輸入可以是完全隨機(jī)的或精心構(gòu)造的。Fuzzing測試通常以大小相關(guān)的部分、字符串、標(biāo)志字符串開始或結(jié)束的二進(jìn)制塊等為重點(diǎn),使用邊界值附近的值對目標(biāo)進(jìn)行測試。

主要有兩種類型的fuzzing技術(shù) :

1)dumb fuzzing 這種測試無需了解協(xié)議或文件本身格式,通過提供完全隨機(jī)的輸入或簡單改變某些字節(jié)去發(fā)現(xiàn)問題。這種方法實(shí)現(xiàn)起來較簡單,容易快速觸發(fā)錯誤,但它的完全隨機(jī)性會導(dǎo)致產(chǎn)生大量無效的輸入或格式。

2)Intelligent fuzzing 研究目標(biāo)應(yīng)用程序的協(xié)議或文件格式、功能配置,了解各類漏洞的成因,有目的地編寫fuzzer。編寫有效的fuzzer需要花費(fèi)時間,但能夠?qū)δ承└信d趣的部分集中測試,因此更有效。

1.什么是Binder(有基礎(chǔ)的可以略過這一部分)

Android系統(tǒng)采用Binder機(jī)制作為進(jìn)程間通信機(jī)制,類似于COM和CORBA分布式組件架構(gòu),通俗來講其實(shí)就是提供遠(yuǎn)程過程調(diào)用(RPC)功能。

在Binder機(jī)制中,由Client、Server、ServiceManger、Binder驅(qū)動這四個部分組成,其中Client、Server、ServiceManager運(yùn)行在用戶空間,Binder驅(qū)動運(yùn)行在內(nèi)核空間。Binder就是把這四個組件粘合在一起的粘合劑,核心組件是Binder驅(qū)動,ServiceManager提供了輔助管理的功能。Client和Server正是在Binder驅(qū)動和ServiceManager提供的基礎(chǔ)設(shè)施上,進(jìn)行CS通信。

下面這個流程圖可以簡單說明Client通過binder調(diào)用Server的一個過程,Client會通過Proxy(這里的Proxy不是單一實(shí)體,實(shí)際上是一系列的BpInterface、BpBinder等代理組件)去跟binder驅(qū)動通信,Proxy把數(shù)據(jù)打包成parcel類型數(shù)據(jù)再進(jìn)行傳輸。

那么數(shù)據(jù)具體是怎么傳輸?shù)哪?#xff1f;

我們繼續(xù)深究一下,筆者總結(jié)了一個比較全的圖。Java層服務(wù)其實(shí)也是在Native層服務(wù)BpBinder和BBinder的一個封裝。如果屏蔽底層驅(qū)動來看,整個Binder代理的核心就是BpBinder和BBinder。

其中,BpBinder最重要的職責(zé)就是實(shí)現(xiàn)跨進(jìn)程傳輸?shù)膫鬏敊C(jī)制,至于具體傳輸?shù)氖鞘裁凑Z義,它并不關(guān)心。我們觀察它的transact()函數(shù)的參數(shù),可以看到所有的語義都被打包成Parcel類型數(shù)據(jù)。(Parcel是輕量級的高效的對象序列化和反序列化機(jī)制,Android在Java空間和C++都實(shí)現(xiàn)了Parcel,由于它在C/C++中,直接使用了內(nèi)存來讀取數(shù)據(jù),因此,它更有效率)

請記住這個偉大的函數(shù)——transact()

舉一個例子:上層APP調(diào)用MediaRecorder對外提供的API,名字叫setCamera,實(shí)際上是執(zhí)行了BpMediaRecorder中的setCamera方法中,remote()返回的就是BpBinder對象,這里會組裝好parcel數(shù)據(jù)包,會傳給BpBinder的transact函數(shù)。transact函數(shù)就會把數(shù)據(jù)發(fā)給對端,也就是另一個BBinder對象。

我們看一下具體是如何發(fā)送數(shù)據(jù)?

BpBinder的transact函數(shù),通過層層調(diào)用,最終通過ioctl和binder驅(qū)動通信

嗯,上述的就是發(fā)送請求的過程。

下面來看接收方,Binder遠(yuǎn)程通信的目標(biāo)端實(shí)體必須繼承于BBinder類,該類和BpBinder相對,主要關(guān)心的只是傳輸方面的東西,不太關(guān)心所傳輸?shù)恼Z義。當(dāng)收到回復(fù)后,會執(zhí)行IPCTHreadState::waitForRespaonse函數(shù)的邏輯,并執(zhí)行executeCommand(cmd)

executeCommand中,會取得一個合法的BBinder對象,并執(zhí)行BBinder的transact函數(shù)。
(是不是有點(diǎn)奇怪,BBinder也有一個transact函數(shù),請繼續(xù)往下看吧)

BBinder::transact中會調(diào)用onTransact,這個onTransact才是真正處理業(yè)務(wù)的。需要注意的是,因?yàn)槲覀兊腷inder實(shí)體在本質(zhì)上都是繼承于BBinder的,而且我們一般都會重載onTransact()函數(shù),所以上面的onTransact()實(shí)際上調(diào)用的是具體binder實(shí)體的onTransact()成員函數(shù)。也就是說,onTransact的具體實(shí)現(xiàn)一般在上層的binder實(shí)體,而不在BBinder。

上面說了,BBinder沒有實(shí)現(xiàn)一個默認(rèn)的onTransact()成員函數(shù),所以在遠(yuǎn)程通信時,BBinder::transact()調(diào)用的onTransact()其實(shí)是Bnxxx或者BnInterface的某個子類的onTransact()成員函數(shù),舉個例子,BnMediaRecorder中實(shí)現(xiàn)了一個onTransact函數(shù),通過switch-case,根據(jù)不同code進(jìn)行分發(fā)處理。

switch(code)中的code,其實(shí)就是前面說的BpBinder中transact函數(shù)傳過來的int型的方法號。

2.Binder fuzz怎么作

經(jīng)過上面的分析,我們已經(jīng)對Binder有個全局的了解。fuzz的關(guān)鍵是選擇好fuzz的目標(biāo)和fuzz切入點(diǎn)(接口),那么應(yīng)該如何選擇呢?

思路就是農(nóng)民斗地主!

前面也說了,系統(tǒng)服務(wù)(地主)具有高權(quán)限,是我們需要重點(diǎn)關(guān)注的對象,而低權(quán)限進(jìn)程(農(nóng)民)可以利用binder call去調(diào)用系統(tǒng)服務(wù),從低權(quán)限到高權(quán)限,存在一個跨安全域的數(shù)據(jù)流,這里就是一個典型的攻擊界面。所以,我們選擇系統(tǒng)服務(wù)作為fuzz的目標(biāo)。

那么Fuzz接口呢?選擇fuzz接口需要滿足這幾個要求:

1)這個接口是開放的,是可以被低權(quán)限進(jìn)程調(diào)用的
2)這個接口距離fuzz目標(biāo)(系統(tǒng)服務(wù))比較接近,中間路徑最好透傳,這樣比較容易分析異常
3)從簡原則

根據(jù)上面的分析,BpBinder中的transact函數(shù)就是一個很好的fuzz接口,但這貨在底層無法直接調(diào)用。

怎么辦呢?

我們從BpBinder往上層找,很容易發(fā)現(xiàn),Java層IBinder的transact函數(shù)最終調(diào)用到BpBinder,且參數(shù)是原封不動的“透傳”到底層,考慮到j(luò)ava層的可視化和擴(kuò)展性,我決定選擇IBinder的公有方法transact作為fuzz接口。

下圖就是這個接口的定義:

請大家認(rèn)真看看上圖注釋的說明:

code是int類型,指定了服務(wù)方法號
data是parcel類型,是發(fā)送的數(shù)據(jù),滿足binder協(xié)議規(guī)則,下面會有詳述
reply也是parcel類型,是通信結(jié)束后返回的數(shù)據(jù)
flag是標(biāo)記位,0為普通RPC,需要等待,調(diào)用發(fā)起后處于阻塞狀態(tài)直到接收到返回,1為one-way RPC,表示“不需要等待回復(fù)的”事務(wù),一般為無返回值的單向調(diào)用。

下面開始講重點(diǎn)了,額。

接口不是你想fuzz就能fuzz。我們來解決幾個關(guān)鍵問題:

1)如何取得服務(wù)的IBinder對象?

我們要取到對端的IBinder對象,才可以調(diào)用這個服務(wù)。系統(tǒng)其實(shí)有一些隱藏API可以利用。先通過反射出ServiceManager(hide屬性)中的listServices獲取所有運(yùn)行的服務(wù)名稱:

獲取到String類型的服務(wù)名稱后,再反射getService獲取對應(yīng)的服務(wù)IBinder對象:

是不是很犀利,其實(shí)是借用了上文說的ServiceManager的強(qiáng)大力量。

2)code如何生成?

code也稱為TransactionID,標(biāo)定了服務(wù)端方法號。

每個服務(wù)對外定義的方法都會分配方法號,而且是有規(guī)律的,第一個服務(wù)方法code使用1,第二個是2,,第三個使用3,依次類推,如果有N個方法,就分別分配1-N個連續(xù)的服務(wù)號。

有個小技巧,對于Java服務(wù),必定有Stub類,可以通過反射出mInterfaceToken+”$Stub”類中所有成員屬性,其中以”TRANSACTION_”開頭的int型就是該方法對應(yīng)的。

如下圖的例子,服務(wù)端greet方法對應(yīng)的code就是TRANSACTION_greet:

如果是Native服務(wù),就比較悲劇了,目前還沒有好的自動化方法直接獲取code。一般服務(wù)方法數(shù)不會太多,所以確定一個上限如50,從1到50循環(huán)生成code就可以把所有方法遍歷。當(dāng)然可以通過人工逆向分析出code,但這樣成本比較高。

3)data如何構(gòu)造?

通過大量的源碼review和分析得知,data由“RPC header+參數(shù)1+參數(shù)2+….”來構(gòu)成的。

舉個例子,如下圖,setDataSource這個API,首先調(diào)用data.writeInterfaceToken會寫入一個RPC header,然后會依次寫入調(diào)用方法的參數(shù),比如setdataSource有3個參數(shù),這里就會依次寫入三個數(shù)據(jù):

是不是很有規(guī)律!!

通過review writeInterfaceToken的實(shí)現(xiàn),我們可以發(fā)現(xiàn)這個RPC header是由一個int型數(shù)據(jù)加上String類型的interface name來構(gòu)成。

但我們不需要自己去構(gòu)造RPC header,直接調(diào)用writeInterfaceToken函數(shù),傳入interface name就可以了。最后抽象出來的parcel類型的data應(yīng)該是這樣的:

那大家可能會問interface name是什么東西,如何獲取?很簡單,interface name是接口名稱,只要取得IBinder對象,就可以直接getInterfaceDescriptor來獲取interface name,也就是接口方法的描述符。

再看如何獲取一個方法的參數(shù)和類型呢?

對于Java層服務(wù)的方法,可以通過反射獲取method對象,然后用getParameterTypes獲取所有的類型:

對于native層服務(wù),無法直接獲取方法參數(shù)類型,可以用過review調(diào)用者實(shí)現(xiàn)和反編譯分析等方法來作。

4)fuzz系統(tǒng)和邏輯怎么設(shè)計(jì)?

直接上圖吧。如下圖,整個fuzz系統(tǒng)分為4個模塊,分別是數(shù)據(jù)產(chǎn)生器,fuzz引擎,監(jiān)視器和日志模塊。

1)數(shù)據(jù)產(chǎn)生器就是用上述方法產(chǎn)生transact需要用到的數(shù)據(jù)

2)fuzz引擎用于執(zhí)行具體的transact過程

3)監(jiān)視器用于監(jiān)控fuzz結(jié)果和異常

4)日志模塊用于記錄fuzz結(jié)果

這里筆者采用了3種fuzz方法

1)dumb fuzz:構(gòu)造好RPC header后,直接塞入大量隨機(jī)數(shù)據(jù),code范圍為1-100,比較暴力。

2)intelligent fuzz:構(gòu)造好RPC header后,精準(zhǔn)識別出code,并根據(jù)不同的code構(gòu)造出類型正確的隨機(jī)參數(shù)

3)simple fuzz:構(gòu)造好RPC header后,精準(zhǔn)識別出code,但每次請求只寫入int類型“0”,通過返回值,快速識別fuzz目標(biāo)的接口是否有權(quán)限校驗(yàn)

5)如何判斷fuzz結(jié)果和識別安全漏洞?

一般來說,要做到“權(quán)限判斷+數(shù)據(jù)有效性判斷”兩層防護(hù)才是安全的。

通過監(jiān)控transact的返回值和系統(tǒng)log和系統(tǒng)狀態(tài),可以看到的fuzz現(xiàn)象主要有以下幾種:

1)有SecurityException,則說明該接口有進(jìn)行權(quán)限判斷,做了一層防護(hù)

2)無Exception,說明該接口沒有進(jìn)行權(quán)限校驗(yàn),默認(rèn)對外暴露,是不安全的,可以深挖

3)異?,F(xiàn)象,如系統(tǒng)重啟、指紋服務(wù)掛死、屏幕無響應(yīng)等,說明該接口不僅沒有進(jìn)行權(quán)限判斷,而且fuzz數(shù)據(jù)導(dǎo)致了緩存區(qū)溢出/進(jìn)程crash等異常,這類現(xiàn)象要再去進(jìn)行人工分析,很有可能會嚴(yán)重的提權(quán)漏洞(比如root)

舉個例子,看看到底是哪里出現(xiàn)安全漏洞。下圖,ontransact函數(shù)中switch-case結(jié)構(gòu)里,其中一個case中沒有對數(shù)據(jù)進(jìn)行判斷就讀到*device_address,而這個指針直接當(dāng)成參數(shù)直接使用,當(dāng)指針地址異常就會引起系統(tǒng)服務(wù)進(jìn)程crash,從而導(dǎo)致系統(tǒng)重啟,是一個典型的拒絕服務(wù)漏洞。也就是說,任意一個低權(quán)限的進(jìn)程可以隨時進(jìn)行攻擊,導(dǎo)致系統(tǒng)重啟。

再舉個例子,假設(shè)某手機(jī)廠家的系統(tǒng)指紋服務(wù)有個接口叫DeleteFingerPrint(),用于刪除用戶指紋,該服務(wù)的實(shí)現(xiàn)沒有進(jìn)行權(quán)限判斷和參數(shù)校驗(yàn),惡意攻擊者就有可能構(gòu)造參數(shù),非法調(diào)用該服務(wù)的方法,把用戶的指紋信息刪除。

重要的事情要說三遍!

參數(shù)要做檢查

參數(shù)要做檢查

參數(shù)要做檢查

今天先寫到這里,寫得有點(diǎn)亂,后續(xù)再更新一下。如果你喜歡扣吧的文章,請多多留言支持~

原文地址:?http://colbert337.github.io/2016/01/25/binder-fuzz/

總結(jié)

以上是生活随笔為你收集整理的农民斗地主——Binder fuzz安全研究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。