代码混淆方法、装置、电子设备及存储介质与流程

文档序号:23383145发布日期:2020-12-22 13:47阅读:140来源:国知局
代码混淆方法、装置、电子设备及存储介质与流程

本发明涉及计算机安全技术领域,尤其涉及一种代码混淆方法、装置、电子设备及存储介质。



背景技术:

随着信息科学技术的发展,软件系统在为用户带来便利的同时,其安全性也面临严重威胁。攻击者通过反编译、反汇编、动态调试等逆向手段,可轻易获取软件包含的用户私有信息、核心算法、关键业务流程,甚至软件的源代码。这给企业的软件知识产权保护造成了巨大损失。

为了有效抵御攻击者针对软件的逆向分析,软件开发人员提出了软件加密,代码混淆,软件水印,防篡改等保护技术。代码混淆技术是保障软件安全的关键技术之一,它在不改变原程序语义的前提下,把程序的源代码和内部结构逻辑转换为一种更难分析、更难修改的形式,大大增加攻击者逆向分析成本。

控制流混淆是代码混淆中比较成熟和关键的技术,它通过改变原程序的控制流或使控制流复杂化来隐藏程序真实的执行逻辑,增加破解者分析及重构程序控制流的难度,从而保护源代码。目前研究较多的控制流混淆技术的实现方法包括:

(1)不透明谓词

对控制流图中的基本块,添加从表达式本身很难推断出其值的恒真、恒假或时真时假的不透明谓词,混淆基本块的真实执行流程,使控制流变得更复杂。

(2)控制流平坦化

通过破坏函数控制流图中容易识别的条件及循环结构,将易于阅读的代码流程重组成一个难于理解的switchcase形式的代码执行流程。

(3)插入虚假控制流

利用不透明谓词技术,向原始控制流中插入多余的控制流,增加原始控制流的复杂度,提高攻击者重建出原始控制流的难度。

使用上述控制流混淆方法混淆程序后特征较明显,容易被攻击者发现并利用现有的逆向技术进行破解,还原代码控制流。如经常被使用的不透明谓词是有限数量的较复杂的数学表达式,可收集整理后在逆向分析时直接过滤掉;又如控制流平坦化后程序拥有一个明显的switchcase结构,可在动态调试过程记录代码块的执行顺序,重建控制流。



技术实现要素:

本发明实施例提供一种代码混淆方法、装置、电子设备及存储介质,用以解决现有技术中的代码混淆方法混淆程序代码后,程序特征较为明显,容易被攻击者发现并破解的缺陷。

本发明第一方面实施例提供一种代码混淆方法,包括:

根据目标程序中的函数的控制流走向,确定所述函数中的基本代码块;

对所述基本代码块进行分割,得到子代码块;

将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址;其中,所述代码块包括子代码块,或包括子代码块以及未被分割的基本代码块。

上述技术方案中,在所述对所述基本代码块进行分割,得到子代码块的步骤之后,方法还包括:

打乱所述目标程序中的函数内的代码块在所属函数内的排布顺序。

上述技术方案中,所述将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址,具体包括:

在具有非条件跳转指令的第一代码块与根据所述非条件跳转指令所要跳转的第二代码块之间插入地址计算代码块,并将所述非条件跳转指令的跳转目标变更为所述地址计算代码块;其中,所述地址计算代码块用于在运行时动态计算所述第二代码块的地址。

上述技术方案中,所述在具有非条件跳转指令的第一代码块与根据所述非条件跳转指令所要跳转的第二代码块之间插入地址计算代码块,具体包括:

在所述第一代码块与所述第二代码块之间插入地址计算代码块;

根据所述地址计算代码块的地址信息以及所述第二代码块的地址信息,计算所述地址计算代码块与所述第二代码块之间的地址偏移量;

将所述地址计算代码块内的非条件跳转指令所要跳转的地址修改为一个地址计算式,所述地址计算式包括:所述地址计算代码块自身的地址信息,所述地址计算代码块与所述第二代码块之间的地址偏移量。

