首页 / 专利库 / 电脑编程 / 计算机虚拟化 / 虚拟化软件保护方法和装置

虚拟化软件保护方法和装置

阅读:1025发布:2020-06-22

专利汇可以提供虚拟化软件保护方法和装置专利检索,专利查询,专利分析的服务。并且本 申请 公开了一种虚拟化 软件 保护方法和装置,该方法包括:将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数;利用虚拟化指令转换引擎,将所述第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码;以及根据所述第二属性的函数、所述第二字节码和自定义 虚拟机 解释器,生成所述被保护软件的用于在虚拟机上执行的新安装包;其中,所述自定义虚拟机解释器用于执行新安装包时读取所述第二字节码并根据所述第二字节码的语义进行解释执行。根据本申请的方案,可有效保障被保护软件的安全。,下面是虚拟化软件保护方法和装置专利的具体信息内容。

1.一种虚拟化软件保护方法,其特征在于,包括:
将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数;利用虚拟化指令转换引擎,将所述第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码;以及
根据所述第二属性的函数、所述第二字节码和自定义虚拟机解释器,生成所述被保护软件的用于在虚拟机上执行的新安装包;
其中,所述第一属性的函数具体为爪哇java函数,所述第二属性的函数具体为原生native函数;
所述自定义虚拟机解释器通过爪哇本地接口JNI函数用于执行新安装包时读取所述第二字节码并根据所述第二字节码的语义进行解释执行。
2.根据权利要求1所述的保护方法,其特征在于,所述根据所述第二属性的函数、所述第二字节码和自定义虚拟机解释器,生成所述被保护软件的用于在虚拟机上执行的新安装包,包括:
删除所述第二属性的函数中所述第一属性的函数的已转换的第一字节码,将所述第二字节码,保存于所述第二属性的函数中,生成新的可执行文件;
将自定义虚拟机解释器和含有第二字节码的第二属性的函数编译生成新的动态库文件;以及
根据所述新的可执行程序文件和所述动态库文件,生成所述被保护软件的用于在虚拟机上执行的新安装包。
3.根据权利要求2所述的保护方法,其特征在于,还包括:
将含有第二字节码的第二属性的函数注册到虚拟机中;
使用所述虚拟机读取所述新安装包;以及
经由所述自定义虚拟机解释器执行所述第二字节码。
4.根据权利要求3所述的保护方法,其特征在于,所述经由所述自定义虚拟机解释器执行第二字节码,包括:
分配内存作为运行时所需要的寄存器数组;
将计算机PC指针指向编码缓冲区codebuf的首地址;以及
进入一个无限循环中,在此循环中,解析第二字节码中每条指令的操作数opcode,然后执行该opcode的语义,执行完后,读取所述codebuf中的下一条指令,赋给PC;如果没有指令,则退出该无限循环。
5.根据权利要求4所述的保护方法,其特征在于,
所述第二字节码中存在不涉及java语义的操作的指令时,
所述自定义虚拟机解释器在寄存器上执行该指令对应的操作;
其中,不涉及java语义的操作包括如下至少一项:
算术操作、寄存器赋值操作、条件跳转、返回return操作。
6.根据权利要求4所述的保护方法,其特征在于,
所述第二字节码中存在涉及java语义的操作的指令时,
所述自定义虚拟机解释器通过爪哇本地接口JNI函数的调用来执行该指令对应的操作;
其中,所述涉及java语义的操作包括如下至少一项:
对象的生成操作、对象域的读取操作、数组的生成和读写操作、函数调用操作、的操作、异常处理的操作。
7.根据权利要求6所述的保护方法,其特征在于,所述经由所述自定义虚拟机解释器执行所述第二字节码,还包括:
检测引用的java对象是否超过设定阈值
若超过,则调用删除本地参考Delete Local Ref函数删除寄存器数组中不存在的java对象。
8.根据权利要求1-7任一所述的保护方法,其特征在于,利用虚拟化指令转换引擎,将所述第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码,包括:
选取所述第一属性的函数中至少两个部分的第一字节码;以及
利用至少两个不同的虚拟化指令转换引擎,将所述至少两个部分的第一字节码转换为对应的第二字节码。
9.根据权利要求8所述的保护方法,其特征在于,基于所述第一属性的函数中包含的子函数来选取所述第一属性的函数中至少两个部分的第一字节码。
10.一种虚拟化软件保护装置,其特征在于,所述装置包括:
函数转化单元,配置用于将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数;
字节码转换单元,配置用于利用虚拟化指令转换引擎,将所述第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码;以及
软件保护单元,配置用于根据第二属性的函数、所述第二字节码和自定义虚拟机解释器,生成所述被保护软件的用于在虚拟机上执行的新安装包;
其中,所述第一属性的函数具体为爪哇java函数,所述第二属性的函数具体为原生native函数;
所述自定义虚拟机解释器通过爪哇本地接口JNI函数用于执行新安装包时读取所述第二字节码并根据所述第二字节码的语义进行解释执行。
11.根据权利要求10所述的保护装置,其特征在于,所述软件保护单元包括:
可执行文件生成子单元,配置用于删除所述第二属性的函数中所述第一属性的函数的已转换的第一字节码,将所述第二字节码,保存于所述第二属性的函数中,生成新的可执行文件;
动态库文件生成子单元,配置用于将自定义虚拟机解释器和含有第二字节码的第二属性的函数编译生成新的动态库文件;以及
保护安装包生成子单元,配置用于根据所述新的可执行程序文件和所述动态库文件,生成所述被保护软件的用于在虚拟机上执行的新安装包。
12.根据权利要求11所述的保护装置,其特征在于,还包括:
函数注册单元,配置用于将含有第二字节码的所述第二属性的函数注册到虚拟机中;
安装包运行单元,配置用于使用所述虚拟机读取所述新安装包;经由所述自定义虚拟机解释器执行所述第二字节码。
13.根据权利要求10-12任一所述的保护装置,其特征在于,所述字节码转换单元进一步配置用于:
选取所述第一属性的函数中至少两个部分的第一字节码;以及
利用至少两个不同的虚拟化指令转换引擎,将所述至少两个部分的第一字节码转换为对应的第二字节码。
14.一种计算机设备,包括一个或多个处理器以及存储器,其特征在于:
所述存储器包含可由所述处理器执行的指令以使得所述处理器执行权利要求1-9任一所述的方法。
15.一种存储有计算机程序的计算机可读存储介质,其特征在于,所述计算机程序使计算机执行权利要求1-9任一所述的方法。

