一种程序的运行方法、装置、电子设备及介质与流程

专利2023-09-19  7



1.本技术涉及程序运行的技术领域,尤其涉及一种程序的运行方法、装置、电子设备及介质。


背景技术:

2.软件程序使用的安全性一直是各厂商关注的重点,以安卓(android)系统的程序为例,出于系统使用的安全性考虑,会将系统核心功能核心代码使用开源源码(或称native)的so文件进行开发,目的是so文件的安全性比java层高,原因在于其破解门槛比java层高,而so文件中,则是使用jni(java native interface,java本地接口)来开发,通过jni可以调用于java交换的数据、接口、功能等等。但是通过应用发现,该种方式开发的程序易被反编译破解。
3.因此,如何提高程序运行的安全性,是目前亟待解决的技术问题。


技术实现要素:

4.本发明的一种程序的运行方法、装置、电子设备及介质,能够提高程序运行的安全性。
5.本发明实施例提供了以下方案:
6.第一方面,本发明实施例提供了一种程序的运行方法,所述方法包括:
7.获取程序的指针数组,其中,所述指针数组中的每个函数指针均指向对应的函数;
8.将所述指针数组中的第一函数指针和第二函数指针进行替换;
9.基于所述第二函数指针调用所述第一函数指针的对应函数,以运行所述程序。
10.在一种可选的实施例中,所述获取程序的指针数组,包括:
11.基于所述程序的开发源码,获得包含所述指针数组的目标结构体;
12.根据所述指针数组中第一函数指针的运行路径,获得与原始函数的功能相同的替换函数,其中,所述原始函数为所述第一函数指针在所述目标结构体中指向的函数;
13.根据所述第一函数指针和所述替换函数对应的第二函数指针,获得所述指针数组。
14.在一种可选的实施例中,所述根据所述指针数组中第一函数指针的运行路径,获得与原始函数的功能相同的替换函数,包括:
15.根据所述第一函数指针在所述目标结构体的创建记录,获得所述运行路径的创建路径;
16.根据所述第一函数指针在所述目标结构体的初始化记录,获得所述运行路径的初始化路径;
17.根据所述第一函数指针在所述目标结构体的调用记录,获得所述运行路径的调用链路径;
18.根据所述创建路径、所述初始化路径和所述调用链路径,在所述开发源码的函数
库中确定所述替换函数。
19.在一种可选的实施例中,所述将所述指针数组中的第一函数指针和第二函数指针进行替换,包括:
20.根据所述程序中函数的功能定义,进行函数类别划分;
21.在所述第一函数指针指向函数的所述函数类别中,确定出替换函数和对应的所述第二函数指针;
22.将所述第一函数指针的第一变量和所述第二函数指针的第二变量进行替换。
23.在一种可选的实施例中,所述根据所述程序中函数的功能定义,进行函数类别划分,包括:
24.根据所述功能定义对应生成类别变量,其中,所述功能定义包括调用函数、属性获取函数、属性设置函数、异常处理函数、创建函数和资源释放函数;
25.将所述类别变量存储为所述函数类别的索引。
26.在一种可选的实施例中,所述将所述第一函数指针的第一变量和所述第二函数指针的第二变量进行替换,包括:
27.将所述第一变量和所述第二变量组成的数组,输入预设的算法模型;
28.将所述算法模型输出的随机数组,确定所述第一变量和所述第二变量的替换次序;
29.根据所述替换次序对所述第一变量和所述第二变量进行替换。
30.在一种可选的实施例中,所述基于所述第二函数指针调用所述第一函数指针的对应函数,包括:
31.根据所述第二函数指针的变量值和预设的函数指针列表,确定所述第一函数指针对应函数的函数地址,其中,所述函数指针列表为函数指针和函数地址的对应关系表;
32.根据所述函数地址调用所述第一函数指针的对应函数。
33.第二方面,本发明实施例还提供了一种程序的运行装置,所述装置包括:
34.获取模块,用于获取程序的指针数组,其中,所述指针数组中的每个函数指针均指向对应的函数;
35.替换模块,用于将所述指针数组中的第一函数指针和第二函数指针进行替换;
36.运行模块,用于基于所述第二函数指针调用所述第一函数指针的对应函数,以运行所述程序。
37.第三方面,本发明实施例还提供了一种电子设备,包括处理器和存储器,所述存储器耦接到所述处理器,所述存储器存储指令,当所述指令由所述处理器执行时使所述电子设备执行第一方面中任一项所述方法的步骤。
38.第四方面,本发明实施例还提供了一种计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现第一方面中任一项所述方法的步骤。
39.本发明的一种程序的运行方法和装置与现有技术相比,具有以下优点:
40.本发明的运行方法通过获取程序的指针数组,将指针数组中的第一函数指针和第二函数指针进行替换,使第一函数指针和第二函数指针指向的函数与开放源代码存在差异,基于第二函数指针调用第一函数指针的对应函数时,使程序运行使用的对应函数既能保证正常使用,同时具有一定的隐蔽性,若程序被反编译,无法直接从反编译代码中看出程
序使用第二函数指针对应函数的调用意图,进而提高了程序运行的安全性。
附图说明
41.为了更清楚地说明本说明书实施例或现有技术中的技术方案,下面将对实施例中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本说明书的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
42.图1为本发明实施例提供的一种程序的运行方法的流程图;
43.图2为本发明实施例提供的一种程序的运行装置的结构示意图。
具体实施方式
44.下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整的描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例,基于本发明实施例,本领域普通技术人员所获得的所有其他实施例,都属于本发明实施例保护的范围。
45.目前在安卓系统的jni中,java层交换数据和核心接口的调用,是通过调用核心系统函数来实现,由于核心系统函数是开源的,其在核心系统函数列表中的位置是固定的,因此通过反编译so文件后,查看系统核心函数调用特征的汇编代码,则可以看出其调用了哪些系统核心函数,再基于系统函数的固定位置,黑色产业可以针对性开发应用工具,直接将所有系统函数的调用进行识别,且具有极大的反编译破解速度,对程序的安全运行造成较大威胁。下面本发明实施例将以安卓系统中的jnienv结构体为例,如何保障程序的安全运行。
46.请参阅图1,图1为本发明实施例提供的一种程序的运行方法的流程图,所述方法包括:
47.s11、获取程序的指针数组,其中,所述指针数组中的每个函数指针均指向对应的函数。
48.具体的,指针数组中所有元素的数据类型相同,指针数组的每个数组元素为函数指针,每个函数指针指向对应的函数,在程序中需要实现某种功能或运算,通过函数指针调用对应的函数即可。获取指针数组后进入步骤s12。
49.s12、将所述指针数组中的第一函数指针和第二函数指针进行替换。
50.具体的,第一函数指针和第二函数指针均为指针数组中的指针,进行替换后,第一函数指针和第二函数指针的指向发生变化,即第一函数指针指向第二函数指针对应的函数,而第二函数指针指向第一函数指针对应的函数,以产生调用过程中的混淆效果,与程序的开放源代码产生差异,第一函数指针和第二函数指针指向的函数可以功能相同,也可以不同,能够进行替换混淆即可。对第一函数指针和第二函数指针进行替换后进入步骤s13。
51.s13、基于所述第二函数指针调用所述第一函数指针的对应函数,以运行所述程序。
52.具体的,程序在运行过程中,需要对第二函数指针进行调用,以实现对应的功能,由于第二函数指针和第一函数指针进行了替换,指针对应的函数也会对应发生变化,若需
要调用第一函数指针的对应函数,则需要调用第二函数指针进行实施,通过指针替换产生混淆,即使对程序实施破解操作,也不能从反编译代码中看出程序使用的目的,对于黑客而言,由于采用了混淆方案,无法获知系统函数的真实调用路径,黑客无法破解开发者的意图,进而提高了程序运行的安全性。可以理解,由于第一函数指针和第二函数指针进行了替换,也可以根据程序的应用需求,通过第一函数指针调用第二函数指针的对应函数,若无第二函数指针的对应函数应用需求,也可以不进行调用。
53.在实际应用时,由于第一函数指针和第二函数指针均指向对应的函数,实现程序的运行功能,若第一函数指针和第二函数指针分别指向函数的功能存在较大差异,例如在开放源代码中,第一函数指针指向的函数功能为调用,第二函数指针指向的函数功能为属性获取,如果此时将第一函数指针和第二函数指针进行调换,则可能易于被黑客识破,而导致黑客采用其他的手段破解函数,基于此,在一种具体的实施方式中,获取程序的指针数组,包括:
54.基于程序的开发源码,获得包含指针数组的目标结构体;根据指针数组中第一函数指针的运行路径,获得与原始函数的功能相同的替换函数,其中,原始函数为第一函数指针在目标结构体中指向的函数;根据第一函数指针和替换函数对应的第二函数指针,获得指针数组。
55.具体的,程序的开发源码可以为官方系统的开放源代码,例如安卓系统的开放源代码;也可以为公知的程序开发代码,目标结构体可以为系统程序的核心结构体,也可以为其他需要实施保护的结构体,目标结构体中包含指针数组,在开发源码中,每个函数指针指向对应的函数,目标结构体中第一函数指针指向的函数为原始函数。开发源码通常较为庞大,一种功能可以采用多种不同的函数实现,通过开发源码中第一函数指针的运行路径,可以确定该第一函数指针的整个使用过程,包括创建、使用和释放,基于第一函数指针的运行路径确定出能够与原始函数互换的替换函数,替换函数可以是一个或多个,原始函数与替换函数的功能相同,在替换后实现功能混淆,保证混淆效果更真实,避免被黑客识破。可以理解,为提高程序运行的稳定性,降低程序保护的实施成本,可以在开发源码中寻找稳定兼容性好,成本不高的,不易于出错的替换函数。确定出替换函数后,基于第一函数指针和替换函数对应的第二函数指针,获得指针数组。
56.例如在安卓系统中,jni层的运行和注册,均需要使用指针jnienv,通过它调用jni的函数,以访问java虚拟机,进而操作java对象,jnienv首先指向一个线程相关的结构体,该结构体又指向一个指针数组,在这个指针数组中的每个元素最终指向一个jni函数,所以可以通过jnienv去调用jni的函数。可以将包含jnienv的结构体定义为目标结构体,存储了所有jni层需要使用的函数指针,该结构体的数据结构如下:
57.struct_jnienv{
58.const struct jninativeinterface*functions;
59.#if defined(__cplusplus)
60.jint getversion()
61.{return functions-》getversion(this);}
62.jclass findclass(const char*name)
63.{return functions-》findclass(this,name);}}
64.为便于表述,省略了其他函数,仅示出两个函数进行示意,示出的函数包括getversion()和findclass(const char*name)。声明时*表示指针,从上述结构体中,可以发现该结构体存储了一个指针functions。
65.在基于c++的编程开发语言中,额外包装了一层c++的函数调用接口,其最终函数调用的functions函数指针中的接口。
66.const struct jninativeinterface*functions的数据结构如下:
67.struct jninativeinterface{
68.void*
ꢀꢀꢀꢀꢀꢀꢀ
reserved0;
69.void*
ꢀꢀꢀꢀꢀꢀꢀ
reserved1;
70.void*
ꢀꢀꢀꢀꢀꢀꢀ
reserved2;
71.void*
ꢀꢀꢀꢀꢀꢀꢀ
reserved3;
72.jint
ꢀꢀꢀꢀꢀꢀꢀꢀ
(*getversion)(jnienv*);
73.jclass
ꢀꢀꢀꢀꢀꢀ
(*findclass)(jnienv*,const char*);
74.此处省略其他函数 }
75.通过该数据结构可以看出指针functions是一个struct jninativeinterface的数据结构,而struct jninativeinterface中则存储的是一系列的函数指针,其中,在该结构体的头部void*reserved存储了4个保留的函数指针,以便于后续其他用途。
76.通过上述内容可知在目标结构体中,指针数组中的每个指针指向该结构体对应的函数,需要调用对应的函数时,通过指针指向该函数进行调用即可。
77.在一种具体的实施方式中,根据指针数组中第一函数指针的运行路径,获得与原始函数的功能相同的替换函数,包括:
78.根据第一函数指针在目标结构体的创建记录,获得运行路径的创建路径;根据第一函数指针在目标结构体的初始化记录,获得运行路径的初始化路径;根据第一函数指针在目标结构体的调用记录,获得运行路径的调用链路径;根据创建路径、初始化路径和调用链路径,在开发源码的函数库中确定替换函数。
79.具体的,创建路径、初始化路径和调用链路径表征了第一函数指针的使用过程,例如据此可以得出第一函数指针的数据变量类型等信息,结合其特点在函数库中确定出替换函数,替换函数与原始函数的功能相同,确定的替换函数需要保障不发生编译错误,以实现正常替换。
80.在安卓系统中,jnienv是通过java虚拟机javavm的接口getenv来获取的,因此首要的则是分析接口getenv创建jnienv这个环境变量的过程,同时查看jnienv这个环境变量的初始化的过程,以及其中所有的系统核心函数整个调用链的过程,以确定出替换函数。
81.仍然以目标结构体jnienv中的指针functions为例,其赋值过程如下:
82.const jninativeinterface gjninativeinterface={
83.null,//reserved0.
84.null,//reserved1.
85.null,//reserved2.
86.null,//reserved3.
87.jni::getversion,
88.jni::findclass,
89.此处省略其他函数}
90.可以看到该代码中定义了一个const jninativeinterface gjninativeinterface变量,并对其中存储的函数指针进行了赋值操作,其中定义的函数指针是一一进行具体函数赋值操作的。
91.jni函数的具体实现过程如下:
92.class jni{
93.public:
94.static jint getversion(jnienv*){
95.return jni_version_1_6;}}
96.可以理解,最终的函数实现是在类jni中的通过静态函数来实现getversion,即类jni中则会把上述定义的所有的函数全部运行一次,而其中gjninativeinterface这个变量则会存储所有的这些函数指针。
97.指针functions赋值如下:
98.functions=&gjninativeinterface;
99.那么最终jnienv中的指针functions通过使用的是类jni中的函数来赋值对应的。
100.需要说明的是,jnienv中创建的指针,可以通过如下函数获取:
101.vm-》getenv(&env,jni_version_1_4)
102.该函数是jnienv中创建指针变量的实际函数,因此可以对此函数进行钩取(或称hook)操作,从而可以在源代码中确定到所有的指针变量的创建,从而可以对所有创建的指针变量对应的所有函数进行混淆,而通过钩取操作,对开发人员而言混淆操作更加透明化,避免人为开发而遗漏。虽然每次调用getenv都会创建一个新的jnienv变量,但是所有的jnienv变量中存储的functions=&gjninativeinterface;则都是基于gjninativeinterface来赋值的,所以修改了一个jnienv变量中的functions,那么意味着后续所有创建出来的jnienv变量中的functions都被修改替换,因此在jnienv结构体运行时,有且只能执行一次指针的替换。
103.在一种具体的实施方式中,将指针数组中的第一函数指针和第二函数指针进行替换,包括:
104.根据程序中函数的功能定义,进行函数类别划分;在第一函数指针指向函数的函数类别中,确定出替换函数和对应的第二函数指针;将第一函数指针的第一变量和第二函数指针的第二变量进行替换。
105.具体的,功能定义表征的是函数在程序中的执行功能,或目标结构体中的执行功能,例如创建变量和资源释放是通过不同动能定义的函数实现的,功能定义的一个类别存在多个函数,对函数进行函数类别划分,能够使指针数组中各指针对应的函数功能更清晰,便于进行同类功能函数的混淆,替换时按照同类型间进行替换混淆更具有隐蔽性。例如在对函数调用时,原本是调用一个callbytemethodv不带返回值的静态函数,并且参数是byte类型,那么混淆替换时callfloatmethodv使用浮点数的类型来替换,则更真实。而如果用其他完全无关联的功能函数进行替换,则可能易于被黑客识破。第一变量和第二变量可以通过整数、字符串或数组等进行表征,能够易于进行混淆即可。
106.基于上述对开放源代码的分析,可以发现函数指针是以变量进行存储的,即目标结构体中存储的都是函数指针对应的变量,因此,所有函数其存储函数指针的大小都是固定的,同时函数指针指向的是其对应的函数,就可以通过替换函数指针的变量来指向其他的函数,从而可以实现对替换函数的调用,通过第一函数指针的第一变量和第二函数指针的第二变量进行替换,修改的是变量的内存数据,而不是针对函数代码进行修改,不需要修改代码的执行属性,那么就不存在需要修改程序的代码,降低了程序编译报错的风险。
107.在实际实施时,可以设计算法来对上述已经分类的函数在该类别中进行混淆替换,基于每个分类可以使用不同的算法进行混淆。
108.基于上述的分类来创建出obfuscatefunction一个数组来存储所有的函数。对jninativeinterface中的每个函数指针,则可以创建一个obfuscatefunction的变量。最终对所有的函数指针都创建完成后则会存储到一个数组中。
109.obfuscatefunction array[];array则是对应的数组。
[0110]
例如对于findclass函数,则创建一个obfuscatefunction的变量。
[0111]
obfuscatefunction array[5];其中其对应于函数列表的第5个函数指针。
[0112]
array[5].type=core;此函数则属于核心类型。
[0113]
array[5].index=5;此函数则在该列表的第5项。
[0114]
其中,array的元素的顺序也是和原始的jninativeinterface中的函数顺序是一致对应的。
[0115]
接下来从obfuscatefunction中过滤出各种的类型并单独存放到一起。
[0116]
obfuscatefunction coretype_array[];存放所有的core类型。
[0117]
obfuscatefunction calltype_array[];则存放所有的call类型。
[0118]
通过该种方式可以将所有的类型进行分类存放,对于每种类型的函数则可以在该类型进行混淆。
[0119]
在一种具体的实施方式中,根据程序中函数的功能定义,进行函数类别划分,包括:
[0120]
根据功能定义对应生成类别变量,其中,功能定义包括调用函数、属性获取函数、属性设置函数、异常处理函数、创建函数和资源释放函数;将类别变量存储为函数类别的索引。
[0121]
具体的,为使函数划分的更有序更易识别,根据定义功能对应生成类别变量,类别变量表征的是该种功能函数对应的变量,将类别变量存储为函数类别的索引,例如创建一数组enum type来存储类别变量。
[0122]
enum type{
[0123]
call=1,//调用函数
[0124]
get=2,//属性获取函数
[0125]
set=3,//属性设置函数
[0126]
except=4,//异常处理函数
[0127]
create=5,//创建函数
[0128]
release=6,//资源释放函数
[0129]
core=7,//findclass等一类
[0130]
other=8,//不属于上述所有类型
[0131]
}
[0132]
通过数组enum type将函数根据定义功能进行枚举分类,同时定义obfuscatefunction结构体存储每一个函数指针,其结构如下:
[0133]
struct obfuscatefunction{
[0134]
type t;
[0135]
uint index;}
[0136]
其中,type t为定义的类别变量,用来区分此函数的类型;uint index为变量,用来记录该函数对应于数组enum type中的索引。
[0137]
在一种具体的实施方式中,将第一函数指针的第一变量和第二函数指针的第二变量进行替换,包括:
[0138]
将第一变量和第二变量组成的数组,输入预设的算法模型;将算法模型输出的随机数组,确定第一变量和第二变量的替换次序,根据替换次序对第一变量和第二变量进行替换。
[0139]
具体的,将第一变量和第二变量进行替换为混淆操作,在混淆算法上就是对序号进行混淆替换,例如当变量为整数时,将5号和18号进行替换,那么主要就是进行替换的算法。同时需要在分类中进行替换。在上面的步骤中将分类分别取出来,那么进行替换时,值需要在这分类的序号中进行替换即可。
[0140]
例如定义功能相同的函数存储的为{5,15,23,40,78},进行混淆时是对这些序号进行替换打乱,从而最终使混淆后调用的函数和混淆前调用的函数存在差异。
[0141]
替换算法既可以将上面的数据存储到一个数组中,然后使用系统提供的随机算法来对数组的内容进行随机打乱,那么最终出来的结果则会和之前不一样。例如将上述数组输入算法模型后,算法模型输出的随机数组为{40,78,5,15,23}。可以看出,40号与5号的函数对应替换,78号与15号的函数对应替换,5号与23号的函数对应替换,15号与40号的函数对应替换。
[0142]
假设5号的函数和15号的函数进行替换,需要先取出原始数据存储到temp变量中,然后将混淆的进行存储,最后存储原始值,即:
[0143]
void*temp=(void*)functions[5];
[0144]
(void*)functions[5]=(void*)functions[15];
[0145]
(void*)functions[15]=temp;
[0146]
上述三个步骤完成了5号的函数指针和15号的函数指针的替换,在进行替换时,由于的替换方案是替换的函数指针,所以可以直接以函数指针替换,而不以函数指针的原型(代码)替换,避免了混淆代码导致的编译报错,函数指针全部以void*类型来替代,void*则是指代所有类型的函数指针。
[0147]
在一种具体的实施方式中,基于第二函数指针调用第一函数指针的对应函数,包括:
[0148]
根据第二函数指针的变量值和预设的函数指针列表,确定第一函数指针对应函数的函数地址,其中,函数指针列表为函数指针和函数地址的对应关系表;根据函数地址调用第一函数指针的对应函数。
[0149]
具体的,函数指针列表表征了混淆后,函数指针和函数地址的对应关系,通过第二函数指针的变量值和在函数指针列表进行查找,即可确定出第一函数指针对应函数的函数地址,通过该函数地址即可调用第一函数指针的对应函数。
[0150]
以函数指针clazz,函数findclass为例,没替换之前的调用:clazz=env-》findclass(classname),env为函数指针clazz的变量值,classname为函数名。
[0151]
替换后的调用:由于未混淆前,原始的env-》指向的是函数findclass的原函数地址,调用函数findclass的语句为:
[0152]
jclass(*findclass)(jnienv*,const char*);jclass为函数findclass的返回值类型。
[0153]
jint(*unregisternatives)(jnienv*,jclass);jint为函数unregisternatives的返回值类型。
[0154]
可以理解,函数findclass和函数unregisternatives调用时其返回值类型不会发生变化,混淆时对两者的函数指针进行替换,为确保函数可以成功调用,需要对两者的函数指针进行强制类型的转换后再调用。
[0155]
具体调用过程如下:获取env的环境变量的内存函数指针列表*(void*)env[0];该值则是函数列表的首地址,那么其他的函数地址则依据序号进行计数相加得到对应的函数地址。
[0156]
其中原始的findclass则对应于第5个序号从0开始,而每个函数指针需要占据8个字节的存储空间,因此,通过*(void*)env[0]+(5+1)
×
8计算地址的值;此值在没有混淆之前计算的则是findclass的函数内存地址。
[0157]
那么基于混淆后的情况下,首先需要知道函数findclass被混淆存储到对应的数据结构,然后获取其返回值(或称index),然后重新计数得到值然后进行调用。
[0158]
新值的计算如下:
[0159]
*(void*)env[0]+(new_index+1)
×
8;计算结果则是混淆后的findclass的函数地址。那么则调用此函数地址则对应于调用函数findclass,将每个函数对应混淆后的值存储到了一个数组中,以进行准确的调用。
[0160]
基于与运行方法同样的发明构思,本发明实施例还提供了一种程序的运行装置,请参阅图2,所述装置包括:
[0161]
获取模块201,用于获取程序的指针数组,其中,所述指针数组中的每个函数指针均指向对应的函数;
[0162]
替换模块202,用于将所述指针数组中的第一函数指针和第二函数指针进行替换;
[0163]
运行模块203,用于基于所述第二函数指针调用所述第一函数指针的对应函数,以运行所述程序。
[0164]
在一种可选的实施例中,所述获取模块,包括:
[0165]
第一获得子模块,用于基于所述程序的开发源码,获得包含所述指针数组的目标结构体;
[0166]
第二获得子模块,用于根据所述指针数组中第一函数指针的运行路径,获得与原始函数的功能相同的替换函数,其中,所述原始函数为所述第一函数指针在所述目标结构体中指向的函数;
[0167]
第三获得子模块,用于根据所述第一函数指针和所述替换函数对应的第二函数指针,获得所述指针数组。
[0168]
在一种可选的实施例中,所述第二获得子模块,包括:
[0169]
第一获得单元,用于根据所述第一函数指针在所述目标结构体的创建记录,获得所述运行路径的创建路径;
[0170]
第二获得单元,用于根据所述第一函数指针在所述目标结构体的初始化记录,获得所述运行路径的初始化路径;
[0171]
第三获得单元,用于根据所述第一函数指针在所述目标结构体的调用记录,获得所述运行路径的调用链路径;
[0172]
第一确定单元,用于根据所述创建路径、所述初始化路径和所述调用链路径,在所述开发源码的函数库中确定所述替换函数。
[0173]
在一种可选的实施例中,所述替换模块,包括:
[0174]
划分子模块,用于根据所述程序中函数的功能定义,进行函数类别划分;
[0175]
第一确定子模块,用于在所述第一函数指针指向函数的所述函数类别中,确定出替换函数和对应的所述第二函数指针;
[0176]
替换子模块,用于将所述第一函数指针的第一变量和所述第二函数指针的第二变量进行替换。
[0177]
在一种可选的实施例中,所述划分子模块,包括:
[0178]
生成单元,用于根据所述功能定义对应生成类别变量,其中,所述功能定义包括调用函数、属性获取函数、属性设置函数、异常处理函数、创建函数和资源释放函数;
[0179]
储存单元,用于将所述类别变量存储为所述函数类别的索引。
[0180]
在一种可选的实施例中,所述替换子模块,包括:
[0181]
输入单元,用于将所述第一变量和所述第二变量组成的数组,输入预设的算法模型;
[0182]
第二确定单元,用于将所述算法模型输出的随机数组,确定所述第一变量和所述第二变量的替换次序;
[0183]
替换单元,用于根据所述替换次序对所述第一变量和所述第二变量进行替换。
[0184]
在一种可选的实施例中,所述运行模块,包括:
[0185]
第二确定子模块,用于根据所述第二函数指针的变量值和预设的函数指针列表,确定所述第一函数指针对应函数的函数地址,其中,所述函数指针列表为函数指针和函数地址的对应关系表;
[0186]
调用子模块,用于根据所述函数地址调用所述第一函数指针的对应函数。
[0187]
基于与运行方法同样的发明构思,本发明实施例还提供了一种电子设备,包括处理器和存储器,所述存储器耦接到所述处理器,所述存储器存储指令,当所述指令由所述处理器执行时使所述电子设备执行运行方法中任一项所述方法的步骤。
[0188]
基于与运行方法同样的发明构思,本发明实施例还提供了一种计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现运行方法中任一项所述方法的步骤。
[0189]
本发明实施例中提供的技术方案,至少具有如下技术效果或优点:
[0190]
通过获取程序的指针数组,将指针数组中的第一函数指针和第二函数指针进行替换,使第一函数指针和第二函数指针指向的函数与开放源代码存在差异,基于第二函数指针调用第一函数指针的对应函数时,使程序运行使用的对应函数既能保证正常使用,同时具有一定的隐蔽性,若程序被反编译,无法直接从反编译代码中看出程序使用第二函数指针对应函数的调用意图,进而提高了程序运行的安全性。
[0191]
本领域内的技术人员应明白,本发明的实施例可提供为方法、系统、或计算机程序产品。因此,本发明可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本发明可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、cd-rom、光学存储器等)上实施的计算机程序产品的形式。
[0192]
本发明是参照根据本发明实施例的方法、装置(模块、系统)、和计算机程序产品的流程图和/或方框图来描述。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式计算机或者其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
[0193]
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
[0194]
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
[0195]
尽管已描述了本发明的优选实施例,但本领域内的技术人员一旦得知了基本创造概念,则可对这些实施例作出另外的变更和修改。所以,所附权利要求意欲解释为包括优选实施例以及落入本发明范围的所有变更和修改。
[0196]
显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包括这些改动和变型在内。

