3种加固方式的学习记录
- 在java层为
.apk
文件进行加固- 在Native层为
.dex
文件进行加固- 在Native层为
.so
文件进行加固
1 Java层加固
1.1 Dex文件混淆加密
混淆加 密主要是为了隐藏 dex 文件中关键的代码,力度从轻到重包括:
静态变量的隐藏
函数的重复定义
函数的隐藏
整个类的隐藏。
混淆后的 dex 文件依旧可以通过 dex2jar jade 等工具的反编译成 Java 源码,但是里面关键的代码已经看不到了。
四种混淆加密的实现方式都是通过修改 class_def 结构体中字段实现的。
1 | struct DexClassDef { |
1.1.2 静态变量隐藏
saticValuesoff
保存了每个类中静态变量值的偏移,指向data区一个列表,格式为encode_array_item
,如果没有此项,该值为0,实现静态变量隐藏只需要将该字段修改为0
1.1.2 函数的重复定义
class_def -> class_data -> virtual_methods -> code_ff
表示的是某个类中某个函数的代码偏移地址。这里修改的都是 virtual_methods中 code_off。
实现方式:读取第一个函数的代码偏移地址,将接下来的函数偏移地址都修改为第一的值。
1.1.3 函数隐藏
class_def -> class_data -> virtual_methods_size
和class_def -> class_data -> direct_methods_size
记录了类定义中函数的个数,如果没有定义函数则该值为0。所以只要将该值改为0,函数定义就会被隐藏。
1.1.4 类定义隐藏
class_def -> class_data_off
保存了具体类定义的偏移地址,也就是class_def -> class_data
的地址,如果该值为0则所有实现将被隐藏。隐藏后会把类定义的所有东西都隐藏包括成员变量,成员函数,静态变量,静态函数。
1.2 APK 加固
- 待加密的apk文件进行加密
- 将已加密apk放在提取出来的壳apk的dex之后,
- 将新的dex文件重新放回壳apk,生成新的apk
需要修改dex的checksum,signature,filesize字段,最后需要添加源apk大小
1.2.1 实现原理
从已加壳apk中加载dex文件,得到源apk文件,解密源apk文件,加载解密之后的apk,找源程序的Application程序,使其运行。
通过反射置换
android.app.ActivityThread
中的mClassLoader
,将其改为源apk的DexClassLoader
该DexClassLoader一方面加载了源程序、另一方面以原
mClassLoader
为父节点,这就保证了即加载了源程序又没有放弃原先加载的资源与系统代码随后找到源程序的Application,通过反射建立并运行:找到解密之后的源Apk的Application类,运行的他的onCreate方法,这样源Apk才开始他的运行生命周期。
1.2.2 程序运行过程
- 在加密后的apk的
application
类中,重写attachBaseContest
方法:- 解密源apk
- 初始化自定义类加载器
- 利用反射,生成正确的Application对象
- 重写
onCreat
方法:- 获取源apk的Application名称
- 利用反射,生成正确的Application对象
- 利用反射,设置ActivityThread中的Application信息
- 调用源程序application对象的onCreate()方法
2 native层加固dex文件
2.1 壳原理
将原始apk文件的dex文件加密之后,放在apk的资源路径下,直通通过native代码重新对dex文件进行解密加载,从而执行原始的dex文件
2.2 流程
- 提取原始apk的dex文件,加密后命名位
demod.jar
,将其放置在Assets目录下 - 编写
libdemeod.so
,用于解密demod.jar
文件,并对其进行dexCLassLoader
操作 - 在壳apk中,新建
application
作为壳的启动器,并重写attachBaseContext
方法和onCreate
方法。这两个方法将调用libdemeod.so
的方法 - 修改
AndroidMainfest.xml
的application类名称位这个启动类名称 - 壳的
attachBaseContext
方法里调用native
代码,实现功能:解密dmeod.jar
文件并利用DexClassLoader
对其进行加载,并将其设置成已加载apk的类加载器(即修改成为android.app.LoadedApk的mClassLoader),加载原始apk的入口activity类。 - 壳的
onCreate
方法调用native
代码,实现功能:调用与那时apk的真正application类里的attachBaseContext
方法与DexClassLoader
方法。
3 native层加固so文件
3.1 加密so的section
3.1.1 原理
c代码生成so文件时:
声明重要函数showMessage时指定将其存放在自定义的.mytext段(通过
__attribute__((section(".mytext"))
);编写解密函数并在其声明时指定其在main函数前运行(即通过
__attribute(constructor)
)。从而使得so文件在被加载到内存后可第一时间对showMessage函数进行解密。此时生成初始so文件section_origin.so,对so文件尚未加密。