APK加固之类抽取分析与修复

编程入门 行业动态 更新时间:2024-10-07 18:25:53

<a href=https://www.elefans.com/category/jswz/34/1768561.html style=APK加固之类抽取分析与修复"/>

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中的d1函数主要功能是: 获得系统版本号->验证加固前后的签名是否一致->反调试->将抽走的指令映射到内存中还原指令时用到->HOOK函数dvmResolveClass->结束

代码流程如下:

 libedog.so:5D692C18             Java_com_edog_ELibrary_d1libedog.so:5D692C18libedog.so:5D692C18             var_F0= -0xF0libedog.so:5D692C18             var_EC= -0xEClibedog.so:5D692C18             var_E4= -0xE4libedog.so:5D692C18             var_1C= -0x1Clibedog.so:5D692C18             arg_0=  0libedog.so:5D692C18libedog.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, #0xDClibedog.so:5D692C1E 00 93       STR             R3, [SP,#0xF0+var_F0]libedog.so:5D692C20 7F 44       ADD             R7, PC ; dword_5D6A5E60libedog.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, R0libedog.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, #0xA9libedog.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, #2libedog.so:5D692C34 22 4D       LDR             R5, =(aFjFj0fjFjFj4fj - 0x5D692C42)libedog.so:5D692C36 5B 58       LDR             R3, [R3,R1]libedog.so:5D692C38 11 1C       MOVS            R1, R2libedog.so:5D692C3A 00 22       MOVS            R2, #0libedog.so:5D692C3C 98 47       BLX             R3libedog.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, R4libedog.so:5D692C48 00 F0 5C F8 BL              _Z17ANDROID_API_LEVELP7_JNIEnvlibedog.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, R4libedog.so:5D692C54 00 F0 82 F8 BL              _Z24ANDROID_PLATFORM_VERSIONP7_JNIEnvlibedog.so:5D692C58 20 1C       MOVS            R0, R4libedog.so:5D692C5A 00 F0 A9 F8 BL              _Z22ANDROID_PLATFORM_MODELP7_JNIEnvlibedog.so:5D692C5E 20 1C       MOVS            R0, R4libedog.so:5D692C60 00 F0 D0 F8 BL              _Z22ANDROID_PLATFORM_BRANDP7_JNIEnvlibedog.so:5D692C64 20 1C       MOVS            R0, R4libedog.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_E4libedog.so:5D692C72 79 44       ADD             R1, PC                  ; "/data/data/%s/lib/libfdog.so"libedog.so:5D692C74 FF F7 B0 EE BLX             sprintflibedog.so:5D692C78 03 A8       ADD             R0, SP, #0xF0+var_E4libedog.so:5D692C7A 01 1C       MOVS            R1, R0libedog.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, #0x2A4libedog.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, R4libedog.so:5D692C90 00 22       MOVS            R2, #0libedog.so:5D692C92 98 47       BLX             R3libedog.so:5D692C94 0D 49       LDR             R1, =(unk_5D6A2A0D - 0x5D692C9A)libedog.so:5D692C96 79 44       ADD             R1, PClibedog.so:5D692C98 FF F7 A4 EE BLX             strstrlibedog.so:5D692C9C 00 28       CMP             R0, #0libedog.so:5D692C9E 02 D1       BNE             loc_5D692CA6libedog.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:5D692CA6libedog.so:5D692CA6             loc_5D692CA6                            ; CODE XREF: Java_com_edog_ELibrary_d1+86jlibedog.so:5D692CA6 01 20       MOVS            R0, #1libedog.so:5D692CA8libedog.so:5D692CA8             loc_5D692CA8                            ; CODE XREF: Java_com_edog_ELibrary_d1+8Cjlibedog.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, R3libedog.so:5D692CB2 01 D0       BEQ             loc_5D692CB8libedog.so:5D692CB4 FF F7 9C EE BLX             sub_5D6929F0libedog.so:5D692CB8             ; ---------------------------------------------------------------------------libedog.so:5D692CB8libedog.so:5D692CB8             loc_5D692CB8                            ; CODE XREF: Java_com_edog_ELibrary_d1+9Ajlibedog.so:5D692CB8 37 B0       ADD             SP, SP, #0xDClibedog.so:5D692CBA F0 BD       POP             {R4-R7,PC}libedog.so:5D692CBA             ; End of function Java_com_edog_ELibrary_d1libedog.so:5D692CBAlibedog.so:5D692CBA             ; -------------------------------------

0x03 指令还原算法分析

原始指令还原时机就是在dvmResolveClass的hook函数中对对指令进行解密还原,以下结构的中的几个值会用到,因为被保护后的方法中的 debugInfoOff的值被修改成从0x20000000开始的一个值,该值在指令还原时起到重要作用。

struct DexCode {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字节数做为密钥,一直循环到解密完成。

代码流程如下