上述技术方案中,方法还包括:

将所述目标程序中对系统函数的直接调用指令替换为对系统函数的间接调用指令。

上述技术方案中,所述将所述目标程序中对系统函数的直接调用指令替换为对系统函数的间接调用指令,具体包括:

根据系统函数的真实地址以及动态链接库生成间接调用指令,所述间接调用指令通过解析动态链接库中的函数地址的形式获取要执行的系统函数的真实地址;

将目标程序中对系统函数的直接调用指令替换为对系统函数的间接调用指令。

上述技术方案中,所述根据第二预设规则对所述基本代码块进行分割,得到子代码块,具体包括:

判断所述基本代码块是否满足预设规则,当满足预设规则时,对所述基本代码块进行分割,得到第一分割结果;

判断所述第一分割结果的尾部是否存在跳转指令,当不存在跳转指令时,在所述第一分割结果的尾部添加跳转指令,得到子代码块;其中,所述跳转指令用于跳转到所述第一分割结果的最后一条指令在所述基本代码块中的下一条指令。

本发明第二方面实施例提供一种代码混淆装置,包括:

基本代码块确定模块,用于根据目标程序中的函数的控制流走向,确定所述函数中的基本代码块;

子代码块生成模块,用于对所述基本代码块进行分割,得到子代码块;

指令转换模块,用于将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址;其中,所述代码块包括子代码块,或包括子代码块以及未被分割的基本代码块。

本发明第三方面实施例提供一种电子设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机程序,所述处理器执行所述程序时实现如本发明第一方面实施例所述代码混淆方法的步骤。

本发明第四方面实施例提供一种非暂态计算机可读存储介质,其上存储有计算机程序,该计算机程序被处理器执行时实现如本发明第一方面实施例所述代码混淆方法的步骤。

本发明实施例提供的代码混淆方法、装置、电子设备及存储介质,通过将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址,从而切断了具有非条件跳转指令的代码块与所要跳转的代码块之间的直接跳转关系,增加了反向分析的难度。

附图说明

为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作一简单地介绍,显而易见地,下面描述中的附图是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。

图1为本发明实施例提供的代码混淆方法的流程图;

图2为在具有非条件跳转指令的代码块与所要跳转的代码块之间插入地址计算代码块的示意图;

图3为一个函数未混淆前,用逆向工具ida查看到的控制流图;

图4为与图3相关的函数在被混淆后,用逆向工具ida查看到的控制流图;

图5为本发明实施例提供的代码混淆装置的示意图;

图6为本发明实施例提供的一种电子设备的实体结构示意图。

具体实施方式

为使本发明实施例的目的、技术方案和优点更加清楚,下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。

图1为本发明实施例提供的代码混淆方法的流程图,如图1所示,本发明实施例提供的代码混淆方法包括:

步骤101、根据目标程序中的函数的控制流走向,确定所述函数中的基本代码块。

在本发明实施例中,目标程序是指采用本发明实施例提供的代码混淆方法进行代码混淆的程序。具体的说,目标程序中的函数是代码混淆操作的对象,即需要对目标程序所包含的函数内的代码进行混淆。

本领域技术人员都知道,计算机领域中的函数是一个固定的程序段,它能够独立地完成一个特定的功能。函数的基本组成单位是指令。执行指令可实现某一步具体的操作。基本代码块介于函数与指令之间。基本代码块包括多个指令,而函数又可包括一个或多个基本代码块。

目标程序内部的执行逻辑被称为控制流走向。控制流走向反映了函数之间的调用关系以及函数内部各个指令的执行流程。作为一种可选的实现方式,目标程序的函数的控制流走向可以采用控制流图表示。

在本发明实施例中,控制流走向为预先分析得到的,在本发明的其他实施例中,也可通过llvm提供的工具及函数库对目标程序进行分析,从而得到目标程序的函数的控制流走向。llvm将目标程序的源代码编译为中间代码文件,解析中间代码文件,并遍历中间代码文件中的函数,从而得到函数的控制流走向。

