2020年1月2日 星期四

Android 動態解殼研究(一) - Dex檔案格式探討

隨者科技的演變,Android平台上的惡意程式也越來越進步了,為了防止資安研究員分析它的行為,會將Dex(Dalvik Executable)檔案加殼(Packer),這樣想要知道它運作了那些行為,在靜態分析會非常之困難,因此這次我們聚焦在如何快速的動態解殼。

什麼是加殼(Packer) ?


為了防止資安研究員或者駭客反編譯回原始的程式碼,因此會將原先的Dex檔案加密,等到運行後才會在解密回來。

如果Dex檔案沒有加殼,可以透過Jadx直接將程式碼反編譯成原來的程式碼,這樣程式的行為就一覽無遺。



一、Dex檔案格式

在動態解殼之前,我們必須知道Dex檔案格式的架構,才能在運行時,將這些資料從記憶體上提取出來。

1. header:主要是識別Dex格式、cheacksum和sha1。

2. string_ids:指向字串資料的指引。

3. type_ids:指向成員型態對應的指引。

4. proto_ids:指向方法型態對應的指引。

5. field_ids:指向成員結構的指引。

6. method_ids:指向方法結構的指引。

7. class_ids:指向類別結構的指引。

8. data:透過上述的指引可以從data裡獲取想要的結構資訊。



可能有些同學在看Dex格式可能會有些模糊,還是不知道裡面的資料是什麼東西,那我們再透過Android的Java程式碼,來說明它的資料。

1. class:存放class的結構資訊。

2. type:存放成員名稱的對應資訊。

3. field:存放成員的結構資訊。

4. method:存放方法的結構資訊

5. proto:存放方法的傳入和回傳值型態的對應資訊。



二、Dex資料探討

header主要會存放Dex的識別訊息(dex_magic)和ids、data的起始位址的偏移,這樣就能透過偏移來獲取各個class、method、field等等的資料。



從範例可以看到string_ids會儲存字串的指引,透過指引可以獲取在data裡面的字串訊息(Current loader is stopped; replacing),不過裡面的字串訊息有使用LEB128編碼,需要解碼才能獲取它原本的字串。



從type的內容可以知道什麼型態對應成什麼訊息,像是float對應到F字元、int對應到I字元。



在proto可以獲取方法的傳入和輸出的宣告型態的對應訊息,如果此方法的傳入和輸出參數是String型態,裡面的資料就會是[Ljava/lang/String;。



在field可以獲取成員的結構,從範例可以知道在android.app.Notification的class有宣告int icon的成員。



在method可以獲取方法的結構,從範例可以看到此方法對應到的class (android.accessibilityservice.AccessibilityServiceInfo)、proto (boolean())和方法名稱(getCanRetrieveWindowContent)。



Class結構是最複雜的,它包含了類別名稱、方法結構、成員結構等等大多數的資訊。



最後補充Map Item的結構,它裡面的資訊有些跟header是重複的,不過特別的是它有存放程式碼的偏移資訊(TYPE_CODE_ITEM)。