 libedog.so:5D693144libedog.so:5D693144             _Z13restoreMethodP11ClassObjectP6Method ; CODE XREF: _Z10replaceFunP11ClassObjectjb+22plibedog.so:5D693144                                                     ; _Z10replaceFunP11ClassObjectjb+3Aplibedog.so:5D693144libedog.so:5D693144             var_34= -0x34libedog.so:5D693144             Debug_info= -0x30libedog.so:5D693144             var_2C= -0x2Clibedog.so:5D693144             codeSize= -0x28libedog.so:5D693144             data= -0x24libedog.so:5D693144             codeoffset= -0x1Clibedog.so:5D693144libedog.so:5D693144 F0 B5       PUSH            {R4-R7,LR}libedog.so:5D693146 89 B0       SUB             SP, SP, #0x24libedog.so:5D693148 0F 1E       SUBS            R7, R1, #0libedog.so:5D69314A 5C D0       BEQ             loc_5D693206libedog.so:5D69314C 84 69       LDR             R4, [R0,#0x18]libedog.so:5D69314E 00 2C       CMP             R4, #0libedog.so:5D693150 59 D0       BEQ             loc_5D693206libedog.so:5D693152 20 1C       MOVS            R0, R4libedog.so:5D693154 4C 21       MOVS            R1, #'L'libedog.so:5D693156 FF F7 A0 EC BLX             strchrlibedog.so:5D69315A 00 28       CMP             R0, #0libedog.so:5D69315C 53 D0       BEQ             loc_5D693206libedog.so:5D69315E 3E 6A       LDR             R6, [R7,#0x20]libedog.so:5D693160 00 2E       CMP             R6, #0libedog.so:5D693162 50 D0       BEQ             loc_5D693206libedog.so:5D693164 35 1C       MOVS            R5, R6libedog.so:5D693166 10 3D       SUBS            R5, #0x10libedog.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, =0x1FFFFFFFlibedog.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_5D693206libedog.so:5D69317C 24 49       LDR             R1, =(aLandroid - 0x5D693184)libedog.so:5D69317E 20 1C       MOVS            R0, R4libedog.so:5D693180 79 44       ADD             R1, PC                  ; "Landroid/"libedog.so:5D693182 FF F7 30 EC BLX             strstr                  ; 是系统的类就跳过libedog.so:5D693186 00 28       CMP             R0, #0libedog.so:5D693188 3D D1       BNE             loc_5D693206libedog.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, #0libedog.so:5D693190 39 D1       BNE             loc_5D693206libedog.so:5D693192 20 4B       LDR             R3, =(aFjFj0fjFjFj4fj+0xC - 0x5D69319C)libedog.so:5D693194 07 A8       ADD             R0, SP, #0x38+codeoffsetlibedog.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, #8libedog.so:5D6931A6 89 09       LSRS            R1, R1, #6libedog.so:5D6931A8 89 18       ADDS            R1, R1, R2libedog.so:5D6931AA 04 22       MOVS            R2, #4libedog.so:5D6931AC FF F7 68 EC BLX             memcpy_0libedog.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, #2libedog.so:5D6931B6 08 34       ADDS            R4, #8libedog.so:5D6931B8 E4 18       ADDS            R4, R4, R3libedog.so:5D6931BA 13 1C       MOVS            R3, R2libedog.so:5D6931BC 01 33       ADDS            R3, #1libedog.so:5D6931BE 9B 00       LSLS            R3, R3, #2libedog.so:5D6931C0 E4 18       ADDS            R4, R4, R3libedog.so:5D6931C2 64 00       LSLS            R4, R4, #1libedog.so:5D6931C4 20 1C       MOVS            R0, R4libedog.so:5D6931C6 FF F7 26 EC BLX             malloclibedog.so:5D6931CA 22 1C       MOVS            R2, R4libedog.so:5D6931CC 06 1C       MOVS            R6, R0libedog.so:5D6931CE 01 99       LDR             R1, [SP,#0x38+var_34]libedog.so:5D6931D0 FF F7 5C EC BLX             memset_0libedog.so:5D6931D4 29 1C       MOVS            R1, R5libedog.so:5D6931D6 22 1C       MOVS            R2, R4libedog.so:5D6931D8 30 1C       MOVS            R0, R6libedog.so:5D6931DA FF F7 52 EC BLX             memcpy_0libedog.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, #1libedog.so:5D6931E6 02 98       LDR             R0, [SP,#0x38+Debug_info]libedog.so:5D6931E8 51 18       ADDS            R1, R2, R1libedog.so:5D6931EA 01 23       MOVS            R3, #1libedog.so:5D6931EC 2A 1C       MOVS            R2, R5libedog.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, R6libedog.so:5D6931F6 10 34       ADDS            R4, #0x10libedog.so:5D6931F8 01 1C       MOVS            R1, R0libedog.so:5D6931FA B3 60       STR             R3, [R6,#8]             ; 清空Debug_infolibedog.so:5D6931FC 20 1C       MOVS            R0, R4libedog.so:5D6931FE 2A 1C       MOVS            R2, R5libedog.so:5D693200 FF F7 3E EC BLX             memcpy_0                ; 还原指令libedog.so:5D693204 3C 62       STR             R4, [R7,#0x20]libedog.so:5D693206libedog.so:5D693206             loc_5D693206                            ; CODE XREF: _Z13restoreMethodP11ClassObjectP6Method+6jlibedog.so:5D693206                                                     ; _Z13restoreMethodP11ClassObjectP6Method+Cj ...libedog.so:5D693206 09 B0       ADD             SP, SP, #0x24libedog.so:5D693208 F0 BD       POP             {R4-R7,PC}libedog.so:5D693208             ; End of function _Z13restoreMethodP1解密指令libedog.so:5D69502Clibedog.so:5D69502C             dbone_crypt_ins                         ; CODE XREF: _Z13restoreMethodP11ClassObjectP6Method+AAplibedog.so:5D69502Clibedog.so:5D69502C             DecMode= -0x1Clibedog.so:5D69502C             codeSize= -0x18libedog.so:5D69502C             codedata= -0x14libedog.so:5D69502C             key= -0x10libedog.so:5D69502C             crckey= -8libedog.so:5D69502Clibedog.so:5D69502C 00 48 2D E9 STMFD           SP!, {R11,LR}libedog.so:5D695030 04 B0 8D E2 ADD             R11, SP, #4libedog.so:5D695034 18 D0 4D E2 SUB             SP, SP, #0x18libedog.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]      ; 1libedog.so:5D695048 10 30 4B E2 SUB             R3, R11, #-keylibedog.so:5D69504C 03 00 A0 E1 MOV             R0, R3libedog.so:5D695050 04 10 A0 E3 MOV             R1, #4libedog.so:5D695054 47 01 00 EB BL              _Z5crc32Phjlibedog.so:5D695058 00 30 A0 E1 MOV             R3, R0libedog.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, #1libedog.so:5D695068 06 00 00 1A BNE             loc_5D695088libedog.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, R2libedog.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_jlibedog.so:5D695084 0D 00 00 EA B               loc_5D6950C0libedog.so:5D695088             ; ---------------------------------------------------------------------------libedog.so:5D695088libedog.so:5D695088             loc_5D695088                            ; CODE XREF: dbone_crypt_ins+3Cjlibedog.so:5D695088 1C 30 1B E5 LDR             R3, [R11,#DecMode]libedog.so:5D69508C 00 00 53 E3 CMP             R3, #0libedog.so:5D695090 06 00 00 1A BNE             loc_5D6950B0libedog.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, R2libedog.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_jlibedog.so:5D6950AC 03 00 00 EA B               loc_5D6950C0libedog.so:5D6950B0             ; ---------------------------------------------------------------------------libedog.so:5D6950B0libedog.so:5D6950B0             loc_5D6950B0                            ; CODE XREF: dbone_crypt_ins+64jlibedog.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, R3libedog.so:5D6950BC 99 F6 FF EB BL              putslibedog.so:5D6950C0libedog.so:5D6950C0             loc_5D6950C0                            ; CODE XREF: dbone_crypt_ins+58jlibedog.so:5D6950C0                                                     ; dbone_crypt_ins+80jlibedog.so:5D6950C0 14 30 1B E5 LDR             R3, [R11,#codedata]libedog.so:5D6950C4 03 00 A0 E1 MOV             R0, R3libedog.so:5D6950C8 04 D0 4B E2 SUB             SP, R11, #4libedog.so:5D6950CC 00 88 BD E8 LDMFD           SP!, {R11,PC}libedog.so:5D6950CC             ; End of function dbone_crypt_inslibedog.so:5D6950CClibedog.so:5D6950CC             ; -------------//循环解密libedog.so:5D695288             _Z8XorArrayjPhS_j                       ; CODE XREF: dbone_crypt_file+180plibedog.so:5D695288                                                     ; dbone_crypt_ins+54plibedog.so:5D695288libedog.so:5D695288             codeSize= -0x24libedog.so:5D695288             codedata1= -0x20libedog.so:5D695288             codedata= -0x1Clibedog.so:5D695288             crckey= -0x18libedog.so:5D695288             crckey1= -0x14libedog.so:5D695288             crckeyaddr= -0x10libedog.so:5D695288             crckeyindex= -0xClibedog.so:5D695288             index= -8libedog.so:5D695288libedog.so:5D695288 00 48 2D E9 STMFD           SP!, {R11,LR}libedog.so:5D69528C 04 B0 8D E2 ADD             R11, SP, #4libedog.so:5D695290 20 D0 4D E2 SUB             SP, SP, #0x20libedog.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, #-crckey1libedog.so:5D6952B0 10 30 0B E5 STR             R3, [R11,#crckeyaddr]libedog.so:5D6952B4 00 30 A0 E3 MOV             R3, #0libedog.so:5D6952B8 08 30 0B E5 STR             R3, [R11,#index]libedog.so:5D6952BC 00 30 A0 E3 MOV             R3, #0libedog.so:5D6952C0 0C 30 0B E5 STR             R3, [R11,#crckeyindex]libedog.so:5D6952C4 00 30 A0 E3 MOV             R3, #0libedog.so:5D6952C8 08 30 0B E5 STR             R3, [R11,#index]libedog.so:5D6952CC 1E 00 00 EA B               loc_5D69534Clibedog.so:5D6952D0             ; ---------------------------------------------------------------------------libedog.so:5D6952D0libedog.so:5D6952D0             loc_5D6952D0                            ; CODE XREF: _Z8XorArrayjPhS_j+E0jlibedog.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, R3libedog.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, R2libedog.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, R2libedog.so:5D6952F8 00 20 D2 E5 LDRB            R2, [R2]libedog.so:5D6952FC 02 20 21 E0 EOR             R2, R1, R2libedog.so:5D695300 FF 20 02 E2 AND             R2, R2, #0xFFlibedog.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_5D695334libedog.so:5D695314 14 30 1B E5 LDR             R3, [R11,#crckey1]libedog.so:5D695318 03 00 A0 E1 MOV             R0, R3libedog.so:5D69531C 6C FF FF EB BL              _Z10PolyXorKeyjlibedog.so:5D695320 00 30 A0 E1 MOV             R3, R0libedog.so:5D695324 14 30 0B E5 STR             R3, [R11,#crckey1]libedog.so:5D695328 00 30 A0 E3 MOV             R3, #0libedog.so:5D69532C 0C 30 0B E5 STR             R3, [R11,#crckeyindex]libedog.so:5D695330 02 00 00 EA B               loc_5D695340libedog.so:5D695334             ; ---------------------------------------------------------------------------libedog.so:5D695334libedog.so:5D695334             loc_5D695334                            ; CODE XREF: _Z8XorArrayjPhS_j+88jlibedog.so:5D695334 0C 30 1B E5 LDR             R3, [R11,#crckeyindex]libedog.so:5D695338 01 30 83 E2 ADD             R3, R3, #1libedog.so:5D69533C 0C 30 0B E5 STR             R3, [R11,#crckeyindex]libedog.so:5D695340libedog.so:5D695340             loc_5D695340                            ; CODE XREF: _Z8XorArrayjPhS_j+A8jlibedog.so:5D695340 08 30 1B E5 LDR             R3, [R11,#index]libedog.so:5D695344 01 30 83 E2 ADD             R3, R3, #1libedog.so:5D695348 08 30 0B E5 STR             R3, [R11,#index]libedog.so:5D69534Clibedog.so:5D69534C             loc_5D69534C                            ; CODE XREF: _Z8XorArrayjPhS_j+44jlibedog.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, R3libedog.so:5D695358 00 30 A0 D3 MOVLE           R3, #0libedog.so:5D69535C 01 30 A0 C3 MOVGT           R3, #1libedog.so:5D695360 FF 30 03 E2 AND             R3, R3, #0xFFlibedog.so:5D695364 00 00 53 E3 CMP             R3, #0libedog.so:5D695368 D8 FF FF 1A BNE             loc_5D6952D0libedog.so:5D69536C 04 D0 4B E2 SUB             SP, R11, #4libedog.so:5D695370 00 88 BD E8 LDMFD           SP!, {R11,PC}libedog.so:5D695370             ; End of function _Z8XorArrayjPhS_jlibedog.so:5D695370libedog.so:5D695374libedog.so:5D695374             ; =============== S U B R O U T

0x04 编写修复程序