说明书全文

虚拟化软件保护方法和装置

技术领域

[0001] 本公开一般涉及计算机技术领域,具体涉及一种虚拟化软件保护方法和装置。

背景技术

[0002] Android(安卓)平台上采用java(爪哇)语言进行开发,java语言是一种跨平台的,解释性的语言,Java的源代码编译为一种“字节码”形式的中间代码,这种字节码保留了很多源代码的信息,例如方法名,变量名等,从而java字节码的反编译变得非常容易。为了保护Android程序的应用版权等,需要对应用程序进行保护。
[0003] 传统的Android平台上软件代码保护技术主要包括代码混淆和软件加壳这两种技术。
[0004] 代码混淆是指将程序的代码转换成一种功能上等价,但是难于阅读和理解的形式的行为。
[0005] 软件加壳是另一种应用极其普遍的软件保护技术。所谓“壳”,即包裹在程序外的一层代码,这层代码在被保护代码前执行,执行解密代码、反调试等操作,完成这些任务后,再将执行权转交给目标代码。
[0006] 目前在软件加壳主要有两代技术:一代技术基于java的类加载技术进行保护,二代技术采用方法代码抽取加密的方式实现。一代技术使用java本身提供的类加载技术,可执行文件classes.dex被完整加密,存放到APK(Android Package,安卓安装包)的资源中。运行时修改程序入口,将加密后的classes.dex在内存中解密,并让虚拟机加载执行。二代技术将原APK中的所有方法的代码提取出来,单独加密,当虚拟机要执行某个方法时,加固引擎才解密该方法,并将解密后的代码交给虚拟机的执行引擎执行。
[0007] 然而,现有的代码混淆和软件加壳保护软件代码上存在保护度不够的问题,软件代码的安全性有待进一步提高。发明内容
[0008] 鉴于现有技术中的上述缺陷或不足,期望提供一种能够有效保障软件代码安全的保护方案。
[0009] 第一方面,本申请实施例提供了一种虚拟化软件保护方法,包括:
[0010] 将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数;
[0011] 利用虚拟化指令转换引擎,将所述第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码;以及
[0012] 根据所述第二属性的函数、所述第二字节码和自定义虚拟机解释器,生成所述被保护软件的用于在虚拟机上执行的新安装包;
[0013] 其中,所述第一属性的函数具体为爪哇java函数,所述第二属性的函数具体为原生native函数;
[0014] 所述自定义虚拟机解释器通过爪哇本地接口JNI函数用于执行新安装包时读取所述第二字节码并根据所述第二字节码的语义进行解释执行。
[0015] 第二方面,本申请实施例还提供了一种虚拟化软件保护装置,所述装置包括:
[0016] 函数转化单元,配置用于将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数;
[0017] 字节码转换单元,配置用于利用虚拟化指令转换引擎,将所述第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码;以及
[0018] 软件保护单元,配置用于根据第二属性的函数、所述第二字节码和自定义虚拟机解释器,生成所述被保护软件的用于在虚拟机上执行的新安装包。
[0019] 第三方面,本申请实施例还提供了一种计算机设备,包括一个或多个处理器以及存储器,所述存储器包含可由所述处理器执行的指令以使得所述处理器执行所述虚拟化软件保护方法。
[0020] 第四方面,本申请实施例还提供了一种存储有计算机程序的计算机可读存储介质,所述计算机程序使计算机执行所述虚拟化软件保护方法。
[0021] 本申请实施例提供的方案中,将被保护软件安装包中的第一属性的函数转换为第二属性的函数;利用虚拟化指令转换引擎,将第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码;以及根据第二属性的函数、所述第二字节码和自定义虚拟机解释器,生成所述被保护软件的用于在虚拟机上执行的新安装包。这样,通过改变程序中函数的部分内容(例如,子函数)的代码表现形式和自定义虚拟机解释器,加大了逆向分析的难度和还原代码的难度,从而使被保护软件更加安全。附图说明
[0022] 通过阅读参照以下附图所作的对非限制性实施例所作的详细描述,本申请的其它特征、目的和优点将会变得更明显:
[0023] 图1示出了根据本申请实施例的虚拟化软件保护方法的示例性流程图
[0024] 图2示出了根据本申请一个实施例的虚拟化软件保护装置的示例性结构框图
[0025] 图3出了根据本申请另一个实施例的虚拟化软件保护装置的示例性结构框图;以及
[0026] 图4出了根据本申请一个实施例的软件保护单元的示例性结构框图;
[0027] 图5出了根据本申请一个实施例的计算设备的示例性结构框图。

