结合动态加载和函数Native化的DEX保护方法转让专利

申请号 : CN201810235689.4

文献号 : CN108491235B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 潘丽敏袁晓筱罗森林尚海张笈

申请人 : 北京理工大学

摘要 :

本发明涉及结合动态加载和函数Native化的DEX保护方法,属于计算机与信息科学技术领域中Android平台APP加固技术的一种。本发明第一步对应用的APK文件进行加固修改,加固过程首先通过apktool工具反编译应用APK文件,获取AndroidManifest.xml文件,修改应用启动入口,然后利用输入的待保护方法列表,生成植入代码,并植入原始DEX文件反编译得到的smali文件,重新生成DEX文件并重构,最后对DEX文件加密,输出得.jar,并重新打包生成APK。本发明第二步在APP运行过程中修改进程内存,首先启动壳DEX,运行植入的启动代码对原始DEX文件加密和动态加载,并重定向被保护的方法,接着,在函数调用时执行自定义的代码恢复被调用方法,调用原始函数,完成函数调用。

权利要求 :

1.结合动态加载和函数Native化的DEX保护方法,其特征在于所述方法包括如下步骤:步骤1,对APK文件加固修改阶段,首先对应用APK进行反编译,修改应用启动入口,接着利用输入的待保护方法列表生成植入代码,植入原smali文件,然后进行DEX重构,包括DEX函数抽取和DEX文件加密,其中DEX函数抽取分为函数定位和函数变换;

步骤2,应用启动阶段,首先执行壳DEX,执行自定义的系统启动入口,运行植入的启动代码,完成对源DEX文件的动态加载和加密,并进行被保护函数的重定向;

步骤3,应用运行中的函数调用阶段,首先进行函数自修改,包括DEX文件内存定位,函数信息获取和函数修改,接着进行函数调用,返回结果,完成整个函数的执行过程。

2.根据权利要求1所述的结合动态加载和函数Native化的DEX保护方法,其特征在于:步骤1中DEX函数抽取中的函数变换,将access_flags赋值为access_flags|ACC_NATIVE,实现了Java函数的Native化。

3.根据权利要求1所述的结合动态加载和函数Native化的DEX保护方法,其特征在于:步骤2中对函数进行重定向,将函数的Method‑>nativeFunc地址设置为自定义函数接口重定向函数。

4.根据权利要求1所述的结合动态加载和函数Native化的DEX保护方法,其特征在于:步骤3中函数自修改的DEX文件内存定位阶段,函数调用时,传递一个指向Method结构体指针method,指针指向所调用函数的Method结构体。

5.根据权利要求1所述的结合动态加载和函数Native化的DEX保护方法,其特征在于:步骤3中函数自修改的函数信息获取阶段,通过Method结构体ClassObject类的属性char*descriptor指向的字符串获取类名,通过Method结构体属性char*name指向的字符串获取函数名,通过DexProto结构体的属性protoIdx获取函数声明索引值。

6.根据权利要求1所述的结合动态加载和函数Native化的DEX保护方法,其特征在于:步骤3中函数调用阶段,通过Native形式的Method的insns字段找到Java形式的Method,通过反射方式,在native层调用Java函数。

说明书 :

结合动态加载和函数Native化的DEX保护方法

技术领域

[0001] 本发明涉及结合动态加载和函数Native化的DEX保护方法,属于计算机与信息科学技术领域。

背景技术

