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

測試環境與工具
手機系統: 華爲U9508 android 4.2.2
IDA Pro 6.8
AndroidKiller 1.2

高手不要見笑,僅供小菜玩樂,有不對或不足的地方還請多多指教,不勝感激!


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->結束。

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

0x03 指令還原算法分析

原始指令還原時機就是在dvmResolveClass的hook函數中對對指令進行解密還原,以下結構的中的幾個值會用到,

因爲被保護後的方法中的debugInfoOff的值被修改成從0x20000000開始的一個值,該值在指令還原時起到重要作用。

[C++] 純文本查看 複製代碼
?
1
2
3
4
5
6
7
8
9
structDexCode {
    u2  registersSize;
    u2  insSize;
    u2  outsSize;
    u2  triesSize;
    u4  debugInfoOff;      /* file offset to debug info stream */
    u4  insnsSize;        /* size of the insns array, in u2 units */
    u2  insns[1];
};

指令還原大致流程如下:

判斷是否爲保護的類->判斷debuginfo值大於0x1FFFFFFF->將debuginfo值左移8位再右移6位->將移位後

的值加上加密指令在內存中的開始址取4字節做爲偏移->將偏移加上加密指令在內存中的開始地址定位到對

應方法的指令->解密指令並還原->清零debuginfo值->結束。

解密指令算法流程如下:(每4字節進行xor)

XorArray函數中進行解密操作->將方法debuginfo值進行crc32計算得到一個值->crc32計算得到的值與指令

每4字節進行xor->4字節結束後再將crc32值用PolyXorKey函數生成一個新的4字節數做爲密鑰,一直循環到

解密完成。


