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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Binder fuzz安全研究

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

扣吧力作,歡迎轉載,轉載請注明來自colbert337.github.io

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

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

0.為什么要研究Binder fuzz

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

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

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

我們今天只看Android側的Binder體系。

Binder其實是提供了一種進程間通信(IPC)的功能。這些系統服務,通過binder協議抽象出一個個的“接口”,供其他進程調用,是一個重要的潛在的攻擊面。如果沒有做好權限控制,會讓低權限的第三方應用/病毒/木馬利用,后果不堪設想。

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

插播一個扣吧總結的知識點,系統服務的分類

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

OK,再談談為什么使用fuzz技術呢?

總的來說,是因為fuzz在協議和接口安全測試中比較簡單粗暴,試錯成本低。所以,“不管什么接口,先fuzz一把看看”。

Fuzzing是一種基于缺陷注入的自動軟件測試技術。通過編寫fuzzer工具向目標程序提供某種形式的輸入并觀察其響應來發現問題,這種輸入可以是完全隨機的或精心構造的。Fuzzing測試通常以大小相關的部分、字符串、標志字符串開始或結束的二進制塊等為重點,使用邊界值附近的值對目標進行測試。

主要有兩種類型的fuzzing技術 :

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

2)Intelligent fuzzing 研究目標應用程序的協議或文件格式、功能配置,了解各類漏洞的成因,有目的地編寫fuzzer。編寫有效的fuzzer需要花費時間,但能夠對某些感興趣的部分集中測試,因此更有效。

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

Android系統采用Binder機制作為進程間通信機制,類似于COM和CORBA分布式組件架構,通俗來講其實就是提供遠程過程調用(RPC)功能。

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

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

那么數據具體是怎么傳輸的呢?

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

其中,BpBinder最重要的職責就是實現跨進程傳輸的傳輸機制,至于具體傳輸的是什么語義,它并不關心。我們觀察它的transact()函數的參數,可以看到所有的語義都被打包成Parcel類型數據。(Parcel是輕量級的高效的對象序列化和反序列化機制,Android在Java空間和C++都實現了Parcel,由于它在C/C++中,直接使用了內存來讀取數據,因此,它更有效率)

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

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

我們看一下具體是如何發送數據?

BpBinder的transact函數,通過層層調用,最終通過ioctl和binder驅動通信

嗯,上述的就是發送請求的過程。

下面來看接收方,Binder遠程通信的目標端實體必須繼承于BBinder類,該類和BpBinder相對,主要關心的只是傳輸方面的東西,不太關心所傳輸的語義。當收到回復后,會執行IPCTHreadState::waitForRespaonse函數的邏輯,并執行executeCommand(cmd)

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

BBinder::transact中會調用onTransact,這個onTransact才是真正處理業務的。需要注意的是,因為我們的binder實體在本質上都是繼承于BBinder的,而且我們一般都會重載onTransact()函數,所以上面的onTransact()實際上調用的是具體binder實體的onTransact()成員函數。也就是說,onTransact的具體實現一般在上層的binder實體,而不在BBinder。

上面說了,BBinder沒有實現一個默認的onTransact()成員函數,所以在遠程通信時,BBinder::transact()調用的onTransact()其實是Bnxxx或者BnInterface的某個子類的onTransact()成員函數,舉個例子,BnMediaRecorder中實現了一個onTransact函數,通過switch-case,根據不同code進行分發處理。

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

2.Binder fuzz怎么作

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

思路就是農民斗地主!

前面也說了,系統服務(地主)具有高權限,是我們需要重點關注的對象,而低權限進程(農民)可以利用binder call去調用系統服務,從低權限到高權限,存在一個跨安全域的數據流,這里就是一個典型的攻擊界面。所以,我們選擇系統服務作為fuzz的目標。

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

1)這個接口是開放的,是可以被低權限進程調用的
2)這個接口距離fuzz目標(系統服務)比較接近,中間路徑最好透傳,這樣比較容易分析異常
3)從簡原則

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

怎么辦呢?

我們從BpBinder往上層找,很容易發現,Java層IBinder的transact函數最終調用到BpBinder,且參數是原封不動的“透傳”到底層,考慮到java層的可視化和擴展性,我決定選擇IBinder的公有方法transact作為fuzz接口。

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

請大家認真看看上圖注釋的說明:

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

下面開始講重點了,額。

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

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

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

獲取到String類型的服務名稱后,再反射getService獲取對應的服務IBinder對象:

是不是很犀利,其實是借用了上文說的ServiceManager的強大力量。

2)code如何生成?

code也稱為TransactionID,標定了服務端方法號。

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

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

如下圖的例子,服務端greet方法對應的code就是TRANSACTION_greet:

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

3)data如何構造?

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

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

是不是很有規律!!

通過review writeInterfaceToken的實現,我們可以發現這個RPC header是由一個int型數據加上String類型的interface name來構成。

但我們不需要自己去構造RPC header,直接調用writeInterfaceToken函數,傳入interface name就可以了。最后抽象出來的parcel類型的data應該是這樣的:

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

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

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

對于native層服務,無法直接獲取方法參數類型,可以用過review調用者實現和反編譯分析等方法來作。

4)fuzz系統和邏輯怎么設計?

直接上圖吧。如下圖,整個fuzz系統分為4個模塊,分別是數據產生器,fuzz引擎,監視器和日志模塊。

1)數據產生器就是用上述方法產生transact需要用到的數據

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

3)監視器用于監控fuzz結果和異常

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

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

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

2)intelligent fuzz:構造好RPC header后,精準識別出code,并根據不同的code構造出類型正確的隨機參數

3)simple fuzz:構造好RPC header后,精準識別出code,但每次請求只寫入int類型“0”,通過返回值,快速識別fuzz目標的接口是否有權限校驗

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

一般來說,要做到“權限判斷+數據有效性判斷”兩層防護才是安全的。

通過監控transact的返回值和系統log和系統狀態,可以看到的fuzz現象主要有以下幾種:

1)有SecurityException,則說明該接口有進行權限判斷,做了一層防護

2)無Exception,說明該接口沒有進行權限校驗,默認對外暴露,是不安全的,可以深挖

3)異常現象,如系統重啟、指紋服務掛死、屏幕無響應等,說明該接口不僅沒有進行權限判斷,而且fuzz數據導致了緩存區溢出/進程crash等異常,這類現象要再去進行人工分析,很有可能會嚴重的提權漏洞(比如root)

舉個例子,看看到底是哪里出現安全漏洞。下圖,ontransact函數中switch-case結構里,其中一個case中沒有對數據進行判斷就讀到*device_address,而這個指針直接當成參數直接使用,當指針地址異常就會引起系統服務進程crash,從而導致系統重啟,是一個典型的拒絕服務漏洞。也就是說,任意一個低權限的進程可以隨時進行攻擊,導致系統重啟。

再舉個例子,假設某手機廠家的系統指紋服務有個接口叫DeleteFingerPrint(),用于刪除用戶指紋,該服務的實現沒有進行權限判斷和參數校驗,惡意攻擊者就有可能構造參數,非法調用該服務的方法,把用戶的指紋信息刪除。

重要的事情要說三遍!

參數要做檢查

參數要做檢查

參數要做檢查

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


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

總結

以上是生活随笔為你收集整理的Binder fuzz安全研究的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。