技术特征:
1.一种程序的运行方法,其特征在于,所述方法包括:获取程序的指针数组,其中,所述指针数组中的每个函数指针均指向对应的函数;将所述指针数组中的第一函数指针和第二函数指针进行替换;基于所述第二函数指针调用所述第一函数指针的对应函数,以运行所述程序。2.根据权利要求1所述的程序的运行方法,其特征在于,所述获取程序的指针数组,包括:基于所述程序的开发源码,获得包含所述指针数组的目标结构体;根据所述指针数组中第一函数指针的运行路径,获得与原始函数的功能相同的替换函数,其中,所述原始函数为所述第一函数指针在所述目标结构体中指向的函数;根据所述第一函数指针和所述替换函数对应的第二函数指针,获得所述指针数组。3.根据权利要求2所述的程序的运行方法,其特征在于,所述根据所述指针数组中第一函数指针的运行路径,获得与原始函数的功能相同的替换函数,包括:根据所述第一函数指针在所述目标结构体的创建记录,获得所述运行路径的创建路径;根据所述第一函数指针在所述目标结构体的初始化记录,获得所述运行路径的初始化路径;根据所述第一函数指针在所述目标结构体的调用记录,获得所述运行路径的调用链路径;根据所述创建路径、所述初始化路径和所述调用链路径,在所述开发源码的函数库中确定所述替换函数。4.根据权利要求1所述的程序的运行方法,其特征在于,所述将所述指针数组中的第一函数指针和第二函数指针进行替换,包括:根据所述程序中函数的功能定义,进行函数类别划分;在所述第一函数指针指向函数的所述函数类别中,确定出替换函数和对应的所述第二函数指针;将所述第一函数指针的第一变量和所述第二函数指针的第二变量进行替换。5.根据权利要求4所述的程序的运行方法,其特征在于,所述根据所述程序中函数的功能定义,进行函数类别划分,包括:根据所述功能定义对应生成类别变量,其中,所述功能定义包括调用函数、属性获取函数、属性设置函数、异常处理函数、创建函数和资源释放函数;将所述类别变量存储为所述函数类别的索引。6.根据权利要求4所述的程序的运行方法,其特征在于,所述将所述第一函数指针的第一变量和所述第二函数指针的第二变量进行替换,包括:将所述第一变量和所述第二变量组成的数组,输入预设的算法模型;将所述算法模型输出的随机数组,确定所述第一变量和所述第二变量的替换次序;根据所述替换次序对所述第一变量和所述第二变量进行替换。7.根据权利要求1所述的程序的运行方法,其特征在于,所述基于所述第二函数指针调用所述第一函数指针的对应函数,包括:根据所述第二函数指针的变量值和预设的函数指针列表,确定所述第一函数指针对应
函数的函数地址,其中,所述函数指针列表为函数指针和函数地址的对应关系表;根据所述函数地址调用所述第一函数指针的对应函数。8.一种程序的运行装置,其特征在于,所述装置包括:获取模块,用于获取程序的指针数组,其中,所述指针数组中的每个函数指针均指向对应的函数;替换模块,用于将所述指针数组中的第一函数指针和第二函数指针进行替换;运行模块,用于基于所述第二函数指针调用所述第一函数指针的对应函数,以运行所述程序。9.一种电子设备,其特征在于,包括处理器和存储器,所述存储器耦接到所述处理器,所述存储器存储指令,当所述指令由所述处理器执行时使所述电子设备执行权利要求1-7中任一项所述方法的步骤。10.一种计算机可读存储介质,其上存储有计算机程序,其特征在于,该程序被处理器执行时实现权利要求1-7中任一项所述方法的步骤。

技术总结
本发明公开了一种程序的运行方法、装置、电子设备及介质,运行方法通过获取程序的指针数组,将指针数组中的第一函数指针和第二函数指针进行替换,使第一函数指针和第二函数指针指向的函数与开放源代码存在差异,基于第二函数指针调用第一函数指针的对应函数时,使程序运行使用的对应函数既能保证正常使用,同时具有一定的隐蔽性,若程序被反编译,无法直接从反编译代码中看出程序使用第二函数指针对应函数的调用意图,进而提高了程序运行的安全性。性。性。


技术研发人员:周志刚
受保护的技术使用者:武汉斗鱼鱼乐网络科技有限公司
技术研发日:2022.08.10
技术公布日:2022/12/8
转载请注明原文地址: https://bbs.8miu.com/read-399720.html

最新回复(0)