[0002] Android APP的核心业务逻辑通过Java实现,最终被编译成了DEX文件。DEX的安全问题是APP安全的核心,未加固的DEX文件不具备自我保护能力,需要针对性地对DEX进行保
护,继而保证APP的安全性。本发明提出结合动态加载和函数Native化的DEX保护方法,使
Java函数在内存中始终为Native形式,对抗动态恢复和动态脱壳攻击。
[0003] 针对DEX文件的保护方法需要解决的基本问题是:保护Java函数在内存中的信息,避免DEX容易受到动态恢复和动态脱壳攻击。综观现有的DEX文件保护方法,通常使用方法
可归为四类:
[0004] 1.基于代码混淆的DEX保护方法
[0005] 代码混淆技术是相对通用和成熟的方法,随着混淆技术的发展,已经出现了多个实用的混淆工具。其中包括针对Java源码的混淆工具,如Smardec公司的Allatori,针对
Android程序的混淆工具,如GuardSquare公司的ProGuard,以及它的增强版DexGuard和针
对DEX文件的混淆工具,如AIRO等。
[0006] 代码混淆技术虽然可以降低代码可读性,提高逆向分析的难度,但是攻击者仍然可以直接获取源码,也不影响动态调试的流程,而且存在着混淆失败的风险,给APP新增漏
洞,因此代码混淆只是DEX保护初级的保护方案。
[0007] 2.基于动态加载的DEX保护方法
[0008] 基于动态加载的DEX保护方法,通过对DEX文件整体加密,并将加密后的DEX移动到其他目录,然后在APK文件的根目录下加入壳DEX。当APP启动时,系统加载壳DEX,壳DEX解密
并动态加载DEX文件。这种方法将DEX文件作为一个整体进行加载,加载到内存中的DEX文件
是完整的。这种保护方法对内存dump等动态逆向方法的防护作用很小。
[0009] 3.基于Java函数动态恢复的DEX保护方法
[0010] 基于Java函数动态恢复的保护方法是更深层次的保护方法。以Java函数为基本单位进行DEX保护。目前国内大部分公司采取这样的方法,包括娜迦、腾讯乐固、梆梆、360、爱
加密等。方法有效改进了基于动态加载的DEX保护方法在内存中的完整性问题。如梆梆的加
固方法首先通过壳DEX去动态加载原始的DEX文件,但DEX文件在内存中是不完整的,部分函
数的代码被剥离。该方法Hook了dvmResolveClass函数,当类被加载时,该函数被执行,此时
对类中的被抽取的代码进行还原,填充Method结构体,完成动态恢复的过程。同时也保证了
DEX文件的不完整性。
[0011] 对于Java函数动态恢复的方法,内存中的DEX文件是不完整的。经过动态恢复的函数,虽然其在DEX文件中被描述是Native方法,但是其在内存中已经被还原成一个Java函
数。可以通过遍历class_data_item中所有类的所有函数,并获取该函数在内存中的Method
结构体信息,比较Method结构体对函数的描述和DEX文件对函数的描述,如果不一致,以
Method结构体为准。这样可以完成对已经加载过的类的函数进行恢复。
[0012] 4.基于虚拟机保护的DEX保护方法
[0013] 基于虚拟机保护(VMP)的DEX保护方法是目前安全性较高的一种保护方法。VMP技术通过自定义指令集和解释器,将DEX中函数的字节码全部替换成自定义的指令,运行过程
中,由自定义的解释器进行解释执行,从而使得内存中不会出现真实的字节码。基于虚拟机
保护的DEX保护方法,由于其对每一条指令都进行解释执行,时间和空间损耗较大,同时由
于Android系统的开源性,系统差异性较大,VMP的兼容性较差,主要用于一些关键的函数保
护。
[0014] 综上所述,现有DEX文件保护方法难以对DEX文件进行函数级的保护,实现函数的Native化,所以本发明提出结合动态加载和函数Native化的DEX保护方法。

发明内容

[0015] 本发明的目的是实现Java函数级的DEX保护,提出结合动态加载和函数Native化的DEX保护方法。
[0016] 本发明的设计原理为:首先对应用的APK文件进行加固修改,包括更换APP启动入口,代码植入,DEX重构,应用加壳几个步骤;然后进入在APP运行过程中修改进程内存的启
动阶段,包括动态加载和函数重定向;最后进入在APP运行过程中修改进程内存的函数调用
阶段,包括函数自修改和函数调用,最终实现动态加载和函数Native化的DEX保护。
[0017] 本发明的技术方案是通过如下步骤实现的:
[0018] 步骤1,对应用的APK文件进行加固修改。
[0019] 步骤1.1,通过apktool工具反编译应用APK文件,获取AndroidManifest.xml文件,修改应用启动入口。
[0020] 步骤1.2,利用输入的待保护方法列表,生成植入代码。
[0021] 步骤1.3,反编译原始DEX文件,得到smali文件,向其中植入步骤1.2中生成的植入代码,并生成DEX文件。
[0022] 步骤1.4,DEX重构第一阶段DEX函数抽取,包括函数定位和函数变换。
[0023] 步骤1.5,DEX重构第二阶段DEX文件加密。
[0024] 步骤1.6,应用加壳生成加固后的APK。
[0025] 步骤2,在APP运行过程中修改进程内存的启动阶段。
[0026] 步骤2.1,动态加载。
[0027] 步骤2.2,函数重定向。
[0028] 步骤3,在APP运行过程中修改进程内存的函数调用阶段。
[0029] 步骤3.1,函数自修改。
[0030] 步骤3.2,函数调用。
[0031] 有益效果
[0032] 相比于基于动态加载的DEX保护方法,本方法在防止静态攻击的同时,通过函数Native化,可以保证内存中DEX文件的不完整性,对抗动态脱壳攻击。
[0033] 相比于基于Java函数动态恢复的DEX保护方法,本方法使得函数始终是Native函数,不能通过获取Method结构体信息来动态恢复DEX文件。
[0034] 相比于虚拟机保护的DEX保护方法,本方法的时间增量与函数本身无关,对于执行时间较长的函数,时间损耗更少。

附图说明

[0035] 图1为本发明结合动态加载和函数Native化的DEX保护方法的对应用的APK文件进行加固修改的原理图。

具体实施方式

