APK加固之類抽取分析與修復

我是小三發表於2015-08-25

0x00 簡單介紹

  目前我己知的APK加固主要有以下兩種方式(或有其它的方式有待發現)

隱藏dex檔案:透過對目標DEX檔案進行整體加密或壓縮方式把整個dex轉換為另外一個檔案存放在assets資料夾中或者其它地方,然後利用類載入器技術進行記憶體解密並載入執行。

修改dex結構:抽取DexCode中的位元組碼指令後用零去填充,或者修改方法屬性等操作,執行時在記憶體中做修正、修復等處理工作。

0x01 APK加固前後對比

  整體來看一下原始APK包和加固後的APK包結構相關變化

         圖1

圖1所示加固後的APK包變化如下:

新增2個資料夾:

assets資料夾中增加3個檔案

data

dx

pk

lib資料夾中增加了2個so檔案

libedog.so

libfdog.so

被修改的檔案:

AndroidManifest.xml

classes.dex

0x02 殼流程分析

    我們用AndroidKiller反編譯加固後的APK, 反編譯出錯,錯誤日誌如下:

         圖2

從圖2可以看出反編譯時出現了很多錯誤,我們用IDA對DEX進行反編譯檢視程式碼,發現方法指令都被零填充了,反編譯後程式碼顯示為nop樣式,如圖3所示。

         圖3

我們再來看看APK中的AndroidManifest.xml檔案被修改了什麼地方?

         圖4

從圖4看到AndroidManifest.xml中的application新增瞭如下項做為殼的入口

android:name="com.edog.AppWrapper"該類為殼的入口,繼續分析AppWrapper都做了些什麼?

         圖5

         圖6

         圖7

從圖5-7可以看出最終會呼叫到libedog.so中的dl函式,下面就開始動態除錯分析該so的功能流程(如何動態除錯就不說了,網上己經有很多的教程了)。

 

透過動態分析libedog.so中的dl函式主要功能是: 獲得系統版本號->驗證加固前後的簽名是否一致->反除錯->將抽走的指令對映到記憶體中還原指令時用到->HOOK函式dvmResolveClass->結束

程式碼流程如下:

 1 libedog.so:5D692C18             Java_com_edog_ELibrary_d1
 2 libedog.so:5D692C18
 3 libedog.so:5D692C18             var_F0= -0xF0
 4 libedog.so:5D692C18             var_EC= -0xEC
 5 libedog.so:5D692C18             var_E4= -0xE4
 6 libedog.so:5D692C18             var_1C= -0x1C
 7 libedog.so:5D692C18             arg_0=  0
 8 libedog.so:5D692C18
 9 libedog.so:5D692C18 F0 B5       PUSH            {R4-R7,LR}