         修复程序主要分为解析dex与解密两个步骤来完成,这里只贴出部分代码详细的请看工程,代码写得比较粗操,看下思路就行了,有性趣的就慢慢撸吧!

Shelling.cpp

// Shelling.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include "crc32.h"
#include "dexFile.h"int _tmain(int argc, _TCHAR* argv[])
{initDex("classes.dex");fixdexClassData();Uninit();printf("======================修复完成!!!!========\n");return 0;
}

 dexFile.h

#ifndef LIBDEX_DEXFILE_H_
#define LIBDEX_DEXFILE_H_typedef unsigned long u4;
typedef unsigned short u2;
typedef unsigned char u1;/* DEX file magic number */
#define DEX_MAGIC       "dex\n"/* current version, encoded in 4 bytes of ASCII */
#define DEX_MAGIC_VERS  "036\0"/** older but still-recognized version (corresponding to Android API* levels 13 and earlier*/
#define DEX_MAGIC_VERS_API_13  "035\0"/* same, but for optimized DEX header */
#define DEX_OPT_MAGIC   "dey\n"
#define DEX_OPT_MAGIC_VERS  "036\0"#define DEX_DEP_MAGIC   "deps"/** 160-bit SHA-1 digest.*/
enum { kSHA1DigestLen = 20,kSHA1DigestOutputLen = kSHA1DigestLen*2 +1 };/* general constants */
enum {kDexEndianConstant = 0x12345678,    /* the endianness indicator */kDexNoIndex = 0xffffffff,           /* not a valid index value */
};/** Enumeration of all the primitive types.*/
enum PrimitiveType {PRIM_NOT        = 0,       /* value is a reference type, not a primitive type */PRIM_VOID       = 1,PRIM_BOOLEAN    = 2,PRIM_BYTE       = 3,PRIM_SHORT      = 4,PRIM_CHAR       = 5,PRIM_INT        = 6,PRIM_LONG       = 7,PRIM_FLOAT      = 8,PRIM_DOUBLE     = 9,
};/** access flags and masks; the "standard" ones are all <= 0x4000** Note: There are related declarations in vm/oo/Object.h in the ClassFlags* enum.*/
enum {ACC_PUBLIC       = 0x00000001,       // class, field, method, icACC_PRIVATE      = 0x00000002,       // field, method, icACC_PROTECTED    = 0x00000004,       // field, method, icACC_STATIC       = 0x00000008,       // field, method, icACC_FINAL        = 0x00000010,       // class, field, method, icACC_SYNCHRONIZED = 0x00000020,       // method (only allowed on natives)ACC_SUPER        = 0x00000020,       // class (not used in Dalvik)ACC_VOLATILE     = 0x00000040,       // fieldACC_BRIDGE       = 0x00000040,       // method (1.5)ACC_TRANSIENT    = 0x00000080,       // fieldACC_VARARGS      = 0x00000080,       // method (1.5)ACC_NATIVE       = 0x00000100,       // methodACC_INTERFACE    = 0x00000200,       // class, icACC_ABSTRACT     = 0x00000400,       // class, method, icACC_STRICT       = 0x00000800,       // methodACC_SYNTHETIC    = 0x00001000,       // field, method, icACC_ANNOTATION   = 0x00002000,       // class, ic (1.5)ACC_ENUM         = 0x00004000,       // class, field, ic (1.5)ACC_CONSTRUCTOR  = 0x00010000,       // method (Dalvik only)ACC_DECLARED_SYNCHRONIZED =0x00020000,       // method (Dalvik only)ACC_CLASS_MASK =(ACC_PUBLIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT| ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),ACC_INNER_CLASS_MASK =(ACC_CLASS_MASK | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC),ACC_FIELD_MASK =(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL| ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM),ACC_METHOD_MASK =(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL| ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE| ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR| ACC_DECLARED_SYNCHRONIZED),
};/* annotation constants */
enum {kDexVisibilityBuild         = 0x00,     /* annotation visibility */kDexVisibilityRuntime       = 0x01,kDexVisibilitySystem        = 0x02,kDexAnnotationByte          = 0x00,kDexAnnotationShort         = 0x02,kDexAnnotationChar          = 0x03,kDexAnnotationInt           = 0x04,kDexAnnotationLong          = 0x06,kDexAnnotationFloat         = 0x10,kDexAnnotationDouble        = 0x11,kDexAnnotationString        = 0x17,kDexAnnotationType          = 0x18,kDexAnnotationField         = 0x19,kDexAnnotationMethod        = 0x1a,kDexAnnotationEnum          = 0x1b,kDexAnnotationArray         = 0x1c,kDexAnnotationAnnotation    = 0x1d,kDexAnnotationNull          = 0x1e,kDexAnnotationBoolean       = 0x1f,kDexAnnotationValueTypeMask = 0x1f,     /* low 5 bits */kDexAnnotationValueArgShift = 5,
};/* map item type codes */
enum {kDexTypeHeaderItem               = 0x0000,kDexTypeStringIdItem             = 0x0001,kDexTypeTypeIdItem               = 0x0002,kDexTypeProtoIdItem              = 0x0003,kDexTypeFieldIdItem              = 0x0004,kDexTypeMethodIdItem             = 0x0005,kDexTypeClassDefItem             = 0x0006,kDexTypeMapList                  = 0x1000,kDexTypeTypeList                 = 0x1001,kDexTypeAnnotationSetRefList     = 0x1002,kDexTypeAnnotationSetItem        = 0x1003,kDexTypeClassDataItem            = 0x2000,kDexTypeCodeItem                 = 0x2001,kDexTypeStringDataItem           = 0x2002,kDexTypeDebugInfoItem            = 0x2003,kDexTypeAnnotationItem           = 0x2004,kDexTypeEncodedArrayItem         = 0x2005,kDexTypeAnnotationsDirectoryItem = 0x2006,
};/* auxillary data section chunk codes */
enum {kDexChunkClassLookup            = 0x434c4b50,   /* CLKP */kDexChunkRegisterMaps           = 0x524d4150,   /* RMAP */kDexChunkEnd                    = 0x41454e44,   /* AEND */
};/* debug info opcodes and constants */
enum {DBG_END_SEQUENCE         = 0x00,DBG_ADVANCE_PC           = 0x01,DBG_ADVANCE_LINE         = 0x02,DBG_START_LOCAL          = 0x03,DBG_START_LOCAL_EXTENDED = 0x04,DBG_END_LOCAL            = 0x05,DBG_RESTART_LOCAL        = 0x06,DBG_SET_PROLOGUE_END     = 0x07,DBG_SET_EPILOGUE_BEGIN   = 0x08,DBG_SET_FILE             = 0x09,DBG_FIRST_SPECIAL        = 0x0a,DBG_LINE_BASE            = -4,DBG_LINE_RANGE           = 15,
};/** Direct-mapped "header_item" struct.*/
struct DexHeader {u1  magic[8];           /* includes version number */u4  checksum;           /* adler32 checksum */u1  signature[kSHA1DigestLen]; /* SHA-1 hash */u4  fileSize;           /* length of entire file */u4  headerSize;         /* offset to start of next section */u4  endianTag;u4  linkSize;u4  linkOff;u4  mapOff;u4  stringIdsSize;u4  stringIdsOff;u4  typeIdsSize;u4  typeIdsOff;u4  protoIdsSize;u4  protoIdsOff;u4  fieldIdsSize;u4  fieldIdsOff;u4  methodIdsSize;u4  methodIdsOff;u4  classDefsSize;u4  classDefsOff;u4  dataSize;u4  dataOff;
};/** Direct-mapped "map_item".*/
struct DexMapItem {u2 type;              /* type code (see kDexType* above) */u2 unused;u4 size;              /* count of items of the indicated type */u4 offset;            /* file offset to the start of data */
};/** Direct-mapped "map_list".*/
struct DexMapList {u4  size;               /* #of entries in list */DexMapItem list[1];     /* entries */
};/** Direct-mapped "string_id_item".*/
struct DexStringId {u4 stringDataOff;      /* file offset to string_data_item */
};/** Direct-mapped "type_id_item".*/
struct DexTypeId {u4  descriptorIdx;      /* index into stringIds list for type descriptor */
};/** Direct-mapped "field_id_item".*/
struct DexFieldId {u2  classIdx;           /* index into typeIds list for defining class */u2  typeIdx;            /* index into typeIds for field type */u4  nameIdx;            /* index into stringIds for field name */
};/** Direct-mapped "method_id_item".*/
struct DexMethodId {u2  classIdx;           /* index into typeIds list for defining class */u2  protoIdx;           /* index into protoIds for method prototype */u4  nameIdx;            /* index into stringIds for method name */
};/** Direct-mapped "proto_id_item".*/
struct DexProtoId {u4  shortyIdx;          /* index into stringIds for shorty descriptor */u4  returnTypeIdx;      /* index into typeIds list for return type */u4  parametersOff;      /* file offset to type_list for parameter types */
};/** Direct-mapped "class_def_item".*/
struct DexClassDef {u4  classIdx;           /* index into typeIds for this class */u4  accessFlags;u4  superclassIdx;      /* index into typeIds for superclass */u4  interfacesOff;      /* file offset to DexTypeList */u4  sourceFileIdx;      /* index into stringIds for source file name */u4  annotationsOff;     /* file offset to annotations_directory_item */u4  classDataOff;       /* file offset to class_data_item */u4  staticValuesOff;    /* file offset to DexEncodedArray */
};/** Direct-mapped "type_item".*/
struct DexTypeItem {u2  typeIdx;            /* index into typeIds */
};/** Direct-mapped "type_list".*/
struct DexTypeList {u4  size;               /* #of entries in list */DexTypeItem list[1];    /* entries */
};/** Direct-mapped "code_item".** The "catches" table is used when throwing an exception,* "debugInfo" is used when displaying an exception stack trace or* debugging. An offset of zero indicates that there are no entries.*/
struct DexCode {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];/* followed by optional u2 padding *//* followed by try_item[triesSize] *//* followed by uleb128 handlersSize *//* followed by catch_handler_item[handlersSize] */
};/** Direct-mapped "try_item".*/
struct DexTry {u4  startAddr;          /* start address, in 16-bit code units */u2  insnCount;          /* instruction count, in 16-bit code units */u2  handlerOff;         /* offset in encoded handler data to handlers */
};/** Link table.  Currently undefined.*/
struct DexLink {u1  bleargh;
};/** Direct-mapped "annotations_directory_item".*/
struct DexAnnotationsDirectoryItem {u4  classAnnotationsOff;  /* offset to DexAnnotationSetItem */u4  fieldsSize;           /* count of DexFieldAnnotationsItem */u4  methodsSize;          /* count of DexMethodAnnotationsItem */u4  parametersSize;       /* count of DexParameterAnnotationsItem *//* followed by DexFieldAnnotationsItem[fieldsSize] *//* followed by DexMethodAnnotationsItem[methodsSize] *//* followed by DexParameterAnnotationsItem[parametersSize] */
};/** Direct-mapped "field_annotations_item".*/
struct DexFieldAnnotationsItem {u4  fieldIdx;u4  annotationsOff;             /* offset to DexAnnotationSetItem */
};/** Direct-mapped "method_annotations_item".*/
struct DexMethodAnnotationsItem {u4  methodIdx;u4  annotationsOff;             /* offset to DexAnnotationSetItem */
};/** Direct-mapped "parameter_annotations_item".*/
struct DexParameterAnnotationsItem {u4  methodIdx;u4  annotationsOff;             /* offset to DexAnotationSetRefList */
};/** Direct-mapped "annotation_set_ref_item".*/
struct DexAnnotationSetRefItem {u4  annotationsOff;             /* offset to DexAnnotationSetItem */
};/** Direct-mapped "annotation_set_ref_list".*/
struct DexAnnotationSetRefList {u4  size;DexAnnotationSetRefItem list[1];
};/** Direct-mapped "annotation_set_item".*/
struct DexAnnotationSetItem {u4  size;u4  entries[1];                 /* offset to DexAnnotationItem */
};/** Direct-mapped "annotation_item".** NOTE: this structure is byte-aligned.*/
struct DexAnnotationItem {u1  visibility;u1  annotation[1];              /* data in encoded_annotation format */
};/** Direct-mapped "encoded_array".** NOTE: this structure is byte-aligned.*/
struct DexEncodedArray {u1  array[1];                   /* data in encoded_array format */
};/** Lookup table for classes.  It provides a mapping from class name to* class definition.  Used by dexFindClass().** We calculate this at DEX optimization time and embed it in the file so we* don't need the same hash table in every VM.  This is slightly slower than* a hash table with direct pointers to the items, but because it's shared* there's less of a penalty for using a fairly sparse table.*/
struct DexClassLookup {int     size;                       // total size, including "size"int     numEntries;                 // size of table[]; always power of 2struct {u4      classDescriptorHash;    // class descriptor hash codeint     classDescriptorOffset;  // in bytes, from start of DEXint     classDefOffset;         // in bytes, from start of DEX} table[1];
};/** Header added by DEX optimization pass.  Values are always written in* local byte and structure padding.  The first field (magic + version)* is guaranteed to be present and directly readable for all expected* compiler configurations; the rest is version-dependent.** Try to keep this simple and fixed-size.*/
struct DexOptHeader {u1  magic[8];           /* includes version number */u4  dexOffset;          /* file offset of DEX header */u4  dexLength;u4  depsOffset;         /* offset of optimized DEX dependency table */u4  depsLength;u4  optOffset;          /* file offset of optimized data tables */u4  optLength;u4  flags;              /* some info flags */u4  checksum;           /* adler32 checksum covering deps/opt *//* pad for 64-bit alignment if necessary */
};#define DEX_OPT_FLAG_BIG            (1<<1)  /* swapped to big-endian */#define DEX_INTERFACE_CACHE_SIZE    128     /* must be power of 2 *//** Structure representing a DEX file.** Code should regard DexFile as opaque, using the API calls provided here* to access specific structures.*/
struct DexFile {/* directly-mapped "opt" header */const DexOptHeader* pOptHeader;/* pointers to directly-mapped structs and arrays in base DEX */const DexHeader*    pHeader;const DexStringId*  pStringIds;const DexTypeId*    pTypeIds;const DexFieldId*   pFieldIds;const DexMethodId*  pMethodIds;const DexProtoId*   pProtoIds;const DexClassDef*  pClassDefs;const DexLink*      pLinkData;/** These are mapped out of the "auxillary" section, and may not be* included in the file.*/const DexClassLookup* pClassLookup;const void*         pRegisterMapPool;       // RegisterMapClassPool/* points to start of DEX file data */const u1*           baseAddr;/* track memory overhead for auxillary structures */int                 overhead;/* additional app-specific data structures associated with the DEX *///void*               auxData;
};/* expanded form of a class_data_item header */
struct DexClassDataHeader {u4 staticFieldsSize;u4 instanceFieldsSize;u4 directMethodsSize;u4 virtualMethodsSize;
};/* expanded form of encoded_field */
struct DexField {u4 fieldIdx;    /* index to a field_id_item */u4 accessFlags;
};/* expanded form of encoded_method */
struct DexMethod {u4 methodIdx;    /* index to a method_id_item */u4 accessFlags;u4 codeOff;      /* file offset to a code_item */
};/* expanded form of class_data_item. Note: If a particular item is* absent (e.g., no static fields), then the corresponding pointer* is set to NULL. */
struct DexClassData {DexClassDataHeader header;DexField*          staticFields;DexField*          instanceFields;DexMethod*         directMethods;DexMethod*         virtualMethods;
};#endifvoid fixdexClassData();void initDex(char* DexFileName);
void Uninit();
dexFile.cpp
// FindDexCode.cpp : Defines the entry point for the console application.
//
#pragma once
#include "stdafx.h"
#include "dexFile.h"
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include "Dec.h"//DexFile* pDexFile;
HANDLE hMapFile;
HANDLE hFile;
LPVOID lpMapAddress;
DWORD dexsize;DexFile gDexFile;
u1* gCodeData = NULL;void initDex(char* DexFileName)
{hFile = CreateFile(DexFileName, GENERIC_READ | GENERIC_WRITE,0, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE){printf("hFile is NULL\n");printf("Target file is %s\n", DexFileName);return ;}dexsize = GetFileSize(hFile, NULL);hMapFile = CreateFileMapping( hFile,         // current file handleNULL,           // default securityPAGE_READWRITE, // read/write permission0,              // size of mapping object, highdexsize,  // size of mapping object, lowNULL);          // name of mapping objectif (hMapFile == NULL) {printf("hMapFile is NULL: last error: %d\n", GetLastError() );return;}// Map the view and test the results.lpMapAddress = MapViewOfFile(hMapFile,            // handle to // mapping objectFILE_MAP_ALL_ACCESS, // read/write 0,                   // high-order 32 // bits of file // offset0,      // low-order 32// bits of file // offsetdexsize);      // number of bytes// to mapif (lpMapAddress == NULL) {printf("lpMapAddress is NULL: last error: %d\n", GetLastError());return ;}// pDexFile = new DexFile;void *dexBase = lpMapAddress;DexHeader *dexHeader = (DexHeader *)dexBase;gDexFile.baseAddr   = (u1*)dexBase;gDexFile.pHeader    = dexHeader;gDexFile.pStringIds = (DexStringId*)((u4)dexBase+dexHeader->stringIdsOff);gDexFile.pTypeIds   = (DexTypeId*)((u4)dexBase+dexHeader->typeIdsOff);gDexFile.pMethodIds = (DexMethodId*)((u4)dexBase+dexHeader->methodIdsOff);gDexFile.pFieldIds  = (DexFieldId*)((u4)dexBase+dexHeader->fieldIdsOff);gDexFile.pClassDefs = (DexClassDef*)((u4)dexBase+dexHeader->classDefsOff);gDexFile.pProtoIds  = (DexProtoId*)((u4)dexBase+dexHeader->protoIdsOff);}void Uninit()
{UnmapViewOfFile(lpMapAddress);CloseHandle(hFile);if (NULL != gCodeData){free(gCodeData);gCodeData = NULL;}
}//-------------------------------------------------static void getAccessFlags(char *buf, int flags)
{if((flags & ACC_PUBLIC) != 0)   strcat(buf, "public ");if((flags & ACC_PRIVATE) != 0)   strcat(buf, "private ");if((flags & ACC_PROTECTED) != 0)   strcat(buf, "protected ");    if((flags & ACC_STATIC) != 0)   strcat(buf, "static ");    if((flags & ACC_FINAL) != 0)   strcat(buf, "final ");    if((flags & ACC_SYNCHRONIZED) != 0)   strcat(buf, "synchronized ");    if((flags & ACC_SUPER) != 0)   strcat(buf, "super ");    if((flags & ACC_VOLATILE) != 0)   strcat(buf, "volatile ");    if((flags & ACC_BRIDGE) != 0)   strcat(buf, "bridge ");    if((flags & ACC_TRANSIENT) != 0)   strcat(buf, "transient ");    if((flags & ACC_VARARGS) != 0)   strcat(buf, "varargs ");    if((flags & ACC_NATIVE) != 0)   strcat(buf, "native ");    if((flags & ACC_INTERFACE) != 0)   strcat(buf, "interface ");    if((flags & ACC_ABSTRACT) != 0)   strcat(buf, "abstract ");    if((flags & ACC_STRICT) != 0)   strcat(buf, "strict ");    if((flags & ACC_SYNTHETIC) != 0)   strcat(buf, "synthetic ");    if((flags & ACC_ANNOTATION) != 0)   strcat(buf, "annotation ");    if((flags & ACC_ENUM) != 0)   strcat(buf, "enum ");    if((flags & ACC_CONSTRUCTOR) != 0)   strcat(buf, "constructor ");    if((flags & ACC_DECLARED_SYNCHRONIZED) != 0)   strcat(buf, "synchronize ");    
}static int readUnsignedLeb128(const u1** pStream) {const u1* ptr = *pStream;int result = *(ptr++);if (result > 0x7f) {int cur = *(ptr++);result = (result & 0x7f) | ((cur & 0x7f) << 7);if (cur > 0x7f) {cur = *(ptr++);result |= (cur & 0x7f) << 14;if (cur > 0x7f) {cur = *(ptr++);result |= (cur & 0x7f) << 21;if (cur > 0x7f) {/** Note: We don't check to see if cur is out of* range here, meaning we tolerate garbage in the* high four-order bits.*/cur = *(ptr++);result |= cur << 28;}}}}*pStream = ptr;return result;
}static  DexCode* dexGetCode(DexFile* pDexFile,const DexMethod* pDexMethod)
{if (pDexMethod->codeOff == 0)return NULL;return (DexCode*) (pDexFile->baseAddr + pDexMethod->codeOff);
}/* return the ClassDef with the specified index */
static const DexClassDef* dexGetClassDef(const DexFile* pDexFile, u4 idx) {assert(idx < pDexFile->pHeader->classDefsSize);return &pDexFile->pClassDefs[idx];
}/* Read the header of a class_data_item without verification. This* updates the given data pointer to point past the end of the read* data. */
static void dexReadClassDataHeader(const u1** pData,DexClassDataHeader *pHeader) {pHeader->staticFieldsSize = readUnsignedLeb128(pData);pHeader->instanceFieldsSize = readUnsignedLeb128(pData);pHeader->directMethodsSize = readUnsignedLeb128(pData);pHeader->virtualMethodsSize = readUnsignedLeb128(pData);
}/* Read an encoded_field without verification. This updates the* given data pointer to point past the end of the read data.** The lastIndex value should be set to 0 before the first field in* a list is read. It is updated as fields are read and used in the* decode process.*/
static void dexReadClassDataField(const u1** pData, DexField* pField,u4* lastIndex) {u4 index = *lastIndex + readUnsignedLeb128(pData);pField->accessFlags = readUnsignedLeb128(pData);pField->fieldIdx = index;*lastIndex = index;
}/* Read an encoded_method without verification. This updates the* given data pointer to point past the end of the read data.** The lastIndex value should be set to 0 before the first method in* a list is read. It is updated as fields are read and used in the* decode process.*/
static void dexReadClassDataMethod(const u1** pData, DexMethod* pMethod,u4* lastIndex) {u4 index = *lastIndex + readUnsignedLeb128(pData);pMethod->accessFlags = readUnsignedLeb128(pData);pMethod->codeOff = readUnsignedLeb128(pData);pMethod->methodIdx = index;*lastIndex = index;
}static char *getString(const DexFile *dexFile, int id)
{return (char *)(dexFile->baseAddr + dexFile->pStringIds[id].stringDataOff+1);
}static int getTypeIdStringId(const DexFile *dexFile, int id)
{const DexTypeId *typeId = dexFile->pTypeIds;return typeId[id].descriptorIdx;
}
#define getTpyeIdString(dexFile, id) getString((dexFile), getTypeIdStringId((dexFile),(id)))static u1 *getClassDataPtr(const DexFile *dexFile, int idx)
{return (u1 *)(dexFile->baseAddr + dexFile->pClassDefs[idx].classDataOff);
}static void dumpDexHeader(DexHeader *header)
{printf("[Dex Header] headerSize:0x%08lx fileSize:0x%08lx", header->headerSize, header->fileSize);printf("[Dex Header] linkSize:0x%08lx linkOff:0x%08lx mapOff:0x%08lx", header->linkSize, header->linkOff, header->mapOff);printf("[Dex Header] StringIds   size:0x%08lx offset:0x%08lx", header->stringIdsSize, header->stringIdsOff);printf("[Dex Header] TypeIds     size:0x%08lx offset:0x%08lx", header->typeIdsSize, header->typeIdsOff);printf("[Dex Header] ProtoIds    size:0x%08lx offset:0x%08lx", header->protoIdsSize, header->protoIdsOff);printf("[Dex Header] FieldIds    size:0x%08lx offset:0x%08lx", header->fieldIdsSize, header->fieldIdsOff);printf("[Dex Header] MethodIds   size:0x%08lx offset:0x%08lx", header->methodIdsSize, header->methodIdsOff);printf("[Dex Header] ClassDefs   size:0x%08lx offset:0x%08lx", header->classDefsSize, header->classDefsOff);printf("[Dex Header] Data        size:0x%08lx offset:0x%08lx", header->dataSize, header->dataOff);
}static void dumpDexStrings(const DexFile *dexFile)
{int i =0;char *str;int count = dexFile->pHeader->stringIdsSize;for(i=0; i<count; i++){str = (char *)(dexFile->baseAddr + dexFile->pStringIds[i].stringDataOff);printf("[Strings] id=%d [%d]:%s", i, str[0], str+1);}
}static void dumpDexTypeIds(const DexFile *dexFile)
{const DexTypeId *typeId = dexFile->pTypeIds;int count = dexFile->pHeader->typeIdsSize;for(int i=0; i<count; i++){printf("[types] [%d] %s",  i, getString(dexFile, typeId[i].descriptorIdx));}
}static void dumpFieldIds(const DexFile *dexFile)
{const DexFieldId *pfield = dexFile->pFieldIds;int count = dexFile->pHeader->fieldIdsSize;for(int i=0; i<count; i++){printf("[field] %s -> %s %s",getTpyeIdString(dexFile, pfield[i].classIdx),getString(dexFile, pfield[i].nameIdx),getTpyeIdString(dexFile, pfield[i].typeIdx));}
}static void dumpDexProtos(const DexFile *dexFile)
{char buffer[1024];const DexProtoId *proto = dexFile->pProtoIds;int count = dexFile->pHeader->protoIdsSize;DexTypeList *plist;for(int i=0; i<count; i++){sprintf(buffer, "[proto] %d  short:", i);strcat(buffer, getString(dexFile, proto[i].shortyIdx));strcat(buffer, " return:");strcat(buffer, getTpyeIdString(dexFile, proto[i].returnTypeIdx));if(proto[i].parametersOff == 0){printf("%s", buffer);continue;}strcat(buffer, " param:");plist = (DexTypeList *)(dexFile->baseAddr + proto[i].parametersOff);for(u4 j=0; j<plist->size; j++){strcat(buffer, getTpyeIdString(dexFile,  plist->list[j].typeIdx));}printf("%s", buffer);}
}static void dumpClassDefines(const DexFile *dexFile)
{char buffer[1024];const DexClassDef* classdef = dexFile->pClassDefs;int count = dexFile->pHeader->classDefsSize;buffer[0] = 0;for(int i=0; i<count; i++){getAccessFlags(buffer, classdef[i].accessFlags);strcat(buffer, " class ");strcat(buffer, getTpyeIdString(dexFile, classdef[i].classIdx));strcat(buffer, " externds ");strcat(buffer, getTpyeIdString(dexFile, classdef[i].superclassIdx));strcat(buffer, " implements ");//strcat(buffer, getTpyeIdString(dexFile, classdef[i].interfacesOff);printf("%s", buffer);}}static void dumpMethodIds(const DexFile *dexFile)
{const DexMethodId *pmethod = dexFile->pMethodIds;
}static int readAndVerifyUnsignedLeb128(const u1** pStream, const u1* limit,bool* okay) {const u1* ptr = *pStream;int result = readUnsignedLeb128(pStream);if (((limit != NULL) && (*pStream > limit))|| (((*pStream - ptr) == 5) && (ptr[4] > 0x0f))) {*okay = false;}return result;
}/* Helper for verification which reads and verifies a given number* of uleb128 values. */
static bool verifyUlebs(const u1* pData, const u1* pLimit, u4 count) {bool okay = true;u4 i;while (okay && (count-- != 0)) {readAndVerifyUnsignedLeb128(&pData, pLimit, &okay);}return okay;
}/* Read and verify the header of a class_data_item. This updates the* given data pointer to point past the end of the read data and* returns an "okay" flag (that is, false == failure). */
static bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit,DexClassDataHeader *pHeader) {if (! verifyUlebs(*pData, pLimit, 4)) {return false;}dexReadClassDataHeader(pData, pHeader);/* printf("ClassHeader: field: s-%ld i-%ld method: d-%ld v-%ld", pHeader->staticFieldsSize, pHeader->instanceFieldsSize,pHeader->directMethodsSize, pHeader->staticFieldsSize);*/return true;
}/* Read and verify an encoded_field. This updates the* given data pointer to point past the end of the read data and* returns an "okay" flag (that is, false == failure).** The lastIndex value should be set to 0 before the first field in* a list is read. It is updated as fields are read and used in the* decode process.** The verification done by this function is of the raw data format* only; it does not verify that access flags or indices* are valid. */
static bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit,DexField* pField, u4* lastIndex) {if (! verifyUlebs(*pData, pLimit, 2)) {return false;}dexReadClassDataField(pData, pField, lastIndex);return true;
}/* Read and verify an encoded_method. This updates the* given data pointer to point past the end of the read data and* returns an "okay" flag (that is, false == failure).** The lastIndex value should be set to 0 before the first method in* a list is read. It is updated as fields are read and used in the* decode process.** The verification done by this function is of the raw data format* only; it does not verify that access flags, indices, or offsets* are valid. */
static bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit,DexMethod* pMethod, u4* lastIndex) {if (! verifyUlebs(*pData, pLimit, 3)) {return false;}dexReadClassDataMethod(pData, pMethod, lastIndex);return true;
}/* Read, verify, and return an entire class_data_item. This updates* the given data pointer to point past the end of the read data. This* function allocates a single chunk of memory for the result, which* must subsequently be free()d. This function returns NULL if there* was trouble parsing the data. If this function is passed NULL, it* returns an initialized empty DexClassData structure.** The verification done by this function is of the raw data format* only; it does not verify that access flags, indices, or offsets* are valid. */
static DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit) {DexClassDataHeader header;u4 lastIndex;if (*pData == NULL) {DexClassData* result = (DexClassData*) malloc(sizeof(DexClassData));memset(result, 0, sizeof(*result));return result;}if (! dexReadAndVerifyClassDataHeader(pData, pLimit, &header)) {return NULL;}size_t resultSize = sizeof(DexClassData) +(header.staticFieldsSize * sizeof(DexField)) +(header.instanceFieldsSize * sizeof(DexField)) +(header.directMethodsSize * sizeof(DexMethod)) +(header.virtualMethodsSize * sizeof(DexMethod));DexClassData* result = (DexClassData*) malloc(resultSize);u1* ptr = ((u1*) result) + sizeof(DexClassData);bool okay = true;u4 i;if (result == NULL) {return NULL;}result->header = header;if (header.staticFieldsSize != 0) {result->staticFields = (DexField*) ptr;ptr += header.staticFieldsSize * sizeof(DexField);} else {result->staticFields = NULL;}if (header.instanceFieldsSize != 0) {result->instanceFields = (DexField*) ptr;ptr += header.instanceFieldsSize * sizeof(DexField);} else {result->instanceFields = NULL;}if (header.directMethodsSize != 0) {result->directMethods = (DexMethod*) ptr;ptr += header.directMethodsSize * sizeof(DexMethod);} else {result->directMethods = NULL;}if (header.virtualMethodsSize != 0) {result->virtualMethods = (DexMethod*) ptr;} else {result->virtualMethods = NULL;}lastIndex = 0;for (i = 0; okay && (i < header.staticFieldsSize); i++) {okay = dexReadAndVerifyClassDataField(pData, pLimit,&result->staticFields[i], &lastIndex);}lastIndex = 0;for (i = 0; okay && (i < header.instanceFieldsSize); i++) {okay = dexReadAndVerifyClassDataField(pData, pLimit,&result->instanceFields[i], &lastIndex);}lastIndex = 0;for (i = 0; okay && (i < header.directMethodsSize); i++) {okay = dexReadAndVerifyClassDataMethod(pData, pLimit,&result->directMethods[i], &lastIndex);}lastIndex = 0;for (i = 0; okay && (i < header.virtualMethodsSize); i++) {okay = dexReadAndVerifyClassDataMethod(pData, pLimit,&result->virtualMethods[i], &lastIndex);}if (! okay) {free(result);return NULL;}return result;
}static void dumpDexClassDataMethod(DexFile *dexFile, DexClassData* classData)
{int idx = 0;DexMethod *method = NULL;const DexMethodId* methodId = NULL;method = classData->directMethods;methodId = dexFile->pMethodIds;for (int i = 0; i < (int) classData->header.directMethodsSize; i++) {idx = classData->directMethods[i].methodIdx;DexCode* pCode = dexGetCode(dexFile, &classData->directMethods[i]);if(pCode == NULL) continue;//ALOGD("      registers     : %d", pCode->registersSize);// ALOGD("      ins           : %d", pCode->insSize);// ALOGD("      outs          : %d", pCode->outsSize);// ALOGD("      insns size    : %d 16-bit code units", pCode->insnsSize);int a = 0;char buffer[256] = {0, 0};char tmp[32];for(u4 k=0; k<pCode->insnsSize; k++){sprintf(tmp, "%04x ", pCode->insns[k]);strcat(buffer, tmp);if(k%8 == 7){printf("%s", buffer);buffer[0] = 0;}}printf("%s", buffer);}for (int i = 0; i < (int) classData->header.virtualMethodsSize; i++) {idx = classData->virtualMethods[i].methodIdx;printf("idx-%d [%06lx]: %s->%s", idx, classData->virtualMethods[i].codeOff,getTpyeIdString(dexFile, methodId[idx].classIdx), getString(dexFile, methodId[idx].nameIdx));const DexCode* pCode = dexGetCode(dexFile, &classData->virtualMethods[i]);if(pCode == NULL) continue;printf("      registers     : %d", pCode->registersSize);printf("      ins           : %d", pCode->insSize);printf("      outs          : %d", pCode->outsSize);printf("      insns size    : %ld 16-bit code units", pCode->insnsSize);printf("      insns at      : %x ", (int)(pCode->insns) - (int)dexFile->baseAddr);printf("%x %x %x %x", pCode->insns[0], pCode->insns[1], pCode->insns[2], pCode->insns[3]);int a = 0;char buffer[256] = {0, 0};char tmp[32];for(u4 k=0; k<pCode->insnsSize; k++){sprintf(tmp, "%04x ", pCode->insns[k]);strcat(buffer, tmp);if(k%8 == 7){printf("%s", buffer);buffer[0] = 0;}}printf("%s", buffer);}
}const DexStringId* dexGetStringId(const DexFile* pDexFile, u4 idx) {return &pDexFile->pStringIds[idx];
}const char* dexGetStringData(const DexFile* pDexFile,const DexStringId* pStringId) 
{const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff;return (const char*) ptr;
}const char* dexStringById(const DexFile* pDexFile, u4 idx) {const DexStringId* pStringId = dexGetStringId(pDexFile, idx);return dexGetStringData(pDexFile, pStringId);
}const DexMethodId* dexGetMethodId(const DexFile* pDexFile, u4 idx) {return &pDexFile->pMethodIds[idx];
}void FixdexMethodInsns(DexFile *dexFile, const DexClassData*classData ,const char* className)
{int idx = 0;DexMethod *method = NULL;const DexMethodId* methodId = NULL;DexCode* code = NULL;const char* methodName;method = classData->directMethods;methodId = dexFile->pMethodIds;unsigned int CodeDataOffset = 0;u1 * tempCode = NULL;for (int i = 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 (int i = 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;
}void fixdexClassData()
{DexFile *dexFile = &gDexFile;char * Tag = "L";char * ClassTag = "Landroid/";const DexClassDef* classdef;u4 count = dexFile->pHeader->classDefsSize;printf("该DEX共有 %d 个类\n", count);const u1* pEncodedData = NULL;DexClassData* pClassData = NULL;const char *descriptor = NULL;int FileSize = 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);}}static void dumpDexCode(const DexCode *pCode)
{printf("      registers     : %d", pCode->registersSize);  printf("      ins           : %d", pCode->insSize); printf("      outs          : %d", pCode->outsSize);   printf("      insns size    : %ld 16-bit code units", pCode->insnsSize);        int a = 0;        char buffer[256] = {0, 0};        char tmp[32];        for(u4 k=0; k<pCode->insnsSize; k++){          sprintf(tmp, "%04x ", pCode->insns[k]);        strcat(buffer, tmp);           if(k%8 == 7){              printf("%s", buffer);buffer[0] = 0;         }        }    printf("%s", buffer);
}static void handleDexMethod(DexClassData* classData, const char*method)
{// TODO
}void* searchDexStart(const void *base)
{DexOptHeader *optHeader = (DexOptHeader*)base;return (void*)((u4)base + optHeader->dexOffset);
}static bool checkDexMagic(const void *dexBase)
{const char *pattern = "dex\n035";const char *dexer = (const char *)dexBase;if(strcmp(dexer, pattern) == 0){return true;}return false;
}

Dec.h

#include <windows.h>
#include "dexFile.h"unsigned int PolyXorKey(DWORD crckey);
u1* DecCode(u1 *code, int codeSize, DWORD key, u1* oldCode);
void GetCodeData( u1* outdata, int FileSize);int file_size();unsigned __int8 * dbone_crypt_ins(unsigned int DebugInfo1, unsigned __int8 *CodeData, unsigned int CodeLen, int Mode);

Dec.cpp

#include "Dec.h"
#include "crc32.h"
#include<stdio.h>unsigned int PolyXorKey(DWORD crckey)
{unsigned int dwKey;char temp;unsigned __int8 temp1;unsigned __int8 temp2;char *pKey;int temp3;int j;int i;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 = ((signed int)(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;}return dwKey;
}//crc32 FE 00 00 20 = 0x200000FE  = 7C939E40
u1* DecCode(u1 *code, int codeSize, DWORD key, u1* oldData)
{unsigned long Polykey = 0;unsigned long crc2 = 0;u1 * tempcode = NULL;u1 * tempcode1 = NULL;if (NULL == code || 0 == codeSize || NULL == oldData){return NULL;}tempcode = (u1*)malloc(codeSize);if (NULL == tempcode){return NULL;}memset(tempcode, 0, codeSize);tempcode1 = oldData;DWORD CodeOffset = *(DWORD*)code;//得到加密指令偏移tempcode1 += CodeOffset;//定位到加密指令开始位置memcpy(tempcode, tempcode1, codeSize);crc2 = crc32(crc2, (unsigned char*)&key, 4);for (int j=0; j<codeSize; j++){//每4字节进行解密for (int i =0; i<4; i++){tempcode[j+i] ^= *((unsigned char*)(&crc2)+i);tempcode[j+i] &= 0XFF;if (i==3){Polykey = PolyXorKey(crc2);crc2 = Polykey;}}j += 3;}return tempcode;}int file_size()
{FILE * fp;if( (fp=fopen("data","rb")) == NULL ){printf("打开文件失败!\n");return NULL;}fseek(fp,0L,SEEK_END);int size=ftell(fp);fclose(fp);return size;
}void GetCodeData( u1* outdata, int FileSize)
{FILE * fp;if (0 == FileSize || NULL == outdata){return;}if( (fp=fopen("data","rb")) == NULL ){printf("打开文件失败!\n");return;}fread(outdata,FileSize,1,fp);fclose(fp);return;
}int * XorArray(int *key, int codedata, int outcodedata, int codesize)
{int v4; // [sp+0h] [bp-24h]@1int v5; // [sp+4h] [bp-20h]@1int codedata1; // [sp+8h] [bp-1Ch]@1int *key1; // [sp+10h] [bp-14h]@1int *key2; // [sp+14h] [bp-10h]@1int keyindex; // [sp+18h] [bp-Ch]@1int i; // [sp+1Ch] [bp-8h]@1codedata1 = codedata;v5 = outcodedata;v4 = codesize;key1 = key;key2 = (int *)&key1;keyindex = 0;for ( i = 0; v4 > i; ++i ){key = key2;*(BYTE *)(v5 + i) = *(BYTE *)(codedata1 + i) ^ *((BYTE *)key2 + keyindex);if ( keyindex == 3 ){key = (int *)((int *(*)(unsigned int))PolyXorKey)((unsigned int)key1);key1 = key;keyindex = 0;}else{++keyindex;}}return key;
}int XorArray_0x99(int key, int codedata, int outcodedata, int codelen)
{int v4; // [sp+10h] [bp-14h]@1int v5; // [sp+14h] [bp-10h]@1int *v6; // [sp+18h] [bp-Ch]@1int i; // [sp+1Ch] [bp-8h]@1v4 = key;v6 = &v4;v5 = 0;for ( i = 0; codelen > i; ++i )*(BYTE *)(outcodedata + i) = ~(*(BYTE *)(codedata + i) ^ 0x66);return key;
}unsigned __int8 * dbone_crypt_ins(unsigned int DebugInfo1, unsigned __int8 *CodeData, unsigned int CodeLen, int Mode)
{int mode; // [sp+0h] [bp-1Ch]@1int codelen; // [sp+4h] [bp-18h]@1unsigned __int8 *codedata; // [sp+8h] [bp-14h]@1int DebugInfo; // [sp+Ch] [bp-10h]@1int crc2key; // [sp+14h] [bp-8h]@1DebugInfo = DebugInfo1;codedata = CodeData;codelen = CodeLen;mode = Mode;crc2key = crc32(crc2key, (unsigned char*)&DebugInfo, 4);;if ( mode == 1 ){XorArray(&crc2key, (int)codedata, (int)codedata, codelen);}else if ( mode ){puts("USAGE:dbone_crypt_ins(key,ins,ins_lenth)");}else{XorArray_0x99(DebugInfo, (int)codedata, (int)codedata, codelen);}return codedata;
}

crc32.h

#include <windows.h>
#include <stdio.h>static const unsigned long crc_table[256] =
{0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,0x2d02ef8dUL
};unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned len);

crc32.cpp

#include "stdafx.h"
#include "crc32.h"
#include <windows.h>unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned len)
{if (NULL == buf) return 0UL;crc = crc ^ 0xffffffffUL;unsigned n = 0;for (n = 0; n < len; n++){crc = crc_table[(crc ^ buf[n]) & 0xff] ^ (crc >> 8);}return crc ^ 0xffffffffUL;
}

 

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文档下载

 pdf文档_样本_src_bin.zip
 

 

更多推荐

APK加固之类抽取分析与修复

本文发布于:2024-02-13 16:46:56,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1760033.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:APK

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!