作为一种可选的实现方式,可利用llvm提供的工具及函数库分析函数的控制流走向,将函数中所有switch-case结构替换为if-else结构,获取函数原始控制流基本代码块。由于switch-case结构容易被攻击者用于对目标程序的反向分析,因此需要替换函数中的所有switch-case结构为if-else结构。

根据目标程序的控制流走向,对函数做进一步的切分,可得到基本代码块。在对函数做进一步切分时,可根据目标程序中的函数的控制流走向以及第一预设规则,从函数中切分出基本代码块。

根据所述第一预设规则,可确定基本代码块的起始指令,所述第一预设规则包括以下三项中的任意一项:

a)函数的入口指令;

b)跳转指令的目标指令;

c)跳转指令后的下一条指令且该指令并非跳转指令的目标指令。

在确定基本代码块的起始指令之后,将同一函数中两个基本代码块的起始指令之间的所有指令(不含第二个起始指令)构成一个基本代码块。

需要说明的是,本领域技术人员很容易理解,若一个函数中包括有switch-case结构,在将switch-case结构替换后,由该函数进一步切分所得到的基本代码块中,也将不再有switch-case结构。

步骤102、对所述基本代码块进行分割,得到子代码块。

为了进一步增加反向分析的难度,在本发明实施例中,可对基本代码块做进一步分割,得到子代码块。

子代码块是基本代码块的一部分,包括有多个指令。在对基本代码块进行分割前,首先要判断基本代码块是否满足第二预设规则。所述第二预设规则用于描述基本代码块的分割条件。例如,第二预设规则的一种实现方式是预设的指令条数,如5条。则在判断基本代码块是否满足第二预设规则时,判断基本代码块中的指令条数是否有5条,如果大于或等于5条,则基本代码块满足第二预设规则,可做进一步的分割处理;如果小于5条,则不能对该基本代码块做分割处理。第二预设规则的内容并不局限于预设的指令条数,还可以根据实际需要确定第二预设规则的内容。

第二预设规则不仅可以用于判断基本代码块是否能被分割,还可以用于指导基本代码块的分割。在对基本代码块进行分割时,可根据第二预设规则(如预设的指令条数)分割基本代码块,得到子代码块。例如,预先设定每5条指令组成一个子代码块,那么在分割基本代码块时,将基本代码块中的连续的5条指令作为一个基本单元进行分割,得到相应的子代码块。若基本代码块在某一次分割后,剩余的指令不足5条时,可将剩余指令作为一个基本单元组成一个子代码块。

需要说明的是,在生成基本代码块时,以跳转指令作为分割的界线,因此切分所得到的基本代码块之间的逻辑关系不会被中断。但在生成子代码块时,除了少数子代码块(如基本代码块尾部的子代码块)之外,子代码块的尾部在被分割前并不存在诸如跳转指令等与其他子代码块发生明确逻辑关系的指令,因此在分割基本代码块、生成子代码块时,需要在子代码块的尾部添加一个跳转指令,从而明确当前子代码块执行完成后所要执行的下一个子代码块。

例如,某一函数中的一个基本代码块的代码如下:

label%3:

%4=allocai8*,align8

%5=allocai32*,align8

%6=allocai32*,align4

%7=allocai32*,align4

%8=allocai32*,align4

storei8*%0,i8**%4,align8

storei32*%1,i32**%5,align8

storei32*%2,i32**%6,align4

storei32*%0,i32**%7,align4

storei32*%0,i32**%8,align4

brlabel%9

对上述基本代码块按照一定的规则进行切分,可得到以下多个子代码块:

子代码块1

label%3:

%4=allocai8*,align8

%5=allocai32*,align8

%6=allocai32*,align4

brlabel%.split

子代码块2

label.split:

%7=allocai32*,align4

%8=allocai32*,align4

brlabel%.split.split

子代码块3

label.split.split:

storei8*%0,i8**%4,align8

brlabel%.split.split.split

