APK加固之類抽取分析與修復
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)
相關文章
- Android加固之後Apk重簽名2024-03-27AndroidAPK
- 360如何加固安卓apk2017-11-28安卓APK
- APK加固之靜態脫殼機編寫入門2015-10-30APK
- APK包的加固手段收集(淺)2024-07-27APK
- ecshop漏洞修復以及如何加固ecshop網站安全2018-10-22網站
- 效能優化 (八) APK 加固之動態替換 Application2019-06-04優化APKAPP
- 某當網apk加固脫個so2022-10-29APK
- APP資料洩露漏洞該如何修復和加固2022-11-03APP
- 定心丸!ZipperDown漏洞分析與修復建議2018-05-18
- Delphi中兩個BUG的分析與修復 (轉)2007-08-15
- 淺談安卓apk加固原理和實現2018-12-04安卓APK
- Android逆向之旅---動態方式破解apk終極篇(加固apk破解方式)2016-12-02AndroidAPK
- Android 熱修復 Tinker 原始碼分析之DexDiff / DexPatch2017-05-25Android原始碼
- 某殼分析+修復(二)2018-05-14
- FAQ寶典之常見問題排查與修復方法2017-11-12
- MySQL修復表的簡單分析2016-12-20MySql
- 熱修復與外掛化基礎——Java與Android的類載入器2018-05-17JavaAndroid
- APK 檔案分析2018-12-16APK
- 資料恢復:AMDU資料抽取恢復2020-06-05資料恢復
- 網站漏洞修復之圖片驗證碼的詳細修復方案2019-05-05網站
- 6_Oracle truncate異常恢復之bbed修復2020-03-05Oracle
- 7_Oracle truncate異常恢復之plsql修復2020-03-06OracleSQL
- 效能優化 (七) APK 加固之 Dex 加解密,反編譯都看不到專案主要程式碼。2019-06-02優化APK解密編譯
- 修復資料庫壞塊之五2008-05-09資料庫
- 修復資料庫壞塊之四2008-05-09資料庫
- 簡單易懂的tinker熱修復原理分析2018-08-03
- 配置dg broker的問題分析及修復2015-10-10
- 『學了就忘』Linux啟動引導與修復 — 74、Linux系統的修復模式(光碟修復模式)2021-12-10Linux模式
- struts2架構網站漏洞修復詳情與利用漏洞修復方案2018-12-03架構網站
- PrestaShop網站漏洞修復如何修復2019-01-02REST網站
- oracle,db2,mysql類比之九備份與恢復2009-11-15OracleDB2MySql
- Java Web之BaseServlet的抽取2017-12-13JavaWebServlet
- 類屬性設定與修飾詞2017-12-19
- 也談ASProtect 1.3之stolen code的修復2015-11-15
- CSS之樣式無效BUG的修復2024-05-15CSS
- 熱修復與外掛化基礎——dex與class2018-05-13
- Android 安全之如何反編譯與加密apk包2017-02-15Android編譯加密APK
- Android安全之如何反編譯與加密apk包2017-02-15Android編譯加密APK