DroidBox簡介

大搜車-自娛發表於2015-08-12

目前Android系統最大的問題是什麼?安全,這也是Android總是進不了企業的主要原因。如果問主要的安全問題是什麼?我想應該是吸費、流量消耗和隱私洩漏。針對於隱私洩漏的偵測,目前有一個開源軟體叫做DroidBox,算是做的不錯的了。今天我們就來分析一下DroidBox是如何偵測隱私洩漏的。

DroidBox的核心技術稱作TaintDroid,從字面上理解就是汙染機器。我們都知道標識隱私資料並不難,只要牢牢卡住相關的API呼叫就可以了,問題是如何知道這些隱私資料被洩漏出去了?惡意程式拿到隱私資料後往往會做一系列的操作,包括擷取,拼裝,加密甚至是程式間傳遞,這使得隱私資料的跟蹤變得相當困難。所以關鍵技術就演變成了:如何跟蹤資料。TaintDroid的思想就是將所有隱私資料變成汙染源,在程式執行的過程中如果你想對汙染源進行擷取,拼裝,加密,傳遞等等操作,那麼你新生成的資料也會被汙染。如果有被汙染的資料被洩漏出去,那麼就發生了隱私洩漏。好,到這裡問題變成了如何標記資料和如何進行汙染。

先說比較好搞定的問題,如何進行汙染。對於java操作(dex)的汙染規則基本上可以用下圖表示:

可以看出汙染的三大途徑:賦值,引數傳遞,返回值。目前在dex裡面無論怎麼對隱私資料操作,都會被汙染。而對於native的code, 汙染會相對複雜一些,尤其是第三方的native code,但基本的理念還是一樣的,這裡就不詳細介紹了。至於在Android裡面具體汙染的層次,可以用下面這張圖來理解:

基本上能傳播的方式都可以汙染,Dalvik之上是變數級的汙染,Native是呼叫級的汙染,儲存是檔案級的汙染,IPC還有訊息級別的汙染。

汙染跟蹤的問題解決了,另一個問題是如何標記,換句話說,就是在什麼地方儲存每塊資料是否被汙染的標記。對於不同的層次有不同的儲存方式。最容易搞定的依然是Dalvik以上的部分,系統Native庫較為難搞,最不好搞的是第三方Native庫。基本上儲存的方式可以用下面這張圖表示:

對於Dalvik以上的部分,利用修改Dalvik來搞定,因為Android裡面的java是32bit的,所以所有引用的大小也都是32bit,TaintDroid為每個引用多申請了一倍的空間,即64bit。程式自身還是用前32bit, 而TaintDroid就可以利用剩下的32bit, 採用bitmap的方式可以標註32種不同的隱私型別。這種方式帶來的副作用不言而喻,會導致程式引用佔用的記憶體增加一倍,而優點是可以精確定位到每個物件是否被汙染。
對於Native的模組就不這麼簡單了,因為無法修改指標長度(改kernel應該可以,但影響面太大了)。所以TaintDroid的汙染是基於呼叫級的,利用增加呼叫引數的方式來放汙染標記。例如上圖第三列,有一個呼叫的引數有兩個:arg0和arg1, TaintDroid再多加3個引數,第3個引數是輸出引數,呼叫完成後return值的標記就放在這裡,第4和第5個引數是輸入引數分別是arg0和arg1的汙染標記。通過這種方式,在做完一次Native呼叫後就可以得到return值的汙染標記(注意,僅僅是return值),所以這種方式被稱為面向呼叫的汙染。

應該說DroidBox最核心的東西就這麼多了,那麼TaintDroid是否就完美了呢?顯然不是的,它依然存在FP和FN。FN主要存在於Native Code的呼叫,尤其是第三方Native Code的呼叫。對於這個問題TaintDroid有個坑爹的對策:不允許呼叫第三方的動態庫。這就意味著所有呼叫第三方庫的程式都不能在TaintDroid的Image上執行。坑爹吧,因為我們知道尤其在中國很多熱門應用都要用到第三方庫的。而FP的情況也並不樂觀,FP出現問題的地方主要包括:自身設計問題和先天條件限制。我們在實際使用的過程中發現TaintDroid會吧所有的pipe操作誤認為是檔案操作,只要有隱私資料參與pipe操作,就會有FP發生。而TaintDroid對於Array的策略也是另外一個FP的來源,由於Array在Dalvik中只有一個引用,所以TaintDroid只有一個標記的位置,因而策略是寧可錯殺一千,不可放過一個。即使未來Array裡面的那個汙染源已經被移走了,Array的標記依然不會被清除。

針對於這些問題,我們team已經做了很多改動和修補,也許在未來我們會公開我們的原始碼。