具体实施方式

[0028] 下面结合附图和实施例对本申请作进一步的详细说明。可以理解的是,此处所描述的具体实施例仅仅用于解释相关发明,而非对该发明的限定。另外还需要说明的是,为了便于描述,附图中仅示出了与发明相关的部分。
[0029] 需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。下面将参考附图并结合实施例来详细说明本申请。
[0030] 如背景技术中所提到的,现有技术所采用的代码混淆和软件加壳保护技术,存在保护力度不够的问题。本发明的发明人发现,代码混淆并不能真正阻止逆向工程,只能增大其理解难度。软件加壳能有效的阻止静态分析,但很难阻止动态分析,因为最后的解密后的代码最终要在内存中执行,只要破解者能够在内存中找到解密后的代码的地址,那么脱壳就很容易。
[0031] 例如,软件加壳的一代和二代技术,最终都需要将被保护的代码解密后,交给虚拟机的执行引擎执行,只不过二者的保护粒度不同,一代在虚拟机的类载入模进行拦截,就可以备份出最终的保护代码。二代则需要更进一步的深入虚拟机,在虚拟机执行引擎这块进行拦截,即可以备份出解密后的代码。从本质来说,一代和二代的软件加壳技术,都是一种代码的隐藏技术,最终代码还是通过虚拟机进行执行的。因此,破解者可以通过构建一个自己修改过的虚拟机,对保护方案进行脱壳。
[0032] 鉴于现有技术的上述缺陷,本申请实施例提供了一种软件保护方案,对需保护的第一属性的函数在第一属性层面转换为第二属性的函数;并对需保护的第一属性的函数的至少一部分的字节码进行随机化的虚拟化指令转换,转换成为新的字节码格式;这样,后续安装被保护软件时,可通过转换的第二属性的函数读入新的经过虚拟化指令转换后的字节码,并解释执行这段转换后的字节码,完成被保护软件的安装。而程序中在小于函数级别(例如,子函数级别)上的代码表现形式的改变和自定义虚拟机解释器的破解难度,可加大被保护软件的逆向分析难度和还原代码难度,从而使被保护软件更加安全。
[0033] 本申请实施例中,被保护软件原安装包中需保护的函数,称为第一属性的函数;将原安装包中需保护的函数进行属性转换后得到的函数,称为第二属性的函数。在下文的描述中,将以第一属性的函数的其中一个部分(例如,其中一个子函数)为例来说明根据本申请实施例的软件保护方案。函数各部分的划分或选取可以基于多种规则。在一些实施例中,当函数包含多个子函数时,可以基于子函数进行划分或选取。在另一些实施例中,可以对函数进行任意划分或选取。可以理解,以下针对第一属性的函数的一个部分的描述可以扩展到该函数的其他部分,每个部分可以使用相同或不同的虚拟化指令引擎进行转换,从而增加对软件的保护。需要注意,在一些实施例中,当第一属性的函数中存在多个部分需要进行转换时,至少应用两个不同的虚拟化指令转换引擎。
[0034] 本申请方案适用于Android平台上虚拟化软件保护,后续可以第一属性的函数为java(爪哇)函数、第二属性的函数为native(原生)函数为例来详细说明本申请的方案。
[0035] 当然,实际应用中,第一属性的函数不局限于java函数;第二属性的函数不局限于native函数。
[0036] APK(Android Package,安卓安装包)是Android平台上的可执行程序,主要包括以下几类文件:可执行文件classes.dex、动态库文件so文件、Android Manifest.xml、其他资源文件(比如,图片、xml等)。
[0037] 其中,可执行文件classes.dex里面存放了被保护软件所有的java源代码经过编译后的字节码。在Android平台上,java源代码通过Javac编译器先编译为.class文件(标准的Java字节码),然后利用Android提供的工具dx将多个class文件转换为一个dex文件。
[0038] dex文件主要由几个部分组成,头部(Dex Header)、各类表(Table)、数据段(Data Section)。头部包含了每个区域的大小及偏移信息;各类表包含各种数据,如字符串表、类名表、函数表等等,字节码里面通过表的索引来进行编码;数据段包括了字节码等信息。
[0039] 例如:以下语句
[0040] “100b64:1a01 9408|0002:const-string v1,"Hello world"//string@0894”[0041] 其中,1a01 9408是真正的Raw的字节码,1a表示操作数opcode表示const-string,01代表寄存器v1,9408代表在字符串表中的第894项。
[0042] 而Android平台除了Java平台外,还允许使用C/C++语言进行混合编程。同时提供了JNI接口(Java native interface,爪哇本地接口)。JNI接口提供了一系列的接口允许从C/C++语言中操作Java语言中的对象,如设置某个Java对象的域(Field)、调用Java中的函数(method)等。C/C++编写的源代码通过Android NDK(Native Development Kit,原生开发工具包)编译为动态库so文件。
[0043] 基于上述内容,下面将结合流程图来描述本申请实施例的方法。
[0044] 图1示出了根据本申请实施例的虚拟化软件保护方法的示例性流程图。
[0045] 如图1所示,本申请实施例的虚拟化软件保护方法包括如下步骤:
[0046] 步骤110,将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数。
[0047] 步骤120,利用虚拟化指令转换引擎,将第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码。
[0048] 步骤130,根据第二属性的函数、第二字节码和自定义虚拟机解释器,生成被保护软件的用于在虚拟机上执行的新安装包。
[0049] 具体地,步骤130中可以删除第二属性的函数中第一属性的函数已转换的第一字节码,将第二字节码,保存于第二属性的函数中,生成新的可执行文件;将自定义虚拟机解释器和含有第二字节码的第二属性的函数编译生成新的动态库文件;以及根据新的可执行程序文件和动态库文件,生成被保护软件的用于在虚拟机上执行的新安装包。
[0050] 其中,自定义虚拟机解释器用于执行新安装包时读取第二字节码并根据第二字节码的语义进行解释执行。实际应用中,由于自定义虚拟机解释器通常采用标准的JNI函数来构建,JNI函数是Java的一个标准规范,Android上的虚拟机,无论Dalvik虚拟机或者ART虚拟机,都会实现这套函数接口,因此,自定义虚拟机解释器不依赖于具体虚拟机是如何实现的,具有后向的兼容性。
[0051] 本申请实施例中,可预先扫描被保护软件原安装包APK中的所有函数,从中确定需要保护的函数(可称为demo函数);并获取demo函数的第一属性的函数源代码;对第一属性的函数源代码进行编译后生成对应的字节码。其中,第一属性的函数源代码进行编译后生成的字节码,可称为第一字节码。如前面所提到的,第一属性的函数中需要进行字节码转换的部分可以基于子函数来选取或划分,也可以任意选取或划分。该选取或划分可以针对源代码执行,也可以针对编译后字节码执行。本申请实施例提供的方案中,用户可以灵活选择某些关键的函数部分进行虚拟化的保护,便于达到性能和安全性的一个平衡。
[0052] 以第一属性的函数为java函数、第二属性的函数为native函数为例。步骤110中,针对被保护软件原APK中需要保护的函数,可以将其属性修改为native,转换得到对应的native函数。
[0053] 接着,可以从被保护软件原APK中的原可执行文件classes.dex文件中提取出待转换部分的第一字节码。
[0054] 步骤120中,可针对提取出第一字节码,利用虚拟化指令转换引擎进行指令映射,转换为新的、自定义的字节码格式。本文中可将第一字节码转换自定义字节码格式后得到的字节码,称为第二字节码。可以理解,此处“第二字节码”仅是泛指经过转换后的字节码,以与转换前的字节码进行区别描述,函数中不同的部分具有不同的第二字节码。
[0055] 实际应用中,虚拟化指令转换引擎可先随机化生成一个opcode(操作数)的映射表,然后根据该映射表对原来的第一字节码进行映射,生成新的自定义格式的第二字节码。
[0056] 如前面所提到的,本申请的实施例可以基于函数的一部分进行转换。当函数包含多个部分需要转换时,使用至少两个不同的虚拟化指令转换引擎,进一步提高软件保护的安全性。
[0057] 举例而言,假设第一属性的A函数中有3个部分需要转换,在一个实施例中,可以使用2个不同的虚拟化指令转换引擎,具体地,该第一属性的A函数中任意2个部分使用一个虚拟化指令转换引擎进行转换,另外1个部分使用另一个虚拟化指令转换引擎进行转换;在另一个实施例中,可以使用3个不同的虚拟化指令转换引擎,分别对该第一属性的A函数中的3个部分进行转换。
[0058] 步骤130中,可删除通过步骤110转换得到的native函数中java函数的已转换的第一字节码,并将通过步骤120转换得到的第二字节码,保存于native函数中,生成新的可执行文件。
[0059] 实际应用中,在步骤110转换得到native函数的同时,即可执行删除native函数中已转换的第一字节码的操作。
[0060] 之后,将自定义虚拟机解释器和含有第二字节码的native函数编译生成动态库文件。其中,自定义虚拟机解释器的主要工作是读取自定义的第二字节码,然后根据第二字节码的语义进行解释执行。具体地,可将自定义虚拟机解释器和含有第二字节码的native函数,采用Android平台的NDK编译生成新的动态库so文件。
[0061] 继而,根据新的可执行程序文件和动态库文件,生成被保护软件的用于在虚拟机上执行的新安装包。具体地,可将生成的新的可执行程序文件替换掉原APK中的可执行文件;将新的动态库文件插入原APK中,得到最终的保护后的新APK。
[0062] 实际应用中,为了后续能够在虚拟机上执行被保护软件的新安装包,本申请实施例中,可进一步将含有第二字节码的第二属性的函数注册到虚拟机中;使用虚拟机读取新安装包;以及经由自定义虚拟机解释器执行第二字节码。
[0063] 考虑到,虚拟机的字节码是一种基于寄存器的指令集。因此,自定义虚拟机解释器也需要构造出分配出一段内存作为运行时使用的寄存器数组。其中,寄存器数组可参考虚拟机对于每个方法所指明的该方法所需要的最大寄存器数目而进行构造。
[0064] 本申请实施例中,为了执行第二字节码,自定义虚拟机解释器分配内存作为运行时所需要的寄存器数组;将计算机PC指针指向编码缓冲区codebuf的首地址;以及进入一个无限循环中,在此循环中,解析第二字节码中每条指令的opcode(操作数),然后执行该opcode的语义,执行完后,读取codebuf中的下一条指令,赋给PC;如果没有指令,则退出该无限循环。
[0065] 以第一属性的函数为java函数、第二属性的函数为native函数为例。在将第二字节码保存于native函数后,可将含有第二字节码的native函数注册到虚拟机中。在注册过程中,将C/C++层面的函数与java函数建立了注册关系。这样,当被保护软件的java函数被调用时,虚拟机实际调用的是C/C++层面的函数。具体地,使用虚拟机读取被保护软件的新安装包;并经由自定义虚拟机解释器执行第二字节码,完成被保护软件的native函数实现。
[0066] 实际应用中,自定义虚拟机解释器在执行第二字节码的过程中的关键在于如何实现每个opcode的语义。
[0067] Android平台的字节码可以分为两种类型:1)不涉及Java语义的基本操作;2)涉及Java语义的操作。
[0068] 不涉及java语义的操作包括如下至少一项:
[0069] 算术操作、寄存器赋值操作、条件跳转、返回return操作。
[0070] 涉及java语义的操作包括如下至少一项:
[0071] 对象的生成操作、对象域的读取操作、数组的生成和读写操作、函数调用操作、的操作、异常处理的操作。
[0072] 本申请实施例中,如第二字节码中存在不涉及java语义的操作的指令时,自定义虚拟机解释器可在寄存器上执行该指令对应的操作。
[0073] 如第二字节码中存在涉及java语义的操作的指令时,自定义虚拟机解释器可通过JNI函数的调用来执行该指令对应的操作。
[0074] 进一步地,考虑到在自定义虚拟机解释器执行过程中,会产生大量的临时Java对象(jobject),在Android JNI的规范中,一个native函数最多只能有512个Java对象的引用,如果超过512个,则会报“JNI ERROR(app bug):local reference table overflow(max=512)”错误,因此自定义虚拟机解释器需要处理这种情况。
[0075] 由于JNI接口提供了Delete Local Ref来手动删除不再使用jobject的引用。因此,本申请实施例中,可采用类似于垃圾收集的方式来处理这种情况。其思想是在自定义虚拟机解释器执行过程中,如果一个jobject不在当前的寄存器数组中,则可以安全的删除。具体地,检测引用的java对象是否超过设定阈值;若超过,则调用删除本地参考Delete Local Ref函数删除寄存器数组中不存在的java对象。
[0076] 应当注意,尽管在附图中以特定顺序描述了本发明方法的操作,但是,这并非要求或者暗示必须按照该特定顺序来执行这些操作,或是必须执行全部所示的操作才能实现期望的结果。相反,流程图中描绘的步骤可以改变执行顺序。例如,实施例1中的步骤110和步骤120可以交换顺序或同时进行。附加地或备选地,可以省略某些步骤,将多个步骤合并为一个步骤执行,和/或将一个步骤分解为多个步骤执行。例如,可将步骤130进行分解,分解后的多个步骤与步骤110、步骤120的执行顺序可适应性调整。
[0077] 从上面描述可以看出,在本申请的一些实施例中,针对被保护软件的保护问题,提出了基于比函数还小的级别和字节码表现形式的转换的保护方案。被保护软件的字节码转换成自定义的字节码格式,对于破解者来说,即使在内存中拿到了自定义的字节码的内容,还需要去分析和理解这种自定义的字节码格式,因此,破解者需要花费大量的时间来逆向自定义虚拟机解释引擎。而基于比函数还小的级别(例如,子函数级别)转换的虚拟化保护,可以构建多套不同虚拟化的解释引擎,不同的函数部分或子函数采用不同的自定义的字节码,通过这种方式还可以进一步提高安全性。
[0078] 以下将举例说明自定义虚拟机解释器如何实现不同opcode的语义。
[0079] 一、不涉及java语义的基本操作
[0080] 1)基本的算术操作
[0081] 由于此类操作包括加减乘除、移位操作、强制转换操作等。基本的处理模式就是解析指令中的参数,得到操作的是哪几个寄存器,然后在这几个寄存器上执行相应的操作。
[0082] 例如,add-int vAA,vBB,vCC的实现
[0083] 语义:Register[vAA]=regigter[vBB]+register[vCC]
[0084] 实现:
[0085] 如果OPcode为add-int:
[0086] 1.从vBB,vCC中取得寄存器号;
[0087] 2.根据寄存器号从寄存器数组中,取出相应的值,赋给临时变量vsrc1,vsrc2;
[0088] 3.临时变量vdst等于vsrc1+vsrc2的值;
[0089] 4.取得vAA代表的寄存器号;
[0090] 5.设置vAA寄存器号代表的寄存器数组中的值为vdst(Register[vAA]=vdst,[0091] 取下一条指令[PC=PC+当前指令的长度]。
[0092] 2)基本的寄存器赋值操作
[0093] 此类操作主要是以move为前缀的指令,基本语义是从将一个寄存器的值赋给另外一个寄存器。
[0094] 例如:move vA,vB
[0095] 语义:Register[vA]=regigter[vB]
[0096] 实现:
[0097] 如果OPcode为mov:
[0098] 1.从vA,vB中取得寄存器号;
[0099] 2.根据寄存器号vB从寄存器数组中,取出相应的值,赋给临时变量vsrc(vsrc=Register[vB]);
[0100] 3.设置vA寄存器号代表的寄存器数组中的值为vsrc(Register[vAA]=vsrc),[0101] 取下一条指令[PC=PC+当前指令的长度]。
[0102] 3)条件跳转
[0103] 这类指令主要是以IF为前缀的一些指令,主要的区别是会修改PC值如果条件满足,PC值等于当前PC+偏移量(如下例的CCCC的值)。
[0104] 例如:IF-EQ vA,vB+CCCC
[0105] 语义:IF Register[vA]==Register[vB]then PC=PC+0xCCCC else PC=PC+当前指令长度
[0106] 实现:
[0107] 如果OPcode为IF-EQ:
[0108] 1.从vA,vB中取得寄存器号;
[0109] 2.根据寄存器号vB从寄存器数组中,取出相应的值,赋给临时变量vsrc1,vsrc2;
[0110] 3.如果vsrc1==vsrc2,PC=PC=PC+0xCCCC,
[0111] 否则PC=PC+当前指令的长度。
[0112] 4)return操作
[0113] 这类指令主要是以RETURN为前缀的一些指令,主要工作是设置返回值,然后从解释器中返回。
[0114] 例如:return vAA
[0115] 语义:设置返回值为Register[vAA],然后从解释器中返回
[0116] 实现:
[0117] 如果OPcode为return:
[0118] 1.从vAA中取得寄存器号;
[0119] 2.根据寄存器号vAA从寄存器数组中,取出相应的值,赋给临时变量vsrc;
[0120] 3.设置返回值result,从解释器中返回。
[0121] 二、涉及java语义的基本操作
[0122] 1)对象以及数组的生成操作
[0123] 该操作生成一个新的Java对象或者Java数组,有new-instance,new-array两个指令。
[0124] new-instance指令实现的核心是使用JNI的AllocObject函数来生成新的Java对象。
[0125] new-array指令实现的核心是根据指令的参数,使用不同的New[type]Array来生成对应类型的对象,例如:如果参数是对象,使用NewObjectArray,如果参数是boolean,则使用NewBooleanArray等。
[0126] 例如:new-instance vAA,class@BBBB
[0127] 语义:生成一个新的对象,该对象的类是Class Table中的偏移为0xBBBB的类,生成的新对象赋给Register[vAA]
[0128] 实现:
[0129] 如果OPcode为new-instance:
[0130] 1.查询Class Table偏移为0xBBBB处,得到Class的名字;
[0131] 2.调用env->FindClass(class的名字)得到jclass clazz;
[0132] 3.调用env->AllocObject(clazz)生成新的Java对象jobject obj[0133] 4.将obj的值赋予Register[vAA];
[0134] 5.PC=PC+当前指令的长度。
[0135] 2)对象域的读取操作
[0136] 这类指令是对对象里面的域进行读写操作,包括:iget/iput、sget/sput。
[0137] iget/iput是对对象中的非静态域进行读取操作,这类指令使用JNI函数Get[type]Field系列函数来实现。
[0138] sget/sput是对对象中的静态域进行读取操作,这类指令使用JNI函数GetStatic[type]Field系列函数来实现。
[0139] 例如:iget-object vA,vB,field@CCCC
[0140] 语义:根据0xCCCC查找Field Table,取出对象Register[vB]中的域,赋给Register[vA]
[0141] 实现:
[0142] 如果OPcode为iget-object:
[0143] 1.查询Field Table偏移为0xBBBB处,得到Field的信息(类名,域名等);
[0144] 2.调用env->FindClass(Field->calassname)得到jclass clazz;
[0145] 3.调用env->GetFieldID(clazz,Field->fieldname,Field->type)新的jfieldID fieldid;
[0146] 4.Register[vA]=env->GetObjectField(Register[vB],fielded);
[0147] 5.PC=PC+当前指令的长度。
[0148] 3)数组的读写操作
[0149] 这类指令是对数组里某个元素进行读写,包括:AGET/APUT系列的指令,通过使用JNI的Get[Type]ArrayElements等一系列的函数来实现。
[0150] 例如:aget-object vAA,vBB,vCC
[0151] 语义:将Register[vBB]的数组中第vCC个元素赋于Register[vAA][0152] 实现:
[0153] 如果OPcode为aget-object:
[0154] 1.调用env->GetObjectArrayElement(Register[vBB],
[0155] Register[vCC])得到Register[vBB]的数组中第vCC个元素,赋予临时变量vsrc;
[0156] 2.设置Register[vAA]的值为vsrc;
[0157] 3.PC=PC+当前指令的长度。
[0158] 4)函数调用操作
[0159] 这类操作主要时调用Java层面的函数进行调用,包括:
[0160] invoke-static系列的指令调用Java的静态函数,使用JNI接口中CallStatic[type]Method系列函数来实现。
[0161] invoke-virtual,invoke-interface系列的指令调用Java的成员函数、接口等,使用JNI接口中Call[type]method系列函数来实现。
[0162] invoke-super和invoke-direct系列的指令调用Java的父类、private函数等,使用JNI接口中CallNonvirtual[type]Method系列函数来实现。
[0163] 例如:invoke-virtual vB,{vD,vE,vF,vG,vA},meth@CCCC
[0164] 语义:调用Method Table中偏移为0xCCCC的函数,参数为vB,{vD,vE,vF,vG,vA}[0165] 实现:
[0166] 如果OPcode为invoke-virtual:
[0167] 1.查询Method Table偏移为0xCCCC处,得到method的信息(类名,函数名等);
[0168] 2.调用env->FindClass(Method->calassname)得到jclass clazz;
[0169] 3.调用env->GetMethodID(clazz,Method->methodname,Method->methodtype)新的jMethodID methodid;
[0170] 4.根据Method->methodtype判断返回值,调用不同env->Call[type]Method(methodid,vB,{vD,vE,vF,vG,vA}),设置函数返回值。如果method返回一个对象,则调用[0171] result.l=env->CallObjectMethod(method,vB,{vD,vE,vF,vG,vA});
[0172] 5.PC=PC+当前指令的长度。
[0173] 5)锁的操作
[0174] 这类指令主要有两个Monitor-enter(进入临界区)和moniter-exit(退出临界区)。采用JNI函数env->MonitorEnter和env->MoniterExit来实现。
[0175] 6)异常处理的操作
[0176] Java支持异常的处理,这类指令有move-exception,throw等,这类指令可以采用env->ExceptionClear,env->ExceptionOccurred,env->ThrowNew,env->Throw等JNI的函数进行实现。
[0177] 进一步参考图2,其示出了根据本申请实施例的虚拟化软件保护装置的示例性结构框图。
[0178] 如图2所示,虚拟化软件保护装置可以包括:函数转化单元201、字节码转换单元202和软件保护单元203。
[0179] 其中,函数转化单元201配置用于将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数。
[0180] 字节码转换单元202配置用于利用虚拟化指令转换引擎,将第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码。
[0181] 软件保护单元203配置用于根据第二属性的函数、第二字节码和自定义虚拟机解释器,生成被保护软件的用于在虚拟机上执行的新安装包。
[0182] 在一些实施例中,字节码转换单元202可以进一步配置用于:选取第一属性的函数中至少两个部分的第一字节码;以及利用至少两个不同的虚拟化指令转换引擎,将该至少两个部分的第一字节码转换为对应的第二字节码。
[0183] 优选地,图3示出了根据本申请另一个实施例的虚拟化软件保护装置的示例性结构框图。
[0184] 如图3所示,虚拟化软件保护装置除了可以包括:函数转化单元301、字节码转换单元302和软件保护单元303,还可以进一步包括:函数注册单元304、安装包运行单元305。
[0185] 其中,函数转化单元301配置用于将被保护软件原安装包中需保护的第一属性的函数转换为第二属性的函数。
[0186] 字节码转换单元302配置用于利用虚拟化指令转换引擎,将第一属性的函数的至少一部分的第一字节码转换为自定义格式的第二字节码。
[0187] 软件保护单元303配置用于根据第二属性的函数、第二字节码和自定义虚拟机解释器,生成被保护软件的用于在虚拟机上执行的新安装包。
[0188] 函数注册单元304配置用于将含有第二字节码的第二属性的函数注册到虚拟机中。
[0189] 安装包运行单元305配置用于使用虚拟机读取新安装包;经由自定义虚拟机解释器执行第二字节码。
[0190] 图4示出了根据本申请一个实施例的软件保护单元的示例性结构框图。
[0191] 如图4所示,软件保护单元可以包括:可执行文件生成子单元401、动态库文件生成子单元402和保护安装包生成子单元403。
[0192] 其中,可执行文件生成子单元401配置用于删除第二属性的函数中第一属性的函数的已转换的第一字节码,将第二字节码,保存于第二属性的函数中,生成新的可执行文件。
[0193] 动态库文件生成子单元402配置用于将自定义虚拟机解释器和含有第二字节码的第二属性的函数编译生成新的动态库文件。
[0194] 保护安装包生成子单元403配置用于根据新的可执行程序文件和动态库文件,生成被保护软件的用于在虚拟机上执行的新安装包。
[0195] 应当理解,图2、图3所示的虚拟化软件保护装置中记载的诸单元、以及图4所示的软件保护单元中记载的诸子单元,可参考图1描述的方法中的各步骤及其具体实现,在此不再赘述。
[0196] 进一步地,本申请实施例还提供了一种计算设备,包括一个或多个处理器以及存储器;其中,存储器包含可由处理器执行的指令以使得处理器执行图1所示实施例提供的虚拟化软件保护方法。
[0197] 下面参考图5,其示出了适于用来实现本申请实施例的计算设备的结构示意图。
[0198] 如图5所示,计算设备500包括中央处理单元(CPU)501,其可以根据存储在只读存储器(ROM)502中的程序或者从存储部分508加载到随机访问存储器(RAM)503中的程序而执行各种适当的动作和处理。在RAM 503中,还存储有系统操作所需的各种程序和数据。CPU 501、ROM 502以及5AM 703通过总线504彼此相连。输入/输出(I/O)接口505也连接至总线
504。
[0199] 以下部件连接至I/O接口505:包括键盘鼠标等的输入部分506;包括诸如阴极射线管(CRT)、液晶显示器(LCD)等以及扬声器等的输出部分507;包括硬盘等的存储部分508;以及包括诸如LAN卡、调制解调器等的网络接口卡的通信部分509。通信部分509经由诸如因特网的网络执行通信处理。驱动器510也根据需要连接至I/O接口505。可拆卸介质511,诸如磁盘、光盘、磁光盘、半导体存储器等等,根据需要安装在驱动器510上,以便于从其上读出的计算机程序根据需要被安装入存储部分508。
[0200] 特别地,根据本公开的实施例,上文参考图1描述的过程可以被实现为计算机软件程序。例如,本公开的实施例包括一种存储有计算机程序的计算机可读存储介质,计算机程序使计算机执行图1所示实施例提供的虚拟化软件保护方法。在这样的实施例中,该计算机程序可以通过通信部分509从网络上被下载和安装,和/或从可拆卸介质511被安装。
[0201] 附图中的流程图和框图,图示了按照本发明各种实施例的系统、方法和计算机程序产品的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段、或代码的一部分,模块、程序段、或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现中,方框中所标注的功能也可以以不同于附图中所标注的顺序发生。例如,两个接连地表示的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或操作的专用的基于硬件的系统来实现,或者可以用专用硬件与计算机指令的组合来实现。
[0202] 描述于本申请实施例中所涉及到的单元或模块可以通过软件的方式实现,也可以通过硬件的方式来实现。所描述的单元或模块也可以设置在处理器中。这些单元或模块的名称在某种情况下并不构成对该单元或模块本身的限定。
[0203] 作为另一方面,本申请提供的存储有计算机程序的计算机可读存储介质,可以是上述实施例中所述系统中所包含的计算机可读存储介质;也可以是单独存在,未装配入设备中的计算机可读存储介质。计算机可读存储介质存储有一个或者一个以上程序,所述程序被一个或者一个以上的处理器用来执行描述于本申请的公式输入方法。
[0204] 以上描述仅为本申请的较佳实施例以及对所运用技术原理的说明。本领域技术人员应当理解,本申请中所涉及的发明范围,并不限于上述技术特征的特定组合而成的技术方案,同时也应涵盖在不脱离所述发明构思的情况下,由上述技术特征或其等同特征进行任意组合而形成的其它技术方案。例如上述特征与本申请中公开的(但不限于)具有类似功能的技术特征进行互相替换而形成的技术方案。
高效检索全球专利

专利汇是专利免费检索,专利查询,专利分析-国家发明专利查询检索分析平台,是提供专利分析,专利查询,专利检索等数据服务功能的知识产权数据服务商。

我们的产品包含105个国家的1.26亿组数据,免费查、免费专利分析。

申请试用

分析报告

专利汇分析报告产品可以对行业情报数据进行梳理分析,涉及维度包括行业专利基本状况分析、地域分析、技术分析、发明人分析、申请人分析、专利权人分析、失效分析、核心专利分析、法律分析、研发重点分析、企业专利处境分析、技术处境分析、专利寿命分析、企业定位分析、引证分析等超过60个分析角度,系统通过AI智能系统对图表进行解读,只需1分钟,一键生成行业专利分析报告。

申请试用

QQ群二维码
意见反馈