子代码块4

label.split.split.split:

storei32*%1,i32**%5,align8

storei32*%2,i32**%6,align4

storei32*%0,i32**%7,align4

storei32*%0,i32**%8,align4

brlabel%9

从上述的例子中可以看出,从基本代码块新划分得到的子代码块1—子代码块3的尾部都新添加了跳转指令,根据这些新添加的跳转指令可以跳转到下一个子代码块。

步骤103、将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址。

目标程序中的各个函数在经过之前步骤的操作后,函数中包括有子代码块,在某些情况下,函数内的一些基本代码块不满足分割的条件,因此函数中也会包括未被分割的基本代码块。将未被分割的基本代码块(如果有的话)与子代码块统一记为代码块。

所述将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址,具体包括:

在具有非条件跳转指令的第一代码块与根据所述非条件跳转指令所要跳转的第二代码块之间插入地址计算代码块,并将所述非条件跳转指令的跳转目标变更为所述地址计算代码块;所述地址计算代码块用于在运行时动态计算所述第二代码块的地址。

跳转指令包括条件跳转指令与非条件跳转指令。非条件跳转指令也被称为直接跳转指令,该指令无需进行条件判断即需要进行跳转操作。跳转指令能够清晰地反映目标程序的执行顺序,因此为了增加反向分析的难度,需要对跳转指令进行隐藏。

具体的说,在具有非条件跳转指令的第一代码块与所要跳转的第二代码块之间插入地址计算代码块,同时通过修改第一代码块的非条件跳转指令的目标地址来切断具有非条件跳转指令的第一代码块与根据所述非条件跳转指令所要跳转的第二代码块之间的直接控制流关系,即将第一代码块的非条件跳转指令的目标地址由所述第二代码块修改为所述地址计算代码块。所述地址计算模块中包括有一条非条件跳转指令,该非条件跳转指令所要跳转的地址是一个地址计算式,所述地址计算式包括:地址计算代码块自身的地址信息,地址计算代码块与第二代码块之间的地址偏移量。所述地址计算代码块与所述第二代码块之间的地址偏移量可根据所述地址计算代码块的地址信息以及所述第二代码块的地址信息预先计算得到。

目标程序在运行时,可确定地址计算代码块自身的地址信息的具体取值,从而结合地址计算代码块与第二代码块之间的地址偏移量,计算出第二代码块的地址信息,进而实现到第二代码块的跳转。

这一操作可切断第一代码块与第二代码块之间的直接跳转关系,使得第二代码块的地址只能在目标程序运行时才能动态计算得到,增加了反向分析的难度。

例如,图2为在具有非条件跳转指令的代码块与所要跳转的代码块之间插入地址计算代码块的示意图。在图2所示的实施例中,假设目标程序中有代码块a和代码块b,图2最左侧描述了代码块a和代码块b的原始执行流程。按照原始执行流程,代码块a直接跳转到代码块b,代码块a中包括有伪跳转指令jumpb(实际可以是jump,mov,bx,jne等多种类型的指令)。按照本发明实施例的描述,首先,在代码块a与代码块b之间增加一个代码块t,此时代码块t的内容仅包含一条跳转代码块b的指令,同时代码块a中跳转到代码块b的指令jumpb变更为跳转到代码块t的指令jumpt。图2中间部分描述了在代码块a和代码块b之间增加代码块t。接着,计算代码块b与代码块t之间的地址偏移,记为offset。修改代码块t的内容为:获取t的地址,修改直接跳转指令为间接跳转,即将代码块t中直接跳转代码块b的jumpb指令替换为jumpt+offset,从而切断代码块a与代码块b的直接跳转关系,使得代码块b的地址只能在运行时动态计算得到。图2最右侧描述了修改代码块t中的地址内容。

本发明实施例提供的代码混淆方法通过将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址,从而切断了具有非条件跳转指令的代码块与所要跳转的代码块之间的直接跳转关系,增加了反向分析的难度。

基于上述任一实施例,在本发明实施例中,在步骤102之后,方法还包括:

