頻道欄目
首頁 > 資訊 > 系統安全 > 正文

Android操作系統安全

12-04-09        來源:[db:作者]  
收藏   我要投稿

作者:苗甦

 

        Android在迅猛發展的同時,其安全問題一直沒有引起足夠的重視,但在2010年6月研究人員發布Android平臺的KernelRootkit以來,Android平臺的安全問題引來了越來越多的關注,而同時,Android平臺的惡意軟件也開始流行起來。[3]

       根據以上的Android系統架構分析,可以發現在三個層面可能存在惡意軟件。分別是處于最高位置的應用層(Applications),函數庫層(Libraries)之上,還有Android的Linux內核中。根據編程語言的不同,也可以叫做Java層,NativeC層,Linux Kernel層[4]。

 

Native C層安全

       雖然Android平臺的軟件要用Java開發,但是也并非全部如此。Android底層必定是一個Linux [11],在Linux內核之上又有大量的標準C函數庫,在理論上,是可以編譯出可以直接依靠這些函數庫運行的C語言程序的。事實上,在Android系統自身中已經存在很多這樣的程序,在Android的超級終端中,我們可以像在Linux的超級終端中一樣調用一些常用的命令,比如ls,ps,cd,free,等等,這樣的命令在Android中有幾十個。其實這些命令都存在于“/system/bin”或“/system/xbin”下,而且都是C語言編寫的程序。

早在Android NDK發布以前,研究人員就已經可以利用Android的源碼中的資源(.h文件等)和Linux下的編譯工具(gcc,交叉編譯器等)編譯C語言程序,并且可以像執行這些命令一樣執行這些程序,我們可以稱之為Native C。

       AndroidNDK的發布,使得Native C程序的開發更加方便。AndroidNDK于

2009年7月發布第一個版本(Release1),目前已經發布到第五個版本(Release5)。

Android NDK使得普通的應用程序(.apk)中可以使用庫文件(.so),這些庫文件用C語言編寫,并且在Java語言的代碼中,可以通過JNI調用C語言代碼。在這些C語言代碼中,可以調用一些運行時函數(printf,memcpy等等),以及一些Linux中存在的函數(ptrace,waite等等),甚至是一些Android的核心API。再加之C語言對內存有絕對的控制權限,使得一些安全技術可以在這里大展拳腳,尤其是HOOK技術,這對惡意軟件還是安全軟件來說,都是一件好事。Android NDK的發布不僅有利于安全編程,對于其他領域的軟件,尤其是需要較高效率計算,不適宜在較高層的Java語言編寫的軟件,比如擁有自己核心的瀏覽器(火狐,Opera等)和大型游戲,NativeC都給他們帶來的好消息。

       在2011年三月,一個叫LBE的團隊發布了一款基于主動防御的隱私安全軟件,LBE隱私衛士。這是第一款正式發布的Android平臺的主動防御安全軟件。LBE小組曾經將Android的移植到魅族M8(原來運行Mymobile)上,其核心成員常年致力于ARM平臺Linux的研究,有很扎實的Linux功底。這款LBE隱私衛士就是用Android NDK開發的,其中用到了APIHOOK技術。

       關于HOOK技術:HOOK技術無論對于安全軟件還是惡意軟件都是十分關鍵的一項技術,其本質就是劫持函數調用(在Windows中,HOOK也可以理解為窗口消息劫持),不管是Windows 還是Linux平添,HOOK在安全軟件中的應用都十分廣泛。

       NativeC層面的程序雖然是C語言,但是依然處于Android用戶態,即Linux的用戶態。因此NativeC層上只能對某一進程(當然也可以是所有進程)進行API HOOK。不管是Windows還是Linux,其用戶態的每個進程都擁有獨立的進程空間,要對其進行API HOOK必須進入其進程空間才能修改這個進程的代碼,即必須有能力修改目標進程的內存。對于這一方面Windows和Linux采用了不同的方法。Windows沒有API可以修改某一進程的內存,因此一般采用Dll注入(或稱遠程線程注入)的方法。而Linux則常用ptrace與plt實現API HOOK。