[0036] 为了更好的说明本发明的目的和优点,下面结合实例对本发明方法的实施方式做进一步详细说明。
[0037] 具体流程为:
[0038] 步骤1,对应用的APK文件进行加固修改。
[0039] 步骤1.1,修改应用启动入口,首先点击桌面图标,触发点击事件,Launcher进程与AMS通信;然后AMS通过Socket向Zegote进程发送创建进程请求;接着Zegote进程Fork自身,
新建一个应用进程;接着进入应用进程,应用进程调用ActivityThread类的main函数作为
应用程序的入口;然后调用attach函数初始化应用信息;接着调用Application类中经过重
载的attachBaseContext配置应用上下文,最后执行Application的onCreate()方法,进入
应用程序。
[0040] 步骤1.2,生成植入代码,首先修改代码文件,即读取待保护的函数,并将类名和函数名添加入代码集,然后进行Java编译,将Java代码编译成Dalvik虚拟机可执行的字节码。
[0041] 步骤1.3,植入代码,将原始DEX文件反编译后的smali文本集和植入代码的smali文本集合并,并转为DEX文件。
[0042] 步骤1.4,DEX重构第一阶段DEX函数抽取,首先遍历string_id段找到类名字符串和函数名字符串对应的string_id,接着遍历type_id段,确定类type_id值,然后遍历
class_def段,根据type_id确定类的class_def_item,接着遍历method_ids段,根据函数名
string_id和所属类的type_id确定method_id,然后遍历class_data_item的所有函数,根
据method_id确定偏移code_off,完成函数定位;接着函数变为Native的方法,即将access_
flags赋值为access_flags|ACC_NATIVE,其中ACC_NATIVE值为0x100,access_flags在成员
函数的encode_method结构字段中,完成函数变换。
[0043] 步骤1.5,DEX重构第二阶段DEX文件加密,首先利用密钥种子通过自定义的一系列操作生成一个密钥,然后利用密钥对DEX文件加密,解密程序中保存密钥种子,完成对DEX文
件的整体加密。
[0044] 步骤1.6,应用加壳生成加固后的APK,首先将原始的DEX文件经过DEX重构后变成.jar文件,并移动到/assets文件夹,在原DEX位置插入壳DEX文件,在/libs下插入用于脱壳
的动态库,对加壳后的APK重新编译和签名,生成加壳后的APK文件。
[0045] 步骤2,在APP运行过程中修改进程内存的启动阶段。
[0046] 步骤2.1,动态加载,首先打开加密后的DEX文件,读取密钥种子生成密钥,对内存中的DEX文件镜像解密,解密结果仍然存在内存之中,接着将解密后的DEX文件在内存中的
地址构造一个u4参数,调用openDexFile进行加载,然后通过NDK方式修改DexFile对象的
cookie值,最后新建源DEX的Application对象,调用Application的attach方法,完成对源
DEX动态加载和启动。
[0047] 步骤2.2,函数重定向,通过将函数的method‑>nativeFunc地址设定为自定义函数接口,重定向函数,其中自定义函数接口的原型为void hookedMethodCallback(const u4*
args,JValue*pResult,const Method*method,::Thread*self)。
[0048] 步骤3,在APP运行过程中修改进程内存的函数调用阶段。
[0049] 步骤3.1,函数自修改,首先通过一个指向Method结构体指针method,定位当前被调用的函数所在的DEX文件在内存中的位置;然后获取函数的信息,包括所属类的类名
(Method结构体ClassObject类的属性char*descriptor指向的字符串)、函数名(Method结
构体属性char*name指向的字符串)、函数声明索引编号(DexProto结构体的属性
protoIdx);最后通过遍历DEX中函数抽取区域的被保护函数信息,匹配以上三个特征,找到
code_item在内存中的位置,读取信息并修改Method的值。
[0050] 步骤3.2,函数调用,首先通过Native形式的Method的insns字段找到Java形式的Method,通过反射方式,在native层调用Java函数。反射调用的函数原型为
dvmInvokeMethod(thisObject,meth,argList,params,returnType,true);调用
dvmInvokeMethod之后,返回结果,完成整个函数执行过程。
[0051] 测试结果:实验基于结合动态加载和函数Native化的DEX保护方法,通过静态分析实验可以得出,结合动态加载和函数Native化的DEX文件保护方法利用动态加载方式,可以
保护APP原代码不被反编译和逆向分析,防止DEX被静态分析;通过动态脱壳实验可以得出,
通过对函数的Native化处理,可以保证DEX文件在内存中始终是不完整的,从而可以对抗内
存dump攻击;通过Native化验证实验可以得出,通过本发明方法保护DEX,在应用运行阶段,
被保护的函数始终是一个Native函数,实现了函数的Native化;通过性能分析实验可以得
出,a)经过函数抽取保护的DEX,每一个被保护函数的执行时间将会有等量的延长;b)方法
更适合于保护执行时间较长的函数。
[0052] 以上所述的具体描述,对发明的目的、技术方案和有益效果进行了进一步详细说明,所应理解的是,以上所述仅为本发明的具体实施例而已,并不用于限定本发明的保护范
围,凡在本发明的精神和原则之内,所做的任何修改、等同替换、改进等,均应包含在本发明
的保护范围之内。