打乱目标程序中的函数内部的代码块在所属函数内的顺序。

各个函数内部的代码块之间存在线性顺序,为了提高反向分析的难度,在本实施例中,打乱函数内部的代码块之间的顺序。

具体的说,在本发明实施例中,可为函数中的各个代码块设定编号,并生成一个能反映代码块编号的随机数组。例如,某一函数中共有n个代码块,按照从1至n的顺序为这些代码块编号。在为代码块编号后,可生成一个大小为n,内容为1至n且无重复数据的随机数组。这一随机数组中的数字并不按照数字的大小进行排序,而是随机排序。

有了所述的随机数组后,可将代码块按照随机数组的顺序重新排列,达到破坏函数原始布局的目的。例如,一个大小为10的随机数组中的数字排序为:1、3、8、5、7、4、6、2、9、10。在对代码块进行排序时,将编号为1的代码块放在函数中的首位,接着将编号为3的代码块放在函数中的第2位,再接着将编号为8的代码块放在函数中的第3位,以此类推,最后将编号为10的代码块放在函数中的第10位。

需要说明的是,本发明实施例中,打乱函数内部的代码块的顺序是指打乱代码块在函数中的静态布局顺序,由于各个代码块中包含有跳转指令,因此整个函数的动态执行逻辑并未改变,该函数依然可以正常执行。

目标程序中包括有多个函数,对各个函数均可按照上述描述打乱其内部的代码块顺序。

本发明实施例提供的代码混淆方法通过从目标程序所包含的函数中获取基本代码块,并对基本代码块做分割,得到子代码块,然后对函数内未被分割的基本代码块以及子代码块进行乱序排布,从而改变目标程序中各个函数的内容布局,达到增加反向分析难度的目的。

基于上述任一实施例,在本发明实施例中,方法还包括:

将目标函数中对系统函数的直接调用指令替换为对系统函数的间接调用指令。

在本发明实施例中,系统函数是指c语言标准规定的库函数,如glibc中的函数。系统函数容易暴露某些关键代码的位置,因此需要隐藏目标程序中的系统函数。

在具体实现时,将目标程序中对系统函数的直接调用指令替换为对系统函数的间接调用指令,所述间接调用指令通过解析动态链接库中的函数地址的形式获取要执行的系统函数的真实地址。例如,在linux下,通过dlsym函数形式解析要执行的系统函数地址,从而引入系统函数;在windows下,通过getprocaddress函数形式获取要执行的系统函数地址,从而引入系统函数。

例如,在一个实施例中,首先遍历目标程序中的函数,分析并获取函数调用中的系统函数,将所述系统函数记为sysfunc;接着,加密系统函数名,得到加密后的系统函数名encstr;然后,将目标程序中所有系统函数调用指令转变为间接调用指令,具体包括:用dlsym加载需要调用的系统函数,将相关函数的名称记为indirectcall,系统函数名将在运行时解密;最后,函数indirectcall替换目标函数中之前的系统函数。

对应该实施例的相关代码如下:

系统函数被替换前:

sysfunc(…)

系统函数被替换后:

encstr=encode(“sysfunc”);

indirectcall=dlsym((void*)0,decode(encstr))

indirectcall(…)

经过上述操作后,目标程序中对系统函数的调用被隐藏,使得攻击者无法通过反向分析找出目标程序中的系统函数。

在上述的实施例中,作为一种优选实现方式,在将系统函数的直接调用指令替换为对系统函数的间接调用指令的同时,还执行了加密系统函数名的操作。这样做可以进一步加深系统函数的混淆程度。在其他实施例中,也可根据实际需要省去加密系统函数名的操作。

本发明实施例提供的代码混淆方法通过隐藏目标程序中对系统函数的调用,使得攻击者无法通过反向分析找出目标程序中的系统函数,可有效防止静态分析,并延迟对软件的复制或篡改。

为了说明本发明实施例提供的代码混淆方法的技术效果,通过附图对目标程序在代码混淆前后的控制流图进行比较。