在Windows中,APIHOOK的一般流程為:

①    OpenProcess,打開目標進程。

②    獲取LoadLibrary的函數地址,該函數地址一般在每個進程空間內都是相同的。

③    VirtualAllocEx,在打開的進程中申請內存。

④    WriteProcessMemory,在申請的內存中寫入要注入的Dll路徑字符串(此處也可以直接寫入需要的代碼,然后CreateRemoteThread執行來進行HOOK,此方法更加隱蔽,但更加復雜困難)。

⑤    CreateRemoteThread,啟動遠程線程,入口地址為LoadLibrary的函數地址,參數為要注入的Dll路徑字符串(也就是遠程申請的內存地址)。

⑥    注入的Dll中代碼會在自身被加載時開始運行。

⑦    找到要HOOK的API所在的函數庫基址。

⑧    找到要HOOK的API再其函數庫中的導出表所在位置。

⑨    修改導出表,指向自己的函數入口地址。

⑩    在自己的函數中調用原API。

       當然在注入成功后也可以直接修改API的開頭幾個字節,jmp到自己的函數,然后再jmp回去,這種方法稱為InLineHOOK,InLine HOOK更不容易被檢測到,但是穩定性,通用性都較差,而且操作更加復雜。

       在Linux中,APIHOOK進入目標進程空間時使用了Linux中的ptrace函數[9]。ptrace函數原本是用于調試程序用的,功能十分強大,不僅可以綁定某一進程(PTRACE_ATTACH),而且可以任意修改目標進程的內存空間(PTRACE_PEEKDATA,讀內存。PTRACE_POKEDATA,寫內存),甚至是寄存器(PTRACE_SETREGS,PTRACE_GETREGS)。其一般過程為:

①    PTRACE_ATTACH,綁定目標進程。

②    PTRACE_GETREGS,獲取目標進程寄存器狀態,并保存。

③    PTRACE_PEEKDATA與PTRACE_POKEDATA配合,保存原代碼,寫入要注入的代碼到當前運行位置。

④    PTRACE_SETREGS,恢復寄存器狀態,并繼續執行,這是注入的代碼開始在目標進程內執行,注入代碼完成HOOK,過程與Windows下相似。

⑤    在HOOK完成后,注入的代碼執行int3被ptrace捕獲,目標進程再次暫停執行。

⑥    PTRACE_GETREGS,再次保存寄存器。

⑦    PTRACE_PEEKDATA與PTRACE_POKEDATA配合還原代碼。

⑧    PTRACE_SETREGS,恢復寄存器,目標進程繼續執行。

⑨    PTRACE_DETACH,撤銷綁定目標進程。

Linux下還可以LD_PRELOAD來注入代碼[7]從而進行HOOK。

在前面提到的Native C級安全軟件LBE隱私衛士出現后我對其實現方法進行了研究,發現了類似的方法。LBE隱私衛士中有兩個用NativeC編寫的函數庫,分別為libloader.so和libservice.so。其中libloader.so負責將libservice.so注入到系統進程,libservice.so在注入后負責HOOK相關的API,從而實現對這些API的監控功能。在libloader.so的導出函數中可以看到以下三個函數:

 

 

 

其中inject_phonemgr,inject_server,inject_svcmgr三個函數分別負責將libservice.so注入到phonemgr,server,svcmgr三個系統進程中,在加載了LBE隱私衛士的Android手機中,在終端使用 cat /proc/<pid>/map(其中<pid>為三個系統進程的pid)可以在輸出中看到,三個系統進程都加載了 libservice.so。這一點證實了我的推斷。

而在libservice.so的函數導出表中,又可以看到以下函數:


 

 

目前只能通過函數名大體推斷這些函數的具體功能,可能是通過這幾個函數hook監控網絡,發短信,打電話,位置服務等等功能。

