什麼是加殼(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)。