天天看點

Android安全分析挑戰:運作時篡改Dalvik位元組碼

本文章由Jack_Jia編寫,轉載請注明出處。  

文章連結:http://blog.csdn.net/jiazhijun/article/details/8833710

作者:Jack_Jia    郵箱: [email protected]

     移動網際網路已經是一種趨勢,僅2012年就有450億應用程式下載下傳量。伴随着移動網際網路的火爆,衆多攻擊者也被吸引到這個平台,移動平台惡意軟體呈現爆炸式增長态勢。與PC平台不同的是,PC平台有大量的反病毒包和惡意軟體分析工具,而新興的移動網際網路卻缺乏強大的分析工具和技術。這些工具和技術将是保持移動網際網路遠離惡意軟體和惡意應用程式的關鍵。它們一般來自于學術界和安全界的研究人員,但是它們都有一定的缺陷,并不适合所有的情況,加入安全社群可以幫助我們學習和發展android應用的分析方法。

一、介紹

      首先介紹一下移動應用程式的分析方法和背景。我們可以采用很多工具來對應用程式進行分析,Android應用程式的分析一般都是基于APK檔案,APK檔案代表了一個應用程式。

     它存儲了以下内容:

           1、程式邏輯:dex位元組碼和so本地庫。

           2、中繼資料資訊:AndroidManifest.xml檔案。

           3、資源檔案:圖像或其他類型資料。

     分析工具一般采用以下兩種應用分析方法:

          1、靜态分析:該方式收集有關應用程式的資訊,但程式代碼不執行。

          2、動态分析:該方式執行應用程式,同時收集應用運作行為。

     這兩種分析技術都各有利弊,在Android逆向分析領域,許多工具都是基于靜态分析技術,也有用于動态分析的沙箱系統,但受限于動态分析系統的互動靈活性,分析師往往在那些部分需要動态分析上沒有足夠的控制力。在逆向工程過程中,分析人員一旦确定了感興趣的應用程式部分,它們更側重于使用靜态分析工具。問題是如何找到那些部分呢?靜态分析技術的另一個主要缺點是不知道什麼被真正執行和程式上下文在某特定點的執行是否有效。當我們假定應用程式代碼在運作過程中不會改變時,分析工作将是十分容易的,我們可以通過分析apk檔案來識别程式代碼邏輯,混淆的應用程式會給分析人員帶來一定的挑戰。随着運作時篡改Dalvik位元組碼的講解,我們将暴露這些基于代碼流分析的工具的限制和問題。

     我們将在接下來的部分描述一下應用程式的基本組成部分,并指出重要的運作時元件。這将使我們更容易明白當運作crackme時發生了什麼事情。之後,我們将講述用于欺騙靜态分析工具所采用的主要技術。最後我們會進入crackme挑戰的細節。

二、應用程式執行的上下文

      應用程式的生命周期開始于zygote程序的fork方法,因為它已經預先加載了Android架構,是以應用程式不必再花時間加載這些基礎類,同時這也可以有效降低整體的記憶體開銷。在新的程序降低權限之後,它加載了apk檔案中的classes.dex檔案,該檔案包含了可被Dalvik虛拟機(DVM)解釋執行的Dalvik位元組碼,代表了應用程式邏輯。此外,應用程式還帶有可以在運作時動态加載的Native庫。因為Dalvik虛拟機和Native庫運作在同一程序中,是以它們具有相同的權限。一個典型的(縮短的)應用程式的記憶體布局如圖1所示。

Android安全分析挑戰:運作時篡改Dalvik位元組碼

圖1典型的APP記憶體布局

       我們可以看到,Android架構和共享庫及dex檔案一樣被映射到我們的程序。我們的dex檔案位元組碼被映射為隻讀。

三、篡改技術

       回到靜态分析工具的話題,如果Dalvik位元組碼在運作時不能改變的話,靜态分析工具将能很好的工作。因為我們可以直接從APK檔案中提取的出和運作時相比對的位元組碼。你可能會說這種假設是成立的,因為dex檔案映射為隻讀,是以Dalvik指令集是不能夠修改的位元組碼本身的。有限的Dalvik指令集使我們不能夠篡改程式位元組碼,但我們可以利用捆綁在APK檔案中的本地庫。本地代碼和DVM運作在相同的較低水準,如圖2:

Android安全分析挑戰:運作時篡改Dalvik位元組碼

圖2 本地代碼和DVM在同一級别的操作

      本地代碼是能夠任意操作自己程序上下文記憶體的,是以我們可以通過本地代碼覆寫已加載Dalvik位元組碼。但是classes.dex被映射為隻讀。這意味着,如果我們修改該段記憶體,核心将會殺掉我們的程序,是以在實際篡改我們的應用程式的位元組碼之前,我們必須重新映射該段記憶體為可寫。之後,我們就可以寫我們的新位元組碼到我們的應用程式。如果程式調用我們篡改過的方法,那麼将執行新的位元組碼。沒有進一步修改應用程式或DVM的必要。通過這種方法,我們發現“位元組碼在運作時不能修改”的假設也不是絕對的。隻關注classes.dex檔案的靜态分析工具沒有考慮到這種情況,這樣的工具就必須改進以應對這種情況。可以使用靜态和動态分析的組合來克服這種限制,但這樣的複雜的分析系統是不常見的。

三、示例-Crackme

     為了說明我們前面所讨論的一些問題,我們決定建立一個案例研究“challenge”的應用程式“crackme”,它使用惡意軟體使用的混淆技術進行了處理。您可以使用任何分析技術和工具,并弄清楚它是如何工作的。找到正确的密碼,輸入到上面的文本框中。點選按鈕,檢視是否得到了正确的答案。這将顯示按鈕下面的文字。

     您可以在這裡下載下傳crackme的apk檔案的副本:https://github.com/blueboxsecurity/DalvikBytecodeTampering/raw/master/delta.apk

     停止閱讀,如果你打算接受挑戰。下面是挑戰的答案 -----

     首先我們開始分析Action類,這是我們的應用程式的Activity的入口,按鈕會觸發verify()方法。在這裡,我們第一次擷取TextField中的輸入的文本,并把它轉換成一個String。這個String對象并不是java.lang.String類的一個執行個體而是我們自己的實作。在構造函數中,我們使用第二種方法改變字元串。結果将被儲存在私有的區域,和Action類的寫死在一塊。如果密碼相同,将被用于顯示在螢幕上的消息的加密。

     但是String類内所使用的改變文本方法的方法,或者更準确地說,這種方法的位元組碼,将永遠不會被執行。當應用程式啟動後,在Action的靜态類的構造函數中,這個方法的位元組碼已經被替換掉了。在這裡,我們加載本地庫'libnet.so'和執行READMEM()函數。在這個庫中,我們擷取一個指針從堆棧到我們的映射的dex檔案,并嘗試找到檔案的開頭。這可以很容易地通過正向搜尋記憶體頁,直到我們發現dex檔案的magic byte。現在我們可以從dex檔案的開頭解析頭檔案。當我們解析dex檔案時,我們可以找到的我們要篡改方法的位址。但正如前面提到的,我們首先要重新映射記憶體為可寫。這可以使用mprotect()函數實作。之後,我們就可以覆寫原來的位元組碼,并通過從本機代碼到類的初始化的傳回來完成。類初始化已經結束,Activity在Android裝置上彈出。現在,當我們按下按鈕時,我們執行的是新的位元組碼,而不是原來dex的位元組碼。

英文源址:http://bluebox.com/technical/android-security-analysis-challenge-tampering-dalvik-bytecode-during-runtime/