通過與LBE隱私衛士的開發團隊的交流,我了解到在其使用的注入技術,ptrace似乎并不起主要作用,而由于商業機密等原因,其團隊并不方便透露其具體實現細節,LBE團隊畢竟是Linux方面的佼佼者,我剛剛接觸Linux安全,ARM匯編代碼逆向能力更是有限,目前依然不能完全了解LBE的實現細節,也只能在簡單分析的基礎上一些猜測。

Linux Kernel 層安全

2010年8月2日,Spider Labs的安全專家在DefCon安全會議上發布了一個內核級別的Android Rootkit工具,這是Android推出以來公布的第一款Rootkit,這次演講引起的巨大的影響,該Rootkit的源碼也被收錄在本次會議的CD中,此后到2011年初,Android市場上開始出現Rootkit級的惡意軟件,而此時正式推出的安全軟件才剛剛達到Native C的級別。其實AndroidRootkit的研究并不比Native C級別的難,SpiderLabs的安全專家曾經列出一個公式:Android == Linux == 20 year old Open Source OS。在Android的Linux內核層更是如此。大量的Linux內核安全專家,以及現有的Linux Rootkit的研究成果使AndroidRootkit的出現提前了很多。

要加載內核級Rootkit,首先要將代碼放進Linux內核,在這個問題上,可以將代碼編譯為一個“可加載內核模塊”(Loadable Kernel Module,LKM),Linux內核可以動態的加載這些LKM,它與整個Linux內核擁有同樣多的權限,并通過觸發器激發這些代碼,只要這些代碼運行起來,也就意味著有能力經劫持Linux內核,即劫持關鍵的Linux系統調用[10],例如進程操作,文件操作,網絡操作等等,就可以任意對手機進行操作,完成任何功能,比如竊取短信,悄悄打電話,GPS定位,等等,所有這些行為都不會被用戶察覺,這些Rootkit可以不被內核外的任何安全軟件察覺,甚至不被內核級安全軟件所擦察覺,對用戶的隱私,甚至財產造成極大的威脅。

LKM加載進Linux內核后就要對系統調用進行HOOK,劫持這些調用,這這其中有以下幾個難點:如何獲得系統調用表(sys_call_table)的位置[5],如何在Android的源碼下進行編譯,如何調試這些代碼。

Android采用Linux 2.6版本的內核,而2.5及更高版本的Linux內核已經不再導出sys_call_table了,這就意味著extern void *system_call_table[];并不能得到系統調用表。但是依然可以在System.map中找到sys_call_table,而且這個地址是靜態的:[12]

                                                                   

 

圖1.4 獲取sys_call_table的地址

要調試Android下的Linux內核并不是一件簡單的事情,為了得到sys_call_table每個具體函數名及函數地址,可以用sys_write,sys_read,sys_open,sys_close等函數輸出。[12]

在這些工作完成后,就可以根據Android的源碼以及這些分析結果,編寫LKM,通過內核級HOOK劫持系統調用,內核級HOOK相對用戶態APIHOOK更加簡單,因為內核中并沒有進程內存空間等概念,對所有內存有直接的訪問權限,在內核級HOOK時依然可以通過修改sys_call_table或Inline HOOK兩種方式,兩種方式各有優缺點。

完成編寫并編譯后可以通過Linux下的命令工具集Busybox中的insmod來加載內核模塊:

                                                                                                                     

 

圖1.5 加載LKM

該工具集中的lsmod可以列舉出已經加載的內核模塊,但是Rootkit中可以通過劫持相關系統調用,使自身不被lsmod列舉出來,從而達到完全的隱身。[12]

       由于在root權限等方面所遇到的問題,目前Android Linux Kernel級的安全軟件尚屬空白

相關TAG標簽
上一篇:臺積電:絕大多數7nm客戶都會轉向6nm_IT新聞_博客園
下一篇:最后一頁
相關文章
圖文推薦

關于我們 | 聯系我們 | 廣告服務 | 投資合作 | 版權申明 | 在線幫助 | 網站地圖 | 作品發布 | Vip技術培訓 | 舉報中心

版權所有: 紅黑聯盟--致力于做實用的IT技術學習網站

美女MM131爽爽爽毛片