10 libedog.so:5D692C1A 28 4F       LDR             R7, =(dword_5D6A5E60 - 0x5D692C24)
11 libedog.so:5D692C1C B7 B0       SUB             SP, SP, #0xDC
12 libedog.so:5D692C1E 00 93       STR             R3, [SP,#0xF0+var_F0]
13 libedog.so:5D692C20 7F 44       ADD             R7, PC ; dword_5D6A5E60
14 libedog.so:5D692C22 3F 68       LDR             R7, [R7]
15 libedog.so:5D692C24 3C 99       LDR             R1, [SP,#0xF0+arg_0]
16 libedog.so:5D692C26 04 1C       MOVS            R4, R0
17 libedog.so:5D692C28 3B 68       LDR             R3, [R7]
18 libedog.so:5D692C2A 01 91       STR             R1, [SP,#0xF0+var_EC]
19 libedog.so:5D692C2C A9 21       MOVS            R1, #0xA9
20 libedog.so:5D692C2E 35 93       STR             R3, [SP,#0xF0+var_1C]
21 libedog.so:5D692C30 03 68       LDR             R3, [R0]
22 libedog.so:5D692C32 89 00       LSLS            R1, R1, #2
23 libedog.so:5D692C34 22 4D       LDR             R5, =(aFjFj0fjFjFj4fj - 0x5D692C42)
24 libedog.so:5D692C36 5B 58       LDR             R3, [R3,R1]
25 libedog.so:5D692C38 11 1C       MOVS            R1, R2
26 libedog.so:5D692C3A 00 22       MOVS            R2, #0
27 libedog.so:5D692C3C 98 47       BLX             R3
28 libedog.so:5D692C3E 7D 44       ADD             R5, PC                  ; "$fj] fj]0fj](fj],fj]4fj]i]"
29 libedog.so:5D692C40 2D 68       LDR             R5, [R5]                ; "$fj] fj]0fj](fj],fj]4fj]i]"
30 libedog.so:5D692C42 20 4E       LDR             R6, =(aFjFj0fjFjFj4fj+4 - 0x5D692C50)
31 libedog.so:5D692C44 28 60       STR             R0, [R5]
32 libedog.so:5D692C46 20 1C       MOVS            R0, R4
33 libedog.so:5D692C48 00 F0 5C F8 BL              _Z17ANDROID_API_LEVELP7_JNIEnv
34 libedog.so:5D692C4C 7E 44       ADD             R6, PC                  ; " fj]0fj](fj],fj]4fj]i]"
35 libedog.so:5D692C4E 36 68       LDR             R6, [R6]                ; " fj]0fj](fj],fj]4fj]i]"
36 libedog.so:5D692C50 30 60       STR             R0, [R6]
37 libedog.so:5D692C52 20 1C       MOVS            R0, R4
38 libedog.so:5D692C54 00 F0 82 F8 BL              _Z24ANDROID_PLATFORM_VERSIONP7_JNIEnv
39 libedog.so:5D692C58 20 1C       MOVS            R0, R4
40 libedog.so:5D692C5A 00 F0 A9 F8 BL              _Z22ANDROID_PLATFORM_MODELP7_JNIEnv
41 libedog.so:5D692C5E 20 1C       MOVS            R0, R4
42 libedog.so:5D692C60 00 F0 D0 F8 BL              _Z22ANDROID_PLATFORM_BRANDP7_JNIEnv
43 libedog.so:5D692C64 20 1C       MOVS            R0, R4
44 libedog.so:5D692C66 01 99       LDR             R1, [SP,#0xF0+var_EC]
45 libedog.so:5D692C68 00 F0 8A FC BL              _Z6verifyP7_JNIEnvP8_jobject ; 比較加固前後的簽名是否一致
46 libedog.so:5D692C6C 16 49       LDR             R1, =(aDataDataSLibLi - 0x5D692C76)
47 libedog.so:5D692C6E 2A 68       LDR             R2, [R5]
48 libedog.so:5D692C70 03 A8       ADD             R0, SP, #0xF0+var_E4
49 libedog.so:5D692C72 79 44       ADD             R1, PC                  ; "/data/data/%s/lib/libfdog.so"
50 libedog.so:5D692C74 FF F7 B0 EE BLX             sprintf
51 libedog.so:5D692C78 03 A8       ADD             R0, SP, #0xF0+var_E4
52 libedog.so:5D692C7A 01 1C       MOVS            R1, R0
53 libedog.so:5D692C7C 00 F0 02 FD BL              _Z4antiPKcS0_           ; 反除錯
54 libedog.so:5D692C80 00 F0 3E F9 BL              _Z10openMemoryv         ; 將抽走的指令對映到記憶體中來
55 libedog.so:5D692C80                                                     ; assets中的data檔案
56 libedog.so:5D692C84 23 68       LDR             R3, [R4]
57 libedog.so:5D692C86 A9 22 92 00 MOVS            R2, #0x2A4
58 libedog.so:5D692C8A 9B 58       LDR             R3, [R3,R2]
59 libedog.so:5D692C8C 00 99       LDR             R1, [SP,#0xF0+var_F0]
60 libedog.so:5D692C8E 20 1C       MOVS            R0, R4
61 libedog.so:5D692C90 00 22       MOVS            R2, #0
62 libedog.so:5D692C92 98 47       BLX             R3
63 libedog.so:5D692C94 0D 49       LDR             R1, =(unk_5D6A2A0D - 0x5D692C9A)
64 libedog.so:5D692C96 79 44       ADD             R1, PC
65 libedog.so:5D692C98 FF F7 A4 EE BLX             strstr
66 libedog.so:5D692C9C 00 28       CMP             R0, #0
67 libedog.so:5D692C9E 02 D1       BNE             loc_5D692CA6
68 libedog.so:5D692CA0 33 68       LDR             R3, [R6]
69 libedog.so:5D692CA2 14 2B       CMP             R3, #0x14               ; 判斷版本
70 libedog.so:5D692CA4 00 DD       BLE             loc_5D692CA8            ; 根據作業系統的版本
71 libedog.so:5D692CA4                                                     ; hook對應的dvmResolveClass函式
72 libedog.so:5D692CA6
73 libedog.so:5D692CA6             loc_5D692CA6                            ; CODE XREF: Java_com_edog_ELibrary_d1+86j
74 libedog.so:5D692CA6 01 20       MOVS            R0, #1
75 libedog.so:5D692CA8
76 libedog.so:5D692CA8             loc_5D692CA8                            ; CODE XREF: Java_com_edog_ELibrary_d1+8Cj
77 libedog.so:5D692CA8 00 F0 E8 FB BL              _Z7restorei             ; 根據作業系統的版本
78 libedog.so:5D692CA8                                                     ; hook對應的dvmResolveClass函式
79 libedog.so:5D692CAC 35 9A       LDR             R2, [SP,#0xF0+var_1C]
80 libedog.so:5D692CAE 3B 68       LDR             R3, [R7]
81 libedog.so:5D692CB0 9A 42       CMP             R2, R3
82 libedog.so:5D692CB2 01 D0       BEQ             loc_5D692CB8
83 libedog.so:5D692CB4 FF F7 9C EE BLX             sub_5D6929F0
84 libedog.so:5D692CB8             ; ---------------------------------------------------------------------------
85 libedog.so:5D692CB8
86 libedog.so:5D692CB8             loc_5D692CB8                            ; CODE XREF: Java_com_edog_ELibrary_d1+9Aj
87 libedog.so:5D692CB8 37 B0       ADD             SP, SP, #0xDC
88 libedog.so:5D692CBA F0 BD       POP             {R4-R7,PC}
89 libedog.so:5D692CBA             ; End of function Java_com_edog_ELibrary_d1
90 libedog.so:5D692CBA
91 libedog.so:5D692CBA             ; -------------------------------------

0x03 指令還原演算法分析

原始指令還原時機就是在dvmResolveClass的hook函式中對對指令進行解密還原,以下結構的中的幾個值會用到,因為被保護後的方法中的 debugInfoOff的值被修改成從0x20000000開始的一個值,該值在指令還原時起到重要作用。

1 struct DexCode {
2     u2  registersSize;
3     u2  insSize;
4     u2  outsSize;
5     u2  triesSize;
6     u4  debugInfoOff;      /* file offset to debug info stream */
7     u4  insnsSize;        /* size of the insns array, in u2 units */
8     u2  insns[1];
9 };

指令還原大致流程如下:

判斷是否為保護的類->判斷debuginfo值大於0x1FFFFFFF->將debuginfo值左移8位再右移6位->將移位後的值加上加密指令在記憶體中的開始址取4位元組做為偏移->將偏移加上加密指令在記憶體中的開始地址定位到對應方法的指令->解密指令並還原->清零debuginfo值->結束。

解密指令演算法流程如下:(每4位元組進行xor)

XorArray函式中進行解密操作->將方法debuginfo值進行crc32計算得到一個值->crc32計算得到的值與指令每4位元組進行xor->4位元組結束後再將crc32值用PolyXorKey函式生成一個新的4位元組數做為金鑰,一直迴圈到解密完成。

程式碼流程如下

  1 libedog.so:5D693144
  2 libedog.so:5D693144             _Z13restoreMethodP11ClassObjectP6Method ; CODE XREF: _Z10replaceFunP11ClassObjectjb+22p
  3 libedog.so:5D693144                                                     ; _Z10replaceFunP11ClassObjectjb+3Ap
  4 libedog.so:5D693144
  5 libedog.so:5D693144             var_34= -0x34
  6 libedog.so:5D693144             Debug_info= -0x30
  7 libedog.so:5D693144             var_2C= -0x2C
  8 libedog.so:5D693144             codeSize= -0x28
  9 libedog.so:5D693144             data= -0x24
 10 libedog.so:5D693144             codeoffset= -0x1C
 11 libedog.so:5D693144
 12 libedog.so:5D693144 F0 B5       PUSH            {R4-R7,LR}
 13 libedog.so:5D693146 89 B0       SUB             SP, SP, #0x24
 14 libedog.so:5D693148 0F 1E       SUBS            R7, R1, #0
 15 libedog.so:5D69314A 5C D0       BEQ             loc_5D693206
 16 libedog.so:5D69314C 84 69       LDR             R4, [R0,#0x18]
 17 libedog.so:5D69314E 00 2C       CMP             R4, #0
 18 libedog.so:5D693150 59 D0       BEQ             loc_5D693206
 19 libedog.so:5D693152 20 1C       MOVS            R0, R4
 20 libedog.so:5D693154 4C 21       MOVS            R1, #'L'
 21 libedog.so:5D693156 FF F7 A0 EC BLX             strchr
 22 libedog.so:5D69315A 00 28       CMP             R0, #0
 23 libedog.so:5D69315C 53 D0       BEQ             loc_5D693206
 24 libedog.so:5D69315E 3E 6A       LDR             R6, [R7,#0x20]
 25 libedog.so:5D693160 00 2E       CMP             R6, #0
 26 libedog.so:5D693162 50 D0       BEQ             loc_5D693206
 27 libedog.so:5D693164 35 1C       MOVS            R5, R6
 28 libedog.so:5D693166 10 3D       SUBS            R5, #0x10
 29 libedog.so:5D693168 AA 68       LDR             R2, [R5,#8]
 30 libedog.so:5D69316A 02 92       STR             R2, [SP,#0x38+Debug_info]
 31 libedog.so:5D69316C EB 88       LDRH            R3, [R5,#6]
 32 libedog.so:5D69316E EA 68       LDR             R2, [R5,#0xC]
 33 libedog.so:5D693170 03 93       STR             R3, [SP,#0x38+var_2C]
 34 libedog.so:5D693172 04 92       STR             R2, [SP,#0x38+codeSize]
 35 libedog.so:5D693174 25 4B       LDR             R3, =0x1FFFFFFF
 36 libedog.so:5D693176 02 9A       LDR             R2, [SP,#0x38+Debug_info]
 37 libedog.so:5D693178 9A 42       CMP             R2, R3                  ; 判斷debuginfo值大於 0x1FFFFFFF (因為被保護的方法debuginfo從0X20000000開始)
 38 libedog.so:5D69317A 44 D9       BLS             loc_5D693206
 39 libedog.so:5D69317C 24 49       LDR             R1, =(aLandroid - 0x5D693184)
 40 libedog.so:5D69317E 20 1C       MOVS            R0, R4
 41 libedog.so:5D693180 79 44       ADD             R1, PC                  ; "Landroid/"
 42 libedog.so:5D693182 FF F7 30 EC BLX             strstr                  ; 是系統的類就跳過
 43 libedog.so:5D693186 00 28       CMP             R0, #0
 44 libedog.so:5D693188 3D D1       BNE             loc_5D693206
 45 libedog.so:5D69318A 36 78       LDRB            R6, [R6]
 46 libedog.so:5D69318C 01 96       STR             R6, [SP,#0x38+var_34]
 47 libedog.so:5D69318E 00 2E       CMP             R6, #0
 48 libedog.so:5D693190 39 D1       BNE             loc_5D693206
 49 libedog.so:5D693192 20 4B       LDR             R3, =(aFjFj0fjFjFj4fj+0xC - 0x5D69319C)
 50 libedog.so:5D693194 07 A8       ADD             R0, SP, #0x38+codeoffset
 51 libedog.so:5D693196 07 96       STR             R6, [SP,#0x38+codeoffset]
 52 libedog.so:5D693198 7B 44       ADD             R3, PC                  ; "(fj],fj]4fj]i]"
 53 libedog.so:5D69319A 1B 68       LDR             R3, [R3]                ; "(fj],fj]4fj]i]"
 54 libedog.so:5D69319C 1B 68       LDR             R3, [R3]                ; data資料
 55 libedog.so:5D69319E 05 93       STR             R3, [SP,#0x38+data]
 56 libedog.so:5D6931A0 02 9B       LDR             R3, [SP,#0x38+Debug_info]
 57 libedog.so:5D6931A2 05 9A       LDR             R2, [SP,#0x38+data]
 58 libedog.so:5D6931A4 19 02       LSLS            R1, R3, #8
 59 libedog.so:5D6931A6 89 09       LSRS            R1, R1, #6
 60 libedog.so:5D6931A8 89 18       ADDS            R1, R1, R2
 61 libedog.so:5D6931AA 04 22       MOVS            R2, #4
 62 libedog.so:5D6931AC FF F7 68 EC BLX             memcpy_0
 63 libedog.so:5D6931B0 03 9A       LDR             R2, [SP,#0x38+var_2C]
 64 libedog.so:5D6931B2 04 9C       LDR             R4, [SP,#0x38+codeSize]
 65 libedog.so:5D6931B4 93 00       LSLS            R3, R2, #2
 66 libedog.so:5D6931B6 08 34       ADDS            R4, #8
 67 libedog.so:5D6931B8 E4 18       ADDS            R4, R4, R3
 68 libedog.so:5D6931BA 13 1C       MOVS            R3, R2
 69 libedog.so:5D6931BC 01 33       ADDS            R3, #1
 70 libedog.so:5D6931BE 9B 00       LSLS            R3, R3, #2
 71 libedog.so:5D6931C0 E4 18       ADDS            R4, R4, R3
 72 libedog.so:5D6931C2 64 00       LSLS            R4, R4, #1
 73 libedog.so:5D6931C4 20 1C       MOVS            R0, R4
 74 libedog.so:5D6931C6 FF F7 26 EC BLX             malloc
 75 libedog.so:5D6931CA 22 1C       MOVS            R2, R4
 76 libedog.so:5D6931CC 06 1C       MOVS            R6, R0
 77 libedog.so:5D6931CE 01 99       LDR             R1, [SP,#0x38+var_34]
 78 libedog.so:5D6931D0 FF F7 5C EC BLX             memset_0
 79 libedog.so:5D6931D4 29 1C       MOVS            R1, R5
 80 libedog.so:5D6931D6 22 1C       MOVS            R2, R4
 81 libedog.so:5D6931D8 30 1C       MOVS            R0, R6
 82 libedog.so:5D6931DA FF F7 52 EC BLX             memcpy_0
 83 libedog.so:5D6931DE 04 9B       LDR             R3, [SP,#0x38+codeSize]
 84 libedog.so:5D6931E0 05 9A       LDR             R2, [SP,#0x38+data]
 85 libedog.so:5D6931E2 07 99       LDR             R1, [SP,#0x38+codeoffset]
 86 libedog.so:5D6931E4 5D 00       LSLS            R5, R3, #1
 87 libedog.so:5D6931E6 02 98       LDR             R0, [SP,#0x38+Debug_info]
 88 libedog.so:5D6931E8 51 18       ADDS            R1, R2, R1
 89 libedog.so:5D6931EA 01 23       MOVS            R3, #1
 90 libedog.so:5D6931EC 2A 1C       MOVS            R2, R5
 91 libedog.so:5D6931EE 01 F0 1E EF BLX             dbone_crypt_ins         ; 解密指令
 92 libedog.so:5D6931F2 01 9B       LDR             R3, [SP,#0x38+var_34]
 93 libedog.so:5D6931F4 34 1C       MOVS            R4, R6
 94 libedog.so:5D6931F6 10 34       ADDS            R4, #0x10
 95 libedog.so:5D6931F8 01 1C       MOVS            R1, R0
 96 libedog.so:5D6931FA B3 60       STR             R3, [R6,#8]             ; 清空Debug_info
 97 libedog.so:5D6931FC 20 1C       MOVS            R0, R4
 98 libedog.so:5D6931FE 2A 1C       MOVS            R2, R5
 99 libedog.so:5D693200 FF F7 3E EC BLX             memcpy_0                ; 還原指令
100 libedog.so:5D693204 3C 62       STR             R4, [R7,#0x20]
101 libedog.so:5D693206
102 libedog.so:5D693206             loc_5D693206                            ; CODE XREF: _Z13restoreMethodP11ClassObjectP6Method+6j
103 libedog.so:5D693206                                                     ; _Z13restoreMethodP11ClassObjectP6Method+Cj ...
104 libedog.so:5D693206 09 B0       ADD             SP, SP, #0x24
105 libedog.so:5D693208 F0 BD       POP             {R4-R7,PC}
106 libedog.so:5D693208             ; End of function _Z13restoreMethodP1
107 解密指令
108 libedog.so:5D69502C
109 libedog.so:5D69502C             dbone_crypt_ins                         ; CODE XREF: _Z13restoreMethodP11ClassObjectP6Method+AAp
110 libedog.so:5D69502C
111 libedog.so:5D69502C             DecMode= -0x1C
112 libedog.so:5D69502C             codeSize= -0x18
113 libedog.so:5D69502C             codedata= -0x14
114 libedog.so:5D69502C             key= -0x10
115 libedog.so:5D69502C             crckey= -8
116 libedog.so:5D69502C
117 libedog.so:5D69502C 00 48 2D E9 STMFD           SP!, {R11,LR}
118 libedog.so:5D695030 04 B0 8D E2 ADD             R11, SP, #4
119 libedog.so:5D695034 18 D0 4D E2 SUB             SP, SP, #0x18
120 libedog.so:5D695038 10 00 0B E5 STR             R0, [R11,#key]
121 libedog.so:5D69503C 14 10 0B E5 STR             R1, [R11,#codedata]
122 libedog.so:5D695040 18 20 0B E5 STR             R2, [R11,#codeSize]
123 libedog.so:5D695044 1C 30 0B E5 STR             R3, [R11,#DecMode]      ; 1
124 libedog.so:5D695048 10 30 4B E2 SUB             R3, R11, #-key
125 libedog.so:5D69504C 03 00 A0 E1 MOV             R0, R3
126 libedog.so:5D695050 04 10 A0 E3 MOV             R1, #4
127 libedog.so:5D695054 47 01 00 EB BL              _Z5crc32Phj
128 libedog.so:5D695058 00 30 A0 E1 MOV             R3, R0
129 libedog.so:5D69505C 08 30 0B E5 STR             R3, [R11,#crckey]
130 libedog.so:5D695060 1C 30 1B E5 LDR             R3, [R11,#DecMode]
131 libedog.so:5D695064 01 00 53 E3 CMP             R3, #1
132 libedog.so:5D695068 06 00 00 1A BNE             loc_5D695088
133 libedog.so:5D69506C 08 20 1B E5 LDR             R2, [R11,#crckey]
134 libedog.so:5D695070 18 30 1B E5 LDR             R3, [R11,#codeSize]
135 libedog.so:5D695074 02 00 A0 E1 MOV             R0, R2
136 libedog.so:5D695078 14 10 1B E5 LDR             R1, [R11,#codedata]
137 libedog.so:5D69507C 14 20 1B E5 LDR             R2, [R11,#codedata]
138 libedog.so:5D695080 80 00 00 EB BL              _Z8XorArrayjPhS_j
139 libedog.so:5D695084 0D 00 00 EA B               loc_5D6950C0
140 libedog.so:5D695088             ; ---------------------------------------------------------------------------
141 libedog.so:5D695088
142 libedog.so:5D695088             loc_5D695088                            ; CODE XREF: dbone_crypt_ins+3Cj
143 libedog.so:5D695088 1C 30 1B E5 LDR             R3, [R11,#DecMode]
144 libedog.so:5D69508C 00 00 53 E3 CMP             R3, #0
145 libedog.so:5D695090 06 00 00 1A BNE             loc_5D6950B0
146 libedog.so:5D695094 10 20 1B E5 LDR             R2, [R11,#key]
147 libedog.so:5D695098 18 30 1B E5 LDR             R3, [R11,#codeSize]
148 libedog.so:5D69509C 02 00 A0 E1 MOV             R0, R2
149 libedog.so:5D6950A0 14 10 1B E5 LDR             R1, [R11,#codedata]
150 libedog.so:5D6950A4 14 20 1B E5 LDR             R2, [R11,#codedata]
151 libedog.so:5D6950A8 B1 00 00 EB BL              _Z13XorArray_0x99jPhS_j
152 libedog.so:5D6950AC 03 00 00 EA B               loc_5D6950C0
153 libedog.so:5D6950B0             ; ---------------------------------------------------------------------------
154 libedog.so:5D6950B0
155 libedog.so:5D6950B0             loc_5D6950B0                            ; CODE XREF: dbone_crypt_ins+64j
156 libedog.so:5D6950B0 18 30 9F E5 LDR             R3, =(aUsageDbone_cry - 0x5D6950BC)
157 libedog.so:5D6950B4 03 30 8F E0 ADD             R3, PC, R3              ; "USAGE:dbone_crypt_ins(key,ins,ins_lenth"...
158 libedog.so:5D6950B8 03 00 A0 E1 MOV             R0, R3
159 libedog.so:5D6950BC 99 F6 FF EB BL              puts
160 libedog.so:5D6950C0
161 libedog.so:5D6950C0             loc_5D6950C0                            ; CODE XREF: dbone_crypt_ins+58j
162 libedog.so:5D6950C0                                                     ; dbone_crypt_ins+80j
163 libedog.so:5D6950C0 14 30 1B E5 LDR             R3, [R11,#codedata]
164 libedog.so:5D6950C4 03 00 A0 E1 MOV             R0, R3
165 libedog.so:5D6950C8 04 D0 4B E2 SUB             SP, R11, #4
166 libedog.so:5D6950CC 00 88 BD E8 LDMFD           SP!, {R11,PC}
167 libedog.so:5D6950CC             ; End of function dbone_crypt_ins
168 libedog.so:5D6950CC
169 libedog.so:5D6950CC             ; -------------
170 
171 //迴圈解密
172 
173 libedog.so:5D695288             _Z8XorArrayjPhS_j                       ; CODE XREF: dbone_crypt_file+180p
174 libedog.so:5D695288                                                     ; dbone_crypt_ins+54p
175 libedog.so:5D695288
176 libedog.so:5D695288             codeSize= -0x24
177 libedog.so:5D695288             codedata1= -0x20
178 libedog.so:5D695288             codedata= -0x1C
179 libedog.so:5D695288             crckey= -0x18
180 libedog.so:5D695288             crckey1= -0x14
181 libedog.so:5D695288             crckeyaddr= -0x10
182 libedog.so:5D695288             crckeyindex= -0xC
183 libedog.so:5D695288             index= -8
184 libedog.so:5D695288
185 libedog.so:5D695288 00 48 2D E9 STMFD           SP!, {R11,LR}
186 libedog.so:5D69528C 04 B0 8D E2 ADD             R11, SP, #4
187 libedog.so:5D695290 20 D0 4D E2 SUB             SP, SP, #0x20
188 libedog.so:5D695294 18 00 0B E5 STR             R0, [R11,#crckey]
189 libedog.so:5D695298 1C 10 0B E5 STR             R1, [R11,#codedata]
190 libedog.so:5D69529C 20 20 0B E5 STR             R2, [R11,#codedata1]
191 libedog.so:5D6952A0 24 30 0B E5 STR             R3, [R11,#codeSize]
192 libedog.so:5D6952A4 18 30 1B E5 LDR             R3, [R11,#crckey]
193 libedog.so:5D6952A8 14 30 0B E5 STR             R3, [R11,#crckey1]
194 libedog.so:5D6952AC 14 30 4B E2 SUB             R3, R11, #-crckey1
195 libedog.so:5D6952B0 10 30 0B E5 STR             R3, [R11,#crckeyaddr]
196 libedog.so:5D6952B4 00 30 A0 E3 MOV             R3, #0
197 libedog.so:5D6952B8 08 30 0B E5 STR             R3, [R11,#index]
198 libedog.so:5D6952BC 00 30 A0 E3 MOV             R3, #0
199 libedog.so:5D6952C0 0C 30 0B E5 STR             R3, [R11,#crckeyindex]
200 libedog.so:5D6952C4 00 30 A0 E3 MOV             R3, #0
201 libedog.so:5D6952C8 08 30 0B E5 STR             R3, [R11,#index]
202 libedog.so:5D6952CC 1E 00 00 EA B               loc_5D69534C
203 libedog.so:5D6952D0             ; ---------------------------------------------------------------------------
204 libedog.so:5D6952D0
205 libedog.so:5D6952D0             loc_5D6952D0                            ; CODE XREF: _Z8XorArrayjPhS_j+E0j
206 libedog.so:5D6952D0 08 30 1B E5 LDR             R3, [R11,#index]
207 libedog.so:5D6952D4 20 20 1B E5 LDR             R2, [R11,#codedata1]
208 libedog.so:5D6952D8 03 30 82 E0 ADD             R3, R2, R3
209 libedog.so:5D6952DC 08 20 1B E5 LDR             R2, [R11,#index]
210 libedog.so:5D6952E0 1C 10 1B E5 LDR             R1, [R11,#codedata]
211 libedog.so:5D6952E4 02 20 81 E0 ADD             R2, R1, R2
212 libedog.so:5D6952E8 00 10 D2 E5 LDRB            R1, [R2]
213 libedog.so:5D6952EC 0C 20 1B E5 LDR             R2, [R11,#crckeyindex]
214 libedog.so:5D6952F0 10 00 1B E5 LDR             R0, [R11,#crckeyaddr]
215 libedog.so:5D6952F4 02 20 80 E0 ADD             R2, R0, R2
216 libedog.so:5D6952F8 00 20 D2 E5 LDRB            R2, [R2]
217 libedog.so:5D6952FC 02 20 21 E0 EOR             R2, R1, R2
218 libedog.so:5D695300 FF 20 02 E2 AND             R2, R2, #0xFF
219 libedog.so:5D695304 00 20 C3 E5 STRB            R2, [R3]
220 libedog.so:5D695308 0C 30 1B E5 LDR             R3, [R11,#crckeyindex]
221 libedog.so:5D69530C 03 00 53 E3 CMP             R3, #3                  ; 比較key是否結束
222 libedog.so:5D695310 07 00 00 1A BNE             loc_5D695334
223 libedog.so:5D695314 14 30 1B E5 LDR             R3, [R11,#crckey1]
224 libedog.so:5D695318 03 00 A0 E1 MOV             R0, R3
225 libedog.so:5D69531C 6C FF FF EB BL              _Z10PolyXorKeyj
226 libedog.so:5D695320 00 30 A0 E1 MOV             R3, R0
227 libedog.so:5D695324 14 30 0B E5 STR             R3, [R11,#crckey1]
228 libedog.so:5D695328 00 30 A0 E3 MOV             R3, #0
229 libedog.so:5D69532C 0C 30 0B E5 STR             R3, [R11,#crckeyindex]
230 libedog.so:5D695330 02 00 00 EA B               loc_5D695340
231 libedog.so:5D695334             ; ---------------------------------------------------------------------------
232 libedog.so:5D695334
233 libedog.so:5D695334             loc_5D695334                            ; CODE XREF: _Z8XorArrayjPhS_j+88j
234 libedog.so:5D695334 0C 30 1B E5 LDR             R3, [R11,#crckeyindex]
235 libedog.so:5D695338 01 30 83 E2 ADD             R3, R3, #1
236 libedog.so:5D69533C 0C 30 0B E5 STR             R3, [R11,#crckeyindex]
237 libedog.so:5D695340
238 libedog.so:5D695340             loc_5D695340                            ; CODE XREF: _Z8XorArrayjPhS_j+A8j
239 libedog.so:5D695340 08 30 1B E5 LDR             R3, [R11,#index]
240 libedog.so:5D695344 01 30 83 E2 ADD             R3, R3, #1
241 libedog.so:5D695348 08 30 0B E5 STR             R3, [R11,#index]
242 libedog.so:5D69534C
243 libedog.so:5D69534C             loc_5D69534C                            ; CODE XREF: _Z8XorArrayjPhS_j+44j
244 libedog.so:5D69534C 24 20 1B E5 LDR             R2, [R11,#codeSize]
245 libedog.so:5D695350 08 30 1B E5 LDR             R3, [R11,#index]
246 libedog.so:5D695354 03 00 52 E1 CMP             R2, R3
247 libedog.so:5D695358 00 30 A0 D3 MOVLE           R3, #0
248 libedog.so:5D69535C 01 30 A0 C3 MOVGT           R3, #1
249 libedog.so:5D695360 FF 30 03 E2 AND             R3, R3, #0xFF
250 libedog.so:5D695364 00 00 53 E3 CMP             R3, #0
251 libedog.so:5D695368 D8 FF FF 1A BNE             loc_5D6952D0
252 libedog.so:5D69536C 04 D0 4B E2 SUB             SP, R11, #4
253 libedog.so:5D695370 00 88 BD E8 LDMFD           SP!, {R11,PC}
254 libedog.so:5D695370             ; End of function _Z8XorArrayjPhS_j
255 libedog.so:5D695370
256 libedog.so:5D695374
257 libedog.so:5D695374             ; =============== S U B R O U T

0x04 編寫修復程式

         修復程式主要分為解析dex與解密兩個步驟來完成,這裡只貼出部分程式碼詳細的請看工程,程式碼寫得比較粗操,看下思路就行了,有性趣的就慢慢擼吧!

  1 void fixdexClassData()
  2 {
  3 
  4     DexFile *dexFile = &gDexFile;
  5 
  6     char * Tag = "L";
  7     char * ClassTag = "Landroid/";
  8 
  9     const DexClassDef* classdef;
 10     u4 count = dexFile->pHeader->classDefsSize;
 11 
 12     printf("該DEX共有%d 個類\n", count);
 13 
 14     const u1* pEncodedData = NULL;
 15     DexClassData* pClassData = NULL;
 16     const char *descriptor = NULL;
 17 
 18 
 19     int FileSize = file_size();
 20 
 21     gCodeData = (u1*)malloc(FileSize);
 22     if (NULL == gCodeData)
 23     {
 24         printf("分配記憶體失敗!\n");
 25         return;
 26     }
 27     memset(gCodeData, 0, FileSize);
 28 
 29     //獲得加密指令資料
 30     GetCodeData(gCodeData, FileSize);
 31 
 32     if (NULL == gCodeData)
 33     {
 34         printf("獲取加密指令資料出錯!\n");
 35         return;
 36     }
 37 
 38     for(u4 i=0; i<count; i++){
 39         classdef = dexGetClassDef(dexFile, i);
 40 
 41         descriptor = getTpyeIdString(dexFile, classdef->classIdx);
 42 
 43         if (strstr(descriptor,Tag) == NULL)
 44         {
 45             continue;
 46         }
 47 
 48         //跳過一些系統的類
 49         if (strstr(descriptor, ClassTag) != NULL)
 50         {
 51             continue;
 52         }
 53 
 54         pEncodedData = dexFile->baseAddr + classdef->classDataOff;
 55         pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
 56 
 57         if (pClassData == NULL) {
 58             continue;
 59         }
 60 
 61       FixdexMethodInsns(dexFile, pClassData, descriptor);
 62 
 63     }
 64 
 65 }
 66 
 67 void FixdexMethodInsns(DexFile *dexFile, const DexClassData*classData ,const char* className)
 68 {
 69     int idx = 0;
 70     DexMethod *method = NULL;
 71     const DexMethodId* methodId = NULL;
 72     DexCode* code = NULL;
 73     const char* methodName;
 74     method = classData->directMethods;
 75     methodId = dexFile->pMethodIds;
 76     unsigned int CodeDataOffset = 0;
 77     u1 * tempCode = NULL;
 78     for (int i = 0; i < (int) classData->header.directMethodsSize; i++) {
 79         idx = classData->directMethods[i].methodIdx;
 80 
 81         methodId = dexGetMethodId(dexFile, idx);
 82         methodName = dexStringById(dexFile, methodId->nameIdx);
 83 
 84         DexCode* pCode = dexGetCode(dexFile, &classData->directMethods[i]);
 85         if (NULL == pCode)
 86         {
 87             continue;
 88         }
 89         //判斷是否為保護後的方法,如果是就修復指令
 90         if ( (pCode->debugInfoOff > 0x1FFFFFFF) && (pCode->insns[0] == 0X00))
 91         {
 92             //求加密指令的偏移
 93             CodeDataOffset = pCode->debugInfoOff << 0x8;
 94             CodeDataOffset >>= 0x6;
 95             //解密指令
 96             tempCode = DecCode(gCodeData+CodeDataOffset, pCode->insnsSize*sizeof(u2), pCode->debugInfoOff, gCodeData);
 97             //修復指令
 98             memcpy(pCode->insns, tempCode, (pCode->insnsSize)*sizeof(u2));
 99             pCode->debugInfoOff = 0x00;
100             printf("修復%s 類中的%s 方法成功! 大小%X\n",className, methodName,pCode->insnsSize);
101             if (NULL != tempCode)
102             {
103                 free(tempCode);
104                 tempCode = NULL;
105             }
106         }
107     }
108 
109     for (int i = 0; i < (int) classData->header.virtualMethodsSize; i++) {
110         idx = classData->virtualMethods[i].methodIdx;
111 
112         methodId = dexGetMethodId(dexFile, idx);
113         methodName = dexStringById(dexFile, methodId->nameIdx);
114 
115         DexCode* pCode = dexGetCode(dexFile, &classData->virtualMethods[i]);
116         if (NULL == pCode)
117         {
118             continue;
119         }
120         //判斷是否為保護後的方法,如果是就修復指令
121         if ( (pCode->debugInfoOff > 0x1FFFFFFF) && (pCode->insns[0] == 0X00))
122         {
123             //求加密指令的偏移
124             CodeDataOffset = pCode->debugInfoOff << 0x8;
125             CodeDataOffset >>= 0x6;
126             //解密指令
127             tempCode = DecCode(gCodeData+CodeDataOffset, pCode->insnsSize*sizeof(u2), pCode->debugInfoOff, gCodeData);
128             //修復指令
129             memcpy(pCode->insns, tempCode, (pCode->insnsSize)*sizeof(u2));
130             pCode->debugInfoOff = 0x00;
131             printf("修復%s 類中的%s 方法成功! 大小%X\n",className, methodName,pCode->insnsSize);
132             if (NULL != tempCode)
133             {
134                 free(tempCode);
135                 tempCode = NULL;
136             }
137         }
138     }
139     return;
140 }
141 unsigned int PolyXorKey(DWORD crckey)
142 {
143     unsigned int dwKey;
144     char temp;
145     unsigned __int8 temp1;
146     unsigned __int8 temp2;
147     char *pKey;
148     int temp3;
149     int j;
150     int i;
151 
152     j = 0;
153     temp3 = 0;
154     pKey = (char *)&dwKey;
155     temp2 = 0;
156     temp1 = 0;
157     temp = 0;
158     dwKey = crckey ^ 0xDF138530;
159     i = 0;
160     while ( i <= 3 )
161     {
162         temp2 = *pKey;
163         j = 128;
164         temp3 = 7;
165         while ( j > 1 )
166         {
167             temp = (temp2 & j / 2) >> (temp3 - 1);
168             temp1 = ((signed int)(unsigned __int8)(temp2 & j) >> temp3) ^ temp;
169             temp1 <<= temp3;
170             temp2 |= temp1;
171             j /= 2;
172             --temp3;
173         }
174         temp = temp2 & 1;
175         temp1 = temp2 & 1 ^ temp2 & 1;
176         *pKey = temp2;
177         ++i;
178         ++pKey;
179     }
180     return dwKey;
181 }

0x05 測試與總結

         將加固後的 APK中assets資料夾中的data檔案與classes.dex放在修復程式同一個目錄中,然後執行修復程式。

         圖8

去掉AndroidManifest.xml中的殼入口,將修復後的classes.dex重新打包反編譯,成功執行,如圖9所示能正常反編譯原始碼,至此,分析完畢。

         圖9

殼流程總結:

AndroidManifest.xml中的殼入口->com.edog.AppWrapper->

so中Java_com_edog_ELibrary_d1->hook dvmResolveClass函式->在dvmResolveClass hook函式中修復指令->結束。

 

語言表達不行,說的很雜,自己都覺得文章沒有任何邏輯可言,如果大家能從中獲得一些思路那也是好的, 不過這次分析讓自己學到了很多,感謝APK加固作者。

樣本及pdf文件下載

http://yunpan.cn/cmApFwTesyPGk (提取碼:b37f)

相關文章