代碼流程如下
[Asm] 純文本查看 複製代碼
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
libedog.so:5D693144
libedog.so:5D693144             _Z13restoreMethodP11ClassObjectP6Method ; CODE XREF: _Z10replaceFunP11ClassObjectjb+22p
libedog.so:5D693144                                                   ; _Z10replaceFunP11ClassObjectjb+3Ap
libedog.so:5D693144
libedog.so:5D693144             var_34= -0x34
libedog.so:5D693144             Debug_info= -0x30
libedog.so:5D693144             var_2C= -0x2C
libedog.so:5D693144             codeSize= -0x28
libedog.so:5D693144             data= -0x24
libedog.so:5D693144             codeoffset= -0x1C
libedog.so:5D693144
libedog.so:5D693144 F0 B5       PUSH           {R4-R7,LR}
libedog.so:5D693146 89 B0       SUB            SP,SP, #0x24
libedog.so:5D693148 0F 1E       SUBS            R7, R1, #0
libedog.so:5D69314A 5C D0       BEQ             loc_5D693206
libedog.so:5D69314C 84 69       LDR             R4, [R0,#0x18]
libedog.so:5D69314E 00 2C       CMP            R4, #0
libedog.so:5D693150 59 D0       BEQ             loc_5D693206
libedog.so:5D693152 20 1C       MOVS           R0, R4
libedog.so:5D693154 4C 21       MOVS           R1, #'L'
libedog.so:5D693156 FF F7 A0 EC BLX             strchr
libedog.so:5D69315A 00 28       CMP            R0, #0
libedog.so:5D69315C 53 D0       BEQ             loc_5D693206
libedog.so:5D69315E 3E 6A       LDR             R6, [R7,#0x20]
libedog.so:5D693160 00 2E       CMP            R6, #0
libedog.so:5D693162 50 D0       BEQ             loc_5D693206
libedog.so:5D693164 35 1C       MOVS           R5, R6
libedog.so:5D693166 10 3D       SUBS            R5, #0x10
libedog.so:5D693168 AA 68       LDR             R2, [R5,#8]
libedog.so:5D69316A 02 92       STR            R2, [SP,#0x38+Debug_info]
libedog.so:5D69316C EB 88       LDRH            R3, [R5,#6]
libedog.so:5D69316E EA 68       LDR             R2, [R5,#0xC]
libedog.so:5D693170 03 93       STR            R3, [SP,#0x38+var_2C]
libedog.so:5D693172 04 92       STR            R2, [SP,#0x38+codeSize]
libedog.so:5D693174 25 4B       LDR             R3, =0x1FFFFFFF
libedog.so:5D693176 02 9A       LDR             R2, [SP,#0x38+Debug_info]
libedog.so:5D693178 9A 42       CMP            R2, R3                 ; 判斷debuginfo值大於 0x1FFFFFFF (因爲被保護的方法debuginfo從0X20000000開始)
libedog.so:5D69317A 44 D9       BLS             loc_5D693206
libedog.so:5D69317C 24 49       LDR             R1, =(aLandroid - 0x5D693184)
libedog.so:5D69317E 20 1C       MOVS           R0, R4
libedog.so:5D693180 79 44       ADD            R1, PC                 ; "Landroid/"
libedog.so:5D693182 FF F7 30 EC BLX             strstr                 ; 是系統的類就跳過
libedog.so:5D693186 00 28       CMP            R0, #0
libedog.so:5D693188 3D D1       BNE             loc_5D693206
libedog.so:5D69318A 36 78       LDRB            R6, [R6]
libedog.so:5D69318C 01 96       STR            R6, [SP,#0x38+var_34]
libedog.so:5D69318E 00 2E       CMP            R6, #0
libedog.so:5D693190 39 D1       BNE             loc_5D693206
libedog.so:5D693192 20 4B       LDR             R3, =(aFjFj0fjFjFj4fj+0xC - 0x5D69319C)
libedog.so:5D693194 07 A8       ADD            R0,SP, #0x38+codeoffset
libedog.so:5D693196 07 96       STR            R6, [SP,#0x38+codeoffset]
libedog.so:5D693198 7B 44       ADD            R3, PC                 ; "(fj],fj]4fj]i]"
libedog.so:5D69319A 1B 68       LDR             R3, [R3]               ; "(fj],fj]4fj]i]"
libedog.so:5D69319C 1B 68       LDR             R3, [R3]               ; data數據
libedog.so:5D69319E 05 93       STR            R3, [SP,#0x38+data]
libedog.so:5D6931A0 02 9B       LDR             R3, [SP,#0x38+Debug_info]
libedog.so:5D6931A2 05 9A       LDR             R2, [SP,#0x38+data]
libedog.so:5D6931A4 19 02       LSLS            R1, R3, #8
libedog.so:5D6931A6 89 09       LSRS            R1, R1, #6
libedog.so:5D6931A8 89 18       ADDS            R1, R1, R2
libedog.so:5D6931AA 04 22       MOVS           R2, #4
libedog.so:5D6931AC FF F7 68 EC BLX             memcpy_0
libedog.so:5D6931B0 03 9A       LDR             R2, [SP,#0x38+var_2C]
libedog.so:5D6931B2 04 9C       LDR             R4, [SP,#0x38+codeSize]
libedog.so:5D6931B4 93 00       LSLS            R3, R2, #2
libedog.so:5D6931B6 08 34       ADDS            R4, #8
libedog.so:5D6931B8 E4 18       ADDS            R4, R4, R3
libedog.so:5D6931BA 13 1C       MOVS           R3, R2
libedog.so:5D6931BC 01 33       ADDS            R3, #1
libedog.so:5D6931BE 9B 00       LSLS            R3, R3, #2
libedog.so:5D6931C0 E4 18       ADDS            R4, R4, R3
libedog.so:5D6931C2 64 00       LSLS            R4, R4, #1
libedog.so:5D6931C4 20 1C       MOVS           R0, R4
libedog.so:5D6931C6 FF F7 26 EC BLX             malloc
libedog.so:5D6931CA 22 1C       MOVS           R2, R4
libedog.so:5D6931CC 06 1C       MOVS           R6, R0
libedog.so:5D6931CE 01 99       LDR             R1, [SP,#0x38+var_34]
libedog.so:5D6931D0 FF F7 5C EC BLX             memset_0
libedog.so:5D6931D4 29 1C       MOVS           R1, R5
libedog.so:5D6931D6 22 1C       MOVS           R2, R4
libedog.so:5D6931D8 30 1C       MOVS           R0, R6
libedog.so:5D6931DA FF F7 52 EC BLX             memcpy_0
libedog.so:5D6931DE 04 9B       LDR             R3, [SP,#0x38+codeSize]
libedog.so:5D6931E0 05 9A       LDR             R2, [SP,#0x38+data]
libedog.so:5D6931E2 07 99       LDR             R1, [SP,#0x38+codeoffset]
libedog.so:5D6931E4 5D 00       LSLS            R5, R3, #1
libedog.so:5D6931E6 02 98       LDR             R0, [SP,#0x38+Debug_info]
libedog.so:5D6931E8 51 18       ADDS            R1, R2, R1
libedog.so:5D6931EA 01 23       MOVS           R3, #1
libedog.so:5D6931EC 2A 1C       MOVS           R2, R5
libedog.so:5D6931EE 01 F0 1E EF BLX             dbone_crypt_ins        ; 解密指令
libedog.so:5D6931F2 01 9B       LDR             R3, [SP,#0x38+var_34]
libedog.so:5D6931F4 34 1C       MOVS           R4, R6
libedog.so:5D6931F6 10 34       ADDS            R4, #0x10
libedog.so:5D6931F8 01 1C       MOVS           R1, R0
libedog.so:5D6931FA B3 60       STR            R3, [R6,#8]            ; 清空Debug_info
libedog.so:5D6931FC 20 1C       MOVS           R0, R4
libedog.so:5D6931FE 2A 1C       MOVS           R2, R5
libedog.so:5D693200 FF F7 3E EC BLX             memcpy_0               ; 還原指令
libedog.so:5D693204 3C 62       STR            R4, [R7,#0x20]
libedog.so:5D693206
libedog.so:5D693206             loc_5D693206                           ; CODE XREF: _Z13restoreMethodP11ClassObjectP6Method+6j
libedog.so:5D693206                                                   ; _Z13restoreMethodP11ClassObjectP6Method+Cj ...
libedog.so:5D693206 09 B0       ADD            SP,SP, #0x24
libedog.so:5D693208 F0 BD       POP            {R4-R7,PC}
libedog.so:5D693208           ; End of function _Z13restoreMethodP1
解密指令
libedog.so:5D69502C
libedog.so:5D69502C             dbone_crypt_ins                        ; CODE XREF: _Z13restoreMethodP11ClassObjectP6Method+AAp
libedog.so:5D69502C
libedog.so:5D69502C             DecMode= -0x1C
libedog.so:5D69502C             codeSize= -0x18
libedog.so:5D69502C             codedata= -0x14
libedog.so:5D69502C             key= -0x10
libedog.so:5D69502C             crckey= -8
libedog.so:5D69502C
libedog.so:5D69502C 00 48 2D E9 STMFD           SP!, {R11,LR}
libedog.so:5D695030 04 B0 8D E2 ADD            R11,SP, #4
libedog.so:5D695034 18 D0 4D E2 SUB            SP,SP, #0x18
libedog.so:5D695038 10 00 0B E5 STR            R0, [R11,#key]
libedog.so:5D69503C 14 10 0B E5 STR            R1, [R11,#codedata]
libedog.so:5D695040 18 20 0B E5 STR            R2, [R11,#codeSize]
libedog.so:5D695044 1C 30 0B E5 STR            R3, [R11,#DecMode]     ; 1
libedog.so:5D695048 10 30 4B E2 SUB            R3, R11, #-key
libedog.so:5D69504C 03 00 A0 E1 MOV            R0, R3
libedog.so:5D695050 04 10 A0 E3 MOV            R1, #4
libedog.so:5D695054 47 01 00 EB BL             _Z5crc32Phj
libedog.so:5D695058 00 30 A0 E1 MOV            R3, R0
libedog.so:5D69505C 08 30 0B E5 STR            R3, [R11,#crckey]
libedog.so:5D695060 1C 30 1B E5 LDR             R3, [R11,#DecMode]
libedog.so:5D695064 01 00 53 E3 CMP            R3, #1
libedog.so:5D695068 06 00 00 1A BNE             loc_5D695088
libedog.so:5D69506C 08 20 1B E5 LDR             R2, [R11,#crckey]
libedog.so:5D695070 18 30 1B E5 LDR             R3, [R11,#codeSize]
libedog.so:5D695074 02 00 A0 E1 MOV            R0, R2
libedog.so:5D695078 14 10 1B E5 LDR             R1, [R11,#codedata]
libedog.so:5D69507C 14 20 1B E5 LDR             R2, [R11,#codedata]
libedog.so:5D695080 80 00 00 EB BL             _Z8XorArrayjPhS_j
libedog.so:5D695084 0D 00 00 EA B               loc_5D6950C0
libedog.so:5D695088           ; ---------------------------------------------------------------------------
libedog.so:5D695088
libedog.so:5D695088             loc_5D695088                           ; CODE XREF: dbone_crypt_ins+3Cj
libedog.so:5D695088 1C 30 1B E5 LDR             R3, [R11,#DecMode]
libedog.so:5D69508C 00 00 53 E3 CMP            R3, #0
libedog.so:5D695090 06 00 00 1A BNE             loc_5D6950B0
libedog.so:5D695094 10 20 1B E5 LDR             R2, [R11,#key]
libedog.so:5D695098 18 30 1B E5 LDR             R3, [R11,#codeSize]
libedog.so:5D69509C 02 00 A0 E1 MOV            R0, R2
libedog.so:5D6950A0 14 10 1B E5 LDR             R1, [R11,#codedata]
libedog.so:5D6950A4 14 20 1B E5 LDR             R2, [R11,#codedata]
libedog.so:5D6950A8 B1 00 00 EB BL             _Z13XorArray_0x99jPhS_j
libedog.so:5D6950AC 03 00 00 EA B               loc_5D6950C0
libedog.so:5D6950B0           ; ---------------------------------------------------------------------------
libedog.so:5D6950B0
libedog.so:5D6950B0             loc_5D6950B0                           ; CODE XREF: dbone_crypt_ins+64j
libedog.so:5D6950B0 18 30 9F E5 LDR             R3, =(aUsageDbone_cry - 0x5D6950BC)
libedog.so:5D6950B4 03 30 8F E0 ADD            R3, PC, R3             ; "USAGE:dbone_crypt_ins(key,ins,ins_lenth"...
libedog.so:5D6950B8 03 00 A0 E1 MOV            R0, R3
libedog.so:5D6950BC 99 F6 FF EB BL             puts
libedog.so:5D6950C0
libedog.so:5D6950C0             loc_5D6950C0                           ; CODE XREF: dbone_crypt_ins+58j
libedog.so:5D6950C0                                                   ; dbone_crypt_ins+80j
libedog.so:5D6950C0 14 30 1B E5 LDR             R3, [R11,#codedata]
libedog.so:5D6950C4 03 00 A0 E1 MOV            R0, R3
libedog.so:5D6950C8 04 D0 4B E2 SUB            SP, R11, #4
libedog.so:5D6950CC 00 88 BD E8 LDMFD           SP!, {R11,PC}
libedog.so:5D6950CC           ; End of function dbone_crypt_ins
libedog.so:5D6950CC
libedog.so:5D6950CC           ; -------------
 
//循環解密
 
libedog.so:5D695288             _Z8XorArrayjPhS_j                      ; CODE XREF: dbone_crypt_file+180p
libedog.so:5D695288                                                   ; dbone_crypt_ins+54p
libedog.so:5D695288
libedog.so:5D695288             codeSize= -0x24
libedog.so:5D695288             codedata1= -0x20
libedog.so:5D695288             codedata= -0x1C
libedog.so:5D695288             crckey= -0x18
libedog.so:5D695288             crckey1= -0x14
libedog.so:5D695288             crckeyaddr= -0x10
libedog.so:5D695288             crckeyindex= -0xC
libedog.so:5D695288             index= -8
libedog.so:5D695288
libedog.so:5D695288 00 48 2D E9 STMFD           SP!, {R11,LR}
libedog.so:5D69528C 04 B0 8D E2 ADD            R11,SP, #4
libedog.so:5D695290 20 D0 4D E2 SUB            SP,SP, #0x20
libedog.so:5D695294 18 00 0B E5 STR            R0, [R11,#crckey]
libedog.so:5D695298 1C 10 0B E5 STR            R1, [R11,#codedata]
libedog.so:5D69529C 20 20 0B E5 STR            R2, [R11,#codedata1]
libedog.so:5D6952A0 24 30 0B E5 STR            R3, [R11,#codeSize]
libedog.so:5D6952A4 18 30 1B E5 LDR             R3, [R11,#crckey]
libedog.so:5D6952A8 14 30 0B E5 STR            R3, [R11,#crckey1]
libedog.so:5D6952AC 14 30 4B E2 SUB            R3, R11, #-crckey1
libedog.so:5D6952B0 10 30 0B E5 STR            R3, [R11,#crckeyaddr]
libedog.so:5D6952B4 00 30 A0 E3 MOV            R3, #0
libedog.so:5D6952B8 08 30 0B E5 STR            R3, [R11,#index]
libedog.so:5D6952BC 00 30 A0 E3 MOV            R3, #0
libedog.so:5D6952C0 0C 30 0B E5 STR            R3, [R11,#crckeyindex]
libedog.so:5D6952C4 00 30 A0 E3 MOV            R3, #0
libedog.so:5D6952C8 08 30 0B E5 STR            R3, [R11,#index]
libedog.so:5D6952CC 1E 00 00 EA B               loc_5D69534C
libedog.so:5D6952D0           ; ---------------------------------------------------------------------------
libedog.so:5D6952D0
libedog.so:5D6952D0             loc_5D6952D0                           ; CODE XREF: _Z8XorArrayjPhS_j+E0j
libedog.so:5D6952D0 08 30 1B E5 LDR             R3, [R11,#index]
libedog.so:5D6952D4 20 20 1B E5 LDR             R2, [R11,#codedata1]
libedog.so:5D6952D8 03 30 82 E0 ADD            R3, R2, R3
libedog.so:5D6952DC 08 20 1B E5 LDR             R2, [R11,#index]
libedog.so:5D6952E0 1C 10 1B E5 LDR             R1, [R11,#codedata]
libedog.so:5D6952E4 02 20 81 E0 ADD            R2, R1, R2
libedog.so:5D6952E8 00 10 D2 E5 LDRB            R1, [R2]
libedog.so:5D6952EC 0C 20 1B E5 LDR             R2, [R11,#crckeyindex]
libedog.so:5D6952F0 10 00 1B E5 LDR             R0, [R11,#crckeyaddr]
libedog.so:5D6952F4 02 20 80 E0 ADD            R2, R0, R2
libedog.so:5D6952F8 00 20 D2 E5 LDRB            R2, [R2]
libedog.so:5D6952FC 02 20 21 E0 EOR             R2, R1, R2
libedog.so:5D695300 FF 20 02 E2 AND            R2, R2, #0xFF
libedog.so:5D695304 00 20 C3 E5 STRB            R2, [R3]
libedog.so:5D695308 0C 30 1B E5 LDR             R3, [R11,#crckeyindex]
libedog.so:5D69530C 03 00 53 E3 CMP            R3, #3                 ; 比較key是否結束
libedog.so:5D695310 07 00 00 1A BNE             loc_5D695334
libedog.so:5D695314 14 30 1B E5 LDR             R3, [R11,#crckey1]
libedog.so:5D695318 03 00 A0 E1 MOV            R0, R3
libedog.so:5D69531C 6C FF FF EB BL             _Z10PolyXorKeyj
libedog.so:5D695320 00 30 A0 E1 MOV            R3, R0
libedog.so:5D695324 14 30 0B E5 STR            R3, [R11,#crckey1]
libedog.so:5D695328 00 30 A0 E3 MOV            R3, #0
libedog.so:5D69532C 0C 30 0B E5 STR            R3, [R11,#crckeyindex]
libedog.so:5D695330 02 00 00 EA B               loc_5D695340
libedog.so:5D695334           ; ---------------------------------------------------------------------------
libedog.so:5D695334
libedog.so:5D695334             loc_5D695334                           ; CODE XREF: _Z8XorArrayjPhS_j+88j
libedog.so:5D695334 0C 30 1B E5 LDR             R3, [R11,#crckeyindex]
libedog.so:5D695338 01 30 83 E2 ADD            R3, R3, #1
libedog.so:5D69533C 0C 30 0B E5 STR            R3, [R11,#crckeyindex]
libedog.so:5D695340
libedog.so:5D695340             loc_5D695340                           ; CODE XREF: _Z8XorArrayjPhS_j+A8j
libedog.so:5D695340 08 30 1B E5 LDR             R3, [R11,#index]
libedog.so:5D695344 01 30 83 E2 ADD            R3, R3, #1
libedog.so:5D695348 08 30 0B E5 STR            R3, [R11,#index]
libedog.so:5D69534C
libedog.so:5D69534C             loc_5D69534C                           ; CODE XREF: _Z8XorArrayjPhS_j+44j
libedog.so:5D69534C 24 20 1B E5 LDR             R2, [R11,#codeSize]
libedog.so:5D695350 08 30 1B E5 LDR             R3, [R11,#index]
libedog.so:5D695354 03 00 52 E1 CMP            R2, R3
libedog.so:5D695358 00 30 A0 D3 MOVLE           R3, #0
libedog.so:5D69535C 01 30 A0 C3 MOVGT           R3, #1
libedog.so:5D695360 FF 30 03 E2 AND            R3, R3, #0xFF
libedog.so:5D695364 00 00 53 E3 CMP            R3, #0
libedog.so:5D695368 D8 FF FF 1A BNE             loc_5D6952D0
libedog.so:5D69536C 04 D0 4B E2 SUB            SP, R11, #4
libedog.so:5D695370 00 88 BD E8 LDMFD           SP!, {R11,PC}
libedog.so:5D695370           ; End of function _Z8XorArrayjPhS_j
libedog.so:5D695370
libedog.so:5D695374
libedog.so:5D695374           ; =============== S U B R O U T

0x04 編寫修復程序

         修復程序主要分爲解析dex與解密兩個步驟來完成,這裏只貼出部分代碼詳細的請看工程,代碼

寫得比較粗操,看下思路就行了,有性趣的就慢慢擼吧! 

[C++] 純文本查看 複製代碼
?
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
voidfixdexClassData()
{
 
        DexFile *dexFile = &gDexFile;
 
        char* Tag = "L";
        char* ClassTag = "Landroid/";
 
    constDexClassDef* classdef;
    u4 count = dexFile->pHeader->classDefsSize;
 
        printf("該DEX共有%d 個類\n", count);
 
    constu1* pEncodedData = NULL;
    DexClassData* pClassData = NULL;
    constchar*descriptor = NULL;
 
 
        intFileSize = file_size();
 
        gCodeData = (u1*)malloc(FileSize);
        if(NULL == gCodeData)
        {
                printf("分配內存失敗!\n");
                return;
        }
        memset(gCodeData, 0, FileSize);
 
        //獲得加密指令數據
        GetCodeData(gCodeData, FileSize);
 
        if(NULL == gCodeData)
        {
                printf("獲取加密指令數據出錯!\n");
                return;
        }
 
    for(u4 i=0; i<count; i++){
        classdef = dexGetClassDef(dexFile, i);
 
        descriptor = getTpyeIdString(dexFile, classdef->classIdx);
 
                if(strstr(descriptor,Tag) == NULL)
                {
                        continue;
                }
 
                //跳過一些系統的類
                if(strstr(descriptor, ClassTag) != NULL)
                {
                        continue;
                }
 
        pEncodedData = dexFile->baseAddr + classdef->classDataOff;
        pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
 
        if(pClassData == NULL) {
            continue;
        }
 
          FixdexMethodInsns(dexFile, pClassData, descriptor);
 
    }
 
}
 
voidFixdexMethodInsns(DexFile *dexFile, constDexClassData*classData ,constchar* className)
{
        intidx = 0;
        DexMethod *method = NULL;
        constDexMethodId* methodId = NULL;
        DexCode* code = NULL;
        constchar* methodName;
        method = classData->directMethods;
        methodId = dexFile->pMethodIds;
        unsignedintCodeDataOffset = 0;
        u1 * tempCode = NULL;
        for(inti = 0; i < (int) classData->header.directMethodsSize; i++) {
                idx = classData->directMethods[i].methodIdx;
 
                methodId = dexGetMethodId(dexFile, idx);
                methodName = dexStringById(dexFile, methodId->nameIdx);
 
                DexCode* pCode = dexGetCode(dexFile, &classData->directMethods[i]);
                if(NULL == pCode)
                {
                        continue;
                }
                //判斷是否爲保護後的方法,如果是就修復指令
                if( (pCode->debugInfoOff > 0x1FFFFFFF) && (pCode->insns[0] == 0X00))
                {
                        //求加密指令的偏移
                        CodeDataOffset = pCode->debugInfoOff << 0x8;
                        CodeDataOffset >>= 0x6;
                        //解密指令
                        tempCode = DecCode(gCodeData+CodeDataOffset, pCode->insnsSize*sizeof(u2), pCode->debugInfoOff, gCodeData);
                        //修復指令
                        memcpy(pCode->insns, tempCode, (pCode->insnsSize)*sizeof(u2));
                        pCode->debugInfoOff = 0x00;
                        printf("修復%s 類中的%s 方法成功! 大小%X\n",className, methodName,pCode->insnsSize);
                        if(NULL != tempCode)
                        {
                                free(tempCode);
                                tempCode = NULL;
                        }
                }
        }
 
        for(inti = 0; i < (int) classData->header.virtualMethodsSize; i++) {
                idx = classData->virtualMethods[i].methodIdx;
 
                methodId = dexGetMethodId(dexFile, idx);
                methodName = dexStringById(dexFile, methodId->nameIdx);
 
                DexCode* pCode = dexGetCode(dexFile, &classData->virtualMethods[i]);
                if(NULL == pCode)
                {
                        continue;
                }
                //判斷是否爲保護後的方法,如果是就修復指令
                if( (pCode->debugInfoOff > 0x1FFFFFFF) && (pCode->insns[0] == 0X00))
                {
                        //求加密指令的偏移
                        CodeDataOffset = pCode->debugInfoOff << 0x8;
                        CodeDataOffset >>= 0x6;
                        //解密指令
                        tempCode = DecCode(gCodeData+CodeDataOffset, pCode->insnsSize*sizeof(u2), pCode->debugInfoOff, gCodeData);
                        //修復指令
                        memcpy(pCode->insns, tempCode, (pCode->insnsSize)*sizeof(u2));
                        pCode->debugInfoOff = 0x00;
                        printf("修復%s 類中的%s 方法成功! 大小%X\n",className, methodName,pCode->insnsSize);
                        if(NULL != tempCode)
                        {
                                free(tempCode);
                                tempCode = NULL;
                        }
                }
        }
        return;
}
unsignedintPolyXorKey(DWORDcrckey)
{
        unsignedintdwKey;
        chartemp;
        unsigned__int8temp1;
        unsigned__int8temp2;
        char*pKey;
        inttemp3;
        intj;
        inti;
 
        j = 0;
        temp3 = 0;
        pKey = (char*)&dwKey;
        temp2 = 0;
        temp1 = 0;
        temp = 0;
        dwKey = crckey ^ 0xDF138530;
        i = 0;
        while( i <= 3 )
        {
                temp2 = *pKey;
                j = 128;
                temp3 = 7;
                while( j > 1 )
                {
                        temp = (temp2 & j / 2) >> (temp3 - 1);
                        temp1 = ((signedint)(unsigned__int8)(temp2 & j) >> temp3) ^ temp;
                        temp1 <<= temp3;
                        temp2 |= temp1;
                        j /= 2;
                        --temp3;
                }
                temp = temp2 & 1;
                temp1 = temp2 & 1 ^ temp2 & 1;
                *pKey = temp2;
                ++i;
                ++pKey;
        }
        returndwKey;
}


0x05 測試與總結

         將加固後的 APK中assets文件夾中的data文件與classes.dex放在修復程序同一個目錄中,

然後運行修復程序。

 
         圖8

去掉AndroidManifest.xml中的殼入口,將修復後的classes.dex重新打包反編譯,成功運行,如圖9所示能

正常反編譯源碼,至此,分析完畢。

 
殼流程總結:
AndroidManifest.xml中的殼入口->com.edog.AppWrapper->

so中Java_com_edog_ELibrary_d1->hookdvmResolveClass函數->在dvmResolveClass hook函數中

修復指令->結束。

語言表達不行,說的很雜,自己都覺得文章沒有任何邏輯可言,如果大家能從中獲得一些思路那也是好

不過這次分析讓自己學到了很多,感謝APK加固作者。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章