摘 要:Binder是Android系統進程間通信方式之一。Linux已經擁有管道system V IPC、socket等IPC手段,卻還要倚賴Binder來實現進程間通信,說明Binder具有無可比擬的優勢。本文通過對Binder的詳細介紹以及與其他IPC通信方式的調用,使大家對Binder的優勢和使用Binder作為Android主要IPC方式的原因有所了解。
關鍵詞:Android system_server binder
本文內容包含使用在擁有root權限的Android2.3平臺上針對system_server中binder通信的攔截。
一、動態鏈接機制及Binder攔截選址
要攔截模塊甲對乙的調用,一般思路是通過ptrace遠程注入并加載一新攔截模塊至模塊甲,并搜索模塊甲的GOT表,找到對模塊乙的調用地址,改成新模塊內的某函數地址,然后新模塊內的這個函數在進行了自己的處理后,再跳到模塊乙中。
這里用戶進程空間所加載的libbinder.so和system_server端加載的libbinder.so在邏輯上不是同一個東西。正因為不是同一個東西,我們才能針對system_server進程中加載的libbinder.so動手,攔截其GOT表中對ioctl的調用,從而提前知道Service要返回的內容。這個ioctl就是攔截的選址所在。
二、具體實現
在這個常駐system_server進程內的共享庫里,只實現了簡單幾個函數,其中do_hook函數在注入后通過外界調用,它不做具體的hook動作,僅僅只是把所需的兩個函數地址寫入Android的Property供外界使用:
[cpp] view plaincopy01.//將新舊ioctl地址寫入Andorid的Property供外界使用;
02.int do_hook(void * param)
03.{
04.old_ioctl = ioctl;
05.printf(\"Ioctl addr: %p. New addr %p\n\", ioctl, new_ioctl);
06.
07.char value[PROPERTY_VALUE_MAX] = {'\0'};
08.snprintf(value, PROPERTY_VALUE_MAX, \"%u\", ioctl);
09.property_set(PROP_OLD_IOCTL_ADDR, value);
10.
11.snprintf(value, PROPERTY_VALUE_MAX, \"%u\", new_ioctl);
12.property_set(PROP_NEW_IOCTL_ADDR, value);
13.
14.return 0;
15.}
16.
17.//全局變量用以保存舊的ioctl地址,其實也可直接使用ioctl;
18.int (*old_ioctl) (int __fd,unsigned long int __request, void * arg) = 0;
19.int res = (*old_ioctl)(__fd,__request, arg);
20.return res;
21.}.
三、小結
第一,每個被加載的模塊,無論是可執行程序還是共享庫,均有自己獨立的PLT和GOT表。所以攔截這個模塊的對外調用的GOT,不影響其他模塊。
第二,本文只實現了攔截模塊的調出到其他模塊的動作,其他模塊的調入沒有涉及到。
第三,system_server是system用戶,不是有權限寫所有名字的Property,這里用了persist.sys.開頭的屬性名,而persist.sys.開頭的屬性會保存至磁盤,因此性能會差一些。
第四,如果不以root身份運行注入程序,則ptrace附加時會失敗。
第五,Andriod系統的大部分Service都運行在system_server進程中,可以攔截到。但部分自定義的用戶Service在用戶進程中,如需要攔截,則要ptrace到那個用戶進程才行,攔截方法也類似。
以上是筆者關于Android下binder的調用與攔截的一些思路與實現方法。Android自身由于具有集成性、控制性、交互性等特點,所以可以激發學生的學習興趣、調動學生的積極參與、擴大學生知識面,為學生提供多種學習的路徑。