图3为一个函数未混淆前,用逆向工具ida查看到的控制流图。根据该控制流图,攻击者可以清晰的看到程序的布局以及执行流程。使用本发明实施例提供的代码混淆方法后,通过ida逆向工具查看该函数的控制流如图4所示,从图中可以看到程序代码块增多了,且存在很多互不相关的代码块,攻击者很难读懂代码且直接分析程序执行流程。

图5为本发明实施例提供的代码混淆装置的示意图,如图5所示,本发明实施例提供的代码混淆装置包括:

基本代码块确定模块501,用于根据目标程序中的函数的控制流走向,确定所述函数中的基本代码块;

子代码块生成模块502,用于对所述基本代码块进行分割,得到子代码块;

指令转换模块503,用于将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址;其中,所述代码块包括子代码块,或包括子代码块以及未被分割的基本代码块。

本发明实施例提供的代码混淆装置通过将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址,从而切断了具有非条件跳转指令的代码块与所要跳转的代码块之间的直接跳转关系,增加了反向分析的难度。

图6为本发明实施例提供的一种电子设备的实体结构示意图,如图6所示,该电子设备可以包括:处理器(processor)610、通信接口(communicationsinterface)620、存储器(memory)630和通信总线640,其中,处理器610,通信接口620,存储器630通过通信总线640完成相互间的通信。处理器610可以调用存储器630中的逻辑指令,以执行如下方法:根据目标程序中的函数的控制流走向,确定所述函数中的基本代码块;对所述基本代码块进行分割,得到子代码块;将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址;其中,所述代码块包括子代码块,或包括子代码块以及未被分割的基本代码块。

需要说明的是,本实施例中的电子设备在具体实现时可以为服务器,也可以为pc机,还可以为其他设备,只要其结构中包括如图6所示的处理器610、通信接口620、存储器630和通信总线640,其中处理器610,通信接口620,存储器630通过通信总线640完成相互间的通信,且处理器610可以调用存储器630中的逻辑指令以执行上述方法即可。本实施例不对电子设备的具体实现形式进行限定。

此外,上述的存储器630中的逻辑指令可以通过软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本发明各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:u盘、移动硬盘、只读存储器(rom,read-onlymemory)、随机存取存储器(ram,randomaccessmemory)、磁碟或者光盘等各种可以存储程序代码的介质。

进一步地,本发明实施例公开一种计算机程序产品,所述计算机程序产品包括存储在非暂态计算机可读存储介质上的计算机程序,所述计算机程序包括程序指令,当所述程序指令被计算机执行时,计算机能够执行上述各方法实施例所提供的方法,例如包括:根据目标程序中的函数的控制流走向,确定所述函数中的基本代码块;对所述基本代码块进行分割,得到子代码块;将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址;其中,所述代码块包括子代码块,或包括子代码块以及未被分割的基本代码块。

另一方面,本发明实施例还提供一种非暂态计算机可读存储介质,其上存储有计算机程序,该计算机程序被处理器执行时实现以执行上述各实施例提供的方法,例如包括:根据目标程序中的函数的控制流走向,确定所述函数中的基本代码块;对所述基本代码块进行分割,得到子代码块;将代码块中的非条件跳转指令的目标地址转换为在所述目标程序运行时确定的地址;其中,所述代码块包括子代码块,或包括子代码块以及未被分割的基本代码块。

以上所描述的装置实施例仅仅是示意性的,其中所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本实施例方案的目的。本领域普通技术人员在不付出创造性的劳动的情况下,即可以理解并实施。

通过以上的实施方式的描述,本领域的技术人员可以清楚地了解到各实施方式可借助软件加必需的通用硬件平台的方式来实现,当然也可以通过硬件。基于这样的理解,上述技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品可以存储在计算机可读存储介质中,如rom/ram、磁碟、光盘等,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行各个实施例或者实施例的某些部分所述的方法。

最后应说明的是:以上实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的精神和范围。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1