指令级代码复用分析方法及指令级代码复用方法

文档序号:31929732发布日期:2022-10-25 23:58阅读:123来源:国知局
指令级代码复用分析方法及指令级代码复用方法

1.本发明属于代码分析与复用领域,更具体地,涉及指令级代码复用分析方法及指令级代码复用方法。


背景技术:

2.代码复用是对目标代码中现有的代码片段(gadgets)进行重复利用的技术,gadgets来源于目标程序的合法代码片段,天然可执行,能自然绕开或dep防御机制,大大提升了代码复用能力,为代码保护提供新思路,也为代码深度投毒分析开辟新的技术手段;目前针对代码复用的研究主要是基于控制数据的代码复用,典型的基于控制数据的代码复用技术有rop(return-oriented programming)和jop(jump-oriented programming)。rop的思想主要从已有的库或可执行文件中提取以ret结尾的指令片段作为gadgets,利用栈溢出漏洞将需要串起来的指令片段的地址序列和值按照设定的顺序填充到栈空间中,通过ret指令将可以复用的gadgets串接起来,实现图灵完备的功能。jop则用间接call和间接jmp指令结束的代码片段来构造恶意代码。基于控制数据的代码复用有个重要的特征:改变程序执行控制流。随着控制流完整性(control-flow integrity,cfi)机制的部署,基于控制数据的代码复用越发困难。
3.目前有学者将代码复用投向的非控制数据领域,基于非控制数据的代码复用可以在不改变程序控制流的前提下实现代码复用,然而,现有非控制数据领域的代码复用存在三个问题:第一,代码复用分析的粒度局限在中间代码表示级,复用分析精确度低;第二,代码复用采用基于静态的代码分析技术,搜索出来的gadgets可达性低;第三,非控制数据攻击可以在不改变程序的控制流的前提下,实现代码的复用攻击,其隐蔽性强,难以检测,并且,攻击者还可以巧妙的借助代码规模的复杂化做掩护,将攻击事先埋入其中,进一步增加了攻击被发现的难度,这也使得现有的基于非控制数据的代码复用方法难以实现基于二进制层面的代码复用攻击的检测。


技术实现要素:

4.针对现有技术的缺陷和改进需求,本发明提供了一种指令级代码复用分析方法及指令级代码复用方法,其目的在于,实现指令级代码复用分析,以提高代码复用精度,确保搜索出的gadgets具备可达性,同时利于代码投毒分析。
5.为实现上述目的,按照本发明的一个方面,提供了一种指令级代码复用分析方法,用于在不改变控制流的情况下识别出目标二进制代码中的可复用gadgets并求解对应的路径约束值;gadgets为实现目标基本操作的代码片段,目标基本操作包括算术操作、赋值操作和解引用操作;该方法包括:
6.(s1)通过在目标二进制代码的每条指令处插桩第一回调函数的方式,识别出目标二进制代码中的gadgets,得到初始gadgets集合;
7.第一回调函数用于对指令进行分析,并基于指令分析结果搜索目标二进制代码中
的gadgets;
8.(s2)通过动态污点分析技术从初始gadgets集合中筛选出被污染的gadgets,作为可用gadgets;
9.(s3)对于每一个可用gadgets,利用符号执行技术,获取目标二进制代码中从符号执行起点位置运行至该可用gadgets的执行路径,构建执行路径的路径约束表达式并求解得到路径约束值,若成功获取到执行路径并成功求解出路径约束值,则将该可用gadgets作为可复用gadgets;
10.(s4)将所有可复用gadgets及对应的路径约束值作为识别结果,识别结束。
11.进一步地,步骤(s3)中,对于任意一个可用gadgets,执行如下步骤:
12.(s31)将所选定的可用gadgets作为目标gadgets,并确定符号执行的起点位置;
13.(s32)将位于污点分析空间内的内存单元字节设置为符号变量,并将这些符号变量进行初始化;
14.污点分析空间为步骤(s2)中通过动态污点分析技术确定的被污染的内存空间;
15.(s33)获得目标二进制代码的静态控制流程图,以采用静态分析技术穷举目标二进制代码所有的执行路径,将其中无法到达目标gadgets的执行路径作为黑名单路径,保存到路径搜索配置文件中;将poc脚本执行过程中获取到的从符号执行起点位置到达目标gadgets的poc执行路径确定为白名单路径,写入路径搜索配置文件中;
16.(s34)利用符号执行引擎从符号执行起点位置开始执行目标二进制代码,并将路径搜索配置文件导入符号执行引擎,以使符号执行引擎在执行过程中根据黑名单路径和白名单路径实现启发式分支跳转;
17.(s35)若符号执行引擎在预设的跳转总数阈值和搜索深度阈值内,到达目标gadgets,则转入步骤(s36);否则,转入步骤(s37);
18.(s36)根据步骤(s32)中定义的符号变量,将到达目标gadgets的执行路径的约束条件符号化,得到路径约束表达式,求解路径约束表达式,得到目标gadgets的路径约束值;若求解成功,则判定目标gadgets为可复用gadgets,并转入步骤(s37);若求解不成功,且路径搜索配置文件中还存在未搜索过的路径,则转入步骤(s34),开始搜索下一条路径;若求解不成功,且路径搜索配置文件中不存在未搜索过的路径,则说明该gadgets不可复用,转入步骤(s37);
19.(s37)针对目标gadgets的分析结束。
20.进一步地,步骤(s34)中,符号执行引擎实现分支跳转时,优先跳转至位于poc执行路径上的gadgets。
21.进一步地,步骤(s2)中,动态污点分析中的污染源包括:外部输入和漏洞覆盖内存;
22.动态污点分析的污点传播规则如下:
23.对于加载元操作指令,若指令中的地址或地址的值是污染源或被污染,则指令中的寄存器被污染;
24.对于存储元操作指令,若指令中寄存器被污染,则指令中地址和地址的值被污染;
25.对于二元运算元操作指令,若指令中,至少一个寄存器被污染,则第一寄存器被污染;若仅第一寄存器被污染,则第二寄存器不被污染;
26.动态污点分析的执行方式为:在目标二进制代码中用户输入的api函数处进行动态插桩第二回调函数;第二回调函数用于对api函数进行分析,基于所定义的污染源和污点传播规则确定能够被污染的内存空间;
27.其中,第一寄存器和第二寄存器分别为二元运算元操作指令中的两个寄存器,并且第一寄存器为用于存储运算结果的寄存器。
28.按照本发明的另一个方面,提供了一种指令级代码复用方法,用于在不改变控制流的情况下实现对目标二进制代码的复用;该方法包括:
29.对于目标二进制代码,执行本发明提供的上述指令级代码复用分析方法,获得目标二进制代码中的可复用gadgets及相应的路径约束值;
30.建立目标二进制代码的内存污染依赖表;内存污染依赖表记录了污染源地址到污染目的地址的映射关系;
31.根据所需实现的复用功能,执行相应的复用策略;复用策略包括单个gadgets单次复用策略,其执行方式包括:
32.(a1)选取可实现复用功能的一个可复用gadgets,并获取其路径约束值;
33.(a2)通过程序输入或者漏洞利用的输入,输入所获取的路径约束值,到达所选取的可复用gadgets;
34.(a3)确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能。
35.进一步地,复用策略还包括单个gadgets多次复用策略,其执行方式包括:
36.(b1)选取可实现复用功能的一个可复用gadgets,并获取其路径约束值;
37.(b2)通过程序输入或者漏洞利用的输入,输入所获取的路径约束值,到达所选取的可复用gadgets;
38.(b3)确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能,完成一次复用;
39.(b4)根据需要执行的复用次数,多次执行步骤(b2)~(b3),实现单个gadgets多次复用。
40.进一步地,复用策略还包括多个gadgets单次复用策略,其执行方式包括:
41.(c1)选取可实现复用功能且满足复用条件的多个可复用gadgets,并获取各可复用gadgets的路径约束值;
42.复用条件为:前置gadgets中存储元操作的地址与后继gadgets中加载元操作的地址相同;所选取的多个可复用gadgets中,先、后执行的可复用gadgets分别为前置gadgets和后继gadgets;
43.(c2)按照前置和后继关系,将所选取的可复用gadgets有序组织到一起;
44.(c3)按序依次到达所选取的可复用gadgets,每次到达可复用gadgets后,确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能;所有选取的可复用gadgets执行完成后,实现多个gadgets单次复用;
45.其中,到达可复用gadgets的方式为:通过程序输入或者漏洞利用的输入,输入该可复用gadgets的路径约束值,到达该可复用gadgets。
46.进一步地,复用策略还包括多个gadgets多次复用策略,其执行方式包括:
47.(d1)选取可实现复用功能且满足复用条件的多个可复用gadgets,并获取各可复用gadgets的路径约束值;
48.(d2)按照前置和后继关系,将所选取的可复用gadgets有序组织到一起;
49.(d3)按序依次到达所选取的可复用gadgets,每次到达可复用gadgets后,确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能;所有选取的可复用gadgets执行完成后,实现多个gadgets一次复用;
50.到达可复用gadgets的方式为:通过程序输入或者漏洞利用的输入,输入该可复用gadgets的路径约束值,到达该可复用gadgets;
51.(d4)根据需要执行的复用次数,多次执行步骤(d3),实现多个gadgets多次复用。
52.进一步地,步骤(c1)和步骤(d1)还包括:
53.若所选取的多个可复用gadgets中,存在前置gadgets和后继gadgets不满足复用条件的情况,则判断前置gadgets中存储元操作的地址和后继gadgets中加载元操作的地址是否均在污点分析空间中,若是,则将前置gadgets中存储元操作的地址和后继gadgets中加载元操作的地址修改为一致,以保证所选取的多个可复用gadgets满足复用条件。
54.进一步地,内存污染依赖表的建立方式包括:
55.在第一回调函数中增加利用五元组《污染源编号,污染源地址,污染目的地址,源染色序列,目的染色序列》记录各指令中地址关系,其中,污染源编号用于唯一标识污染源;污染源地址和污染目的地址分别为污染源在内存中的地址和被污染的内存单元地址;源染色序列和目的染色序列分别是污染源地址和污染目的地址染色后的序列值;
56.每执行一条指令,则更新相应的五元组,所有指令执行结束后,完成一轮染色,执行至少轮染色后,筛选出源染色序列和目的染色序列相同的五元组,提取其中的污染源地址和污染目的地址,建立映射关系并记录到内存污染依赖表中;n表示染色所使用的颜色总数,t表示污染源编号的字节总数,表示向上取整;
57.每一轮染色包括如下步骤:
58.(t0)将第一条指令作为当前指令;
59.(t1)若当前指令中包含污染源,则将污染源编号和污染源在内存中的地址更新到五元组中,并转入步骤(t2);否则,转入步骤(t3);
60.(t2)对污染源编号进行染色,得到源染色序列,并更新到五元组中;对污染源染色的方式为:
61.预先定义n种不同的颜色,对应的颜色编号依次为1~n;
62.对污染源内存地址以字节为单位,依次染色为第1~n种颜色,根据并污点传播规则对污染目的地址进行染色,得到源染色序列和目的染色序列,并更新到五元组中;
63.(t3)若还存在未执行的指令,则取当前指令的下一条指令,并转入步骤(t1);否则,当前的一轮染色结束。
64.总体而言,通过本发明所构思的以上技术方案,能够取得以下有益效果:
65.(1)本发明以二进制代码为代码复用的分析对象,并将其中实现算术操作、赋值操作和解引用操作的代码片段作为需要分析的单元,即gadgets,通过指令级动态插桩的方式对代码中的逐条指令进行分析,并结合动态污点分析技术和符号执行技术识别出可复用的gadgets并求解对应的路径约束值,该分析方法从非控制数据延伸到了指令级,仅需关注二进制代码层面有限的运行逻辑,而无需考虑源码复杂的逻辑关系和源码不同语言类型带来的差异,有效提高了代码复用的精度;并且,由于本发明在分析过程中,所定义的gadgets仅涉及加载元操作、存储元操作和运算元操作,并不涉及跳转元操作,能够保证分析得到的指令级代码复用路径严格遵循二进制代码原本的cfg控制流。总体而言,本发明在不改变二进制代码原本的cfg控制流的情况下,有效提高了代码复用的精度。
66.(2)本发明采用面向二进制层面的指令级动态插桩方式对二进制代码中的指令进行逐条分析,并进一步识别出其中的gadgets,这样搜索出来的gadgets本身具备可达性,因此,本发明能够保证搜索得到的gadgets具备可达性,并在代码复用分析过程中,无需进行gadgets可达性分析,简化了代码复用分析过程,提高了代码复用的分析效率。
67.(3)本发明采用面向二进制层面的指令级动态插桩方式对二进制代码中的指令进行逐条分析,并进一步识别出其中的gadgets,结合动态污点分析技术和符号执行技术识别出可复用的gadgets并求解对应的路径约束值,最终所确定的可复用gadgets以及到达这些gadgets的路径约束值更接近程序本源,基于这些代码复用分析结果,可以准确地对代码复用行为进行识别和定位,有利于实现更加隐蔽的代码投毒分析。
68.(4)本发明在分析过程中,所定义的gadgets是加载元操作、存储元操作和运算元操作按特定顺序组成的代码片段,所涉及的三类元操作对应的指令特征简单、明了、易于识别,相应地,本发明有效简化了gadgets的提取规则,从而能够高效、快速地从二进制代码中搜索出需要进一步分析的gadgets。
69.(5)本发明基于指令级代码复用分析结果,制定了多种指令级代码复用策略,包括单个gadgets单次复用策略、单个gadgets多次复用策略、多个gadgets单次复用策略以及多个gadgets多次复用策略,可以覆盖各种不同的实际复用需求。
70.总体而言,本发明能够有效解决现有的基于非控制数据的代码复用方法中所存在的复用分析精确度低、gadgets可达性低、攻击被发现的难度大的技术问题。
附图说明
71.图1为本发明实施例提供的指令级代码复用分析方法流程图;
72.图2为本发明实施例提供的多个gadgets单次复用策略的示意图;
73.图3为本发明实施例提供的目标二进制代码反汇编控制流程图;
74.图4为本发明实施例提供的目标二进制代码执行漏洞函数时栈空间布局图;
75.图5为本发明实施例提供的任意内存写入任意值功能复用语义内存与汇编代码示意图。
具体实施方式
76.为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对
本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。此外,下面所描述的本发明各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。
77.在本发明中,本发明及附图中的术语“第一”、“第二”等(如果存在)是用于区别类似的对象,而不必用于描述特定的顺序或先后次序。
78.为了解决现有的针对非控制数据的代码复用分析方法分析精确性低、搜索出来的gadgets可达性低且难以实现基于二进制层面的代码复用攻击的检测的技术问题,本发明提供了一种指令级代码复用分析方法及指令级代码复用方法,其整体思路在于:基于程序的执行机制,即无论规模多复杂的源代码,最终仍需变换成机器可以执行的二进制代码,直接以二进制代码作为代码复用的分析对象,在严格遵循二进制代码原本的cfg执行流的情况下,对二进制代码的漏洞进行利用,以识别出二进制代码中可复用的gadgets,即指定的代码片段,并确定到达可这些可复用gadgets的路径约束值;在此基础上,根据实际的复用需求,选取可复用gadgets,并结合相应的路径约束值对所选取的gadgets进行复用,实现指令级的代码复用。
79.本发明中,需要分析三类元操作指令,分别是存储元操作指令、加载元操作指令和运算元操作指令,这些元操作指令的特征形式化描述具备一定的通用性;以在x86_64架构的windows和linux操作系统,适合c/c++代码编译的二进制代码为例,这三类元操作指令的定义及二进制指令形式化描述分别如下:
80.(1)加载指令:定义为从某一个地址读取数据到某寄存器中的操作;二进制指令形式化描述为:
81.mov寄存器,地址
82.(2)存储指令:定义为将某寄存器的值存回某地址中,二进制指令形式化描述为:
83.mov地址,寄存器
84.(3)运算指令,分为二元运算指令和一元运算指令;二元运算指令,定义为将寄存器1和寄存器2的值,经过op运算,结果保存到寄存器1中,其中二元op操作符包含两大类:算术运算符和逻辑运算符,算术运算符包括add、sub、mul、div等,逻辑运算符包括and、or、xor等;二进制指令形式化描述为:
85.op寄存器1,寄存器2
86.一元运算指令,定义为将寄存器中的值经过op运算,结果保存到寄存器中;一元op运算符包括not等;二进制指令形式化描述为:
87.op寄存器
88.基于上述元操作指令,可实现特定功能的基本操作,本发明中,需要分析三种基本操作,分别是算术操作、赋值操作和解引用操作,这些元操作指令的特征形式化描述同样具备一定的通用性;同样以在x86_64架构的windows和linux操作系统,适合c/c++代码编译的二进制代码为例,这三类基本操作的基本定义及二进制指令形式化描述分别如下:
89.(1)算术操作:以加法运算为例,实现一个典型的加法运算,需要两个加载操作,一个加法运算操作和一个存储操作;二进制指令形式化定义如下:
90.mov寄存器1,地址1
91.mov寄存器2,地址2
92.add寄存器1,寄存器2
93.mov地址3,寄存器1
94.(2)赋值操作:实现赋值功能,需要一个加载操作,一个存储操作。二进制指令形式化定义如下:
95.mov寄存器1,地址1
96.mov地址2,寄存器1
97.(3)解引用操作:实现解引用操作,需要两个加载操作,一个存储操作,二进制指令形式化定义如下:
98.mov寄存器1,地址1
99.mov寄存器2,[寄存器1]
[0100]
mov地址2,寄存器2
[0101]
其中,[寄存器1]表示,把寄存器1中的值作为地址,将该地址的值取出来;地址1可以与地址2相同,也可以不同。
[0102]
本发明中,将实现上述三种基本操作,即算术操作、赋值操作和解引用操作的指令片段定义为gadgets,作为后续复用分析的基本单元;可以看到的是,本发明所定义的gadgets,只包括加载元操作指令、存储元操作指令和运算元操作指令,并不涉及跳转元操作指令,因此,代码复用不会改变二进制代码原本的cfg控制流。
[0103]
根据代码片段中的地址形式,可以将本发明所定义的gadgets分为三类:代码片段中的地址形式为“ebp-偏移量”(局部变量的地址),则该gadgets为局部gadgets;代码片段中的地址形式为“ebp+偏移量”(栈中地址),则该gadgets为参数gadgets;代码片段中的地址形式为一个确定的地址值(全局变量的地址),则该gadgets为全局gadgets;ebp表示栈基址。
[0104]
为便于对本发明技术方案进行更为清楚的解释,在以下实施例中,元操作指令和gadgets均采用上述特征定义。应当说明的是,在不同的架构下,元操作指令及gadgets的特征可能有所变化,以上仅为某一个特定架构下的特征定义,作为示例性说明,不应理解为对本发明的唯一限定。
[0105]
以下为实施例。
[0106]
实施例1:
[0107]
一种指令级代码复用分析方法,用于在不改变控制流的情况下识别出目标二进制代码中的可复用gadgets并求解对应的路径约束值;本实施中,gadgets为实现目标基本操作的代码片段,目标基本操作包括算术操作、赋值操作和解引用操作;
[0108]
参阅图1,本实施提供的指令级代码复用分析方法包括:
[0109]
(s1)通过在目标二进制代码的每条指令处插桩第一回调函数的方式,识别出目标二进制代码中的gadgets,得到初始gadgets集合;
[0110]
第一回调函数用于对指令进行分析,并基于指令分析结果搜索目标二进制代码中的gadgets;
[0111]
(s2)通过动态污点分析技术从初始gadgets集合中筛选出被污染的gadgets,作为可用gadgets;
[0112]
(s3)对于每一个可用gadgets,利用符号执行技术,获取目标二进制代码中从符号
执行起点位置运行至该可用gadgets的执行路径,构建执行路径的路径约束表达式并求解得到路径约束值,若成功获取到执行路径并成功求解出路径约束值,则将该可用gadgets作为可复用gadgets;
[0113]
(s4)将所有可复用gadgets及对应的路径约束值作为识别结果,识别结束。
[0114]
基于gadgets的定义,本实施例的步骤(s1)中,第一回调函数对指令进行分析,包括:识别指令是否是记载元操作指令、存储元操作指令和运算元操作指令;
[0115]
加载元操作指令的识别过程具体如下:
[0116]
第一步,对指令操作符进行判断,如果是mov操作符,则进行第二步判断;第二步,对第1个操作数进行判断,如果是寄存器,则进行第三步判断;第三步,对第2个操作数进行判断,如果是地址,则识别为一个加载元操作指令;
[0117]
存储元操作指令的识别过程具体如下:
[0118]
第一步,对指令操作符进行判断,如果是mov操作符,则进行第二步判断;第二步,对第1个操作数进行判断,如果是地址,则进行第三步判断;第三步,对第2个操作数进行判断,如果是寄存器,则识别为一个存储元操作指令;
[0119]
运算元操作指令的识别包括:
[0120]
对指令操作符进行判断,如果是一元op操作符,则进行一元运算元操作指令的识别,如果是二元op操作符,则进行二元运算元操作指令的识别;一元运算元操作指令的识别过程具体如下:
[0121]
第一步,对第1个操作数进行判断,如果是寄存器,则进行第二步判断;第二步,判断是否存在第2个操作数,如果不存在,则识别为一元运算元操作指令;
[0122]
二元运算元操作指令的识别过程具体如下:
[0123]
第一步,对第1个操作数进行判断,如果是寄存器,则进行第二步判断;第二步,判断是否存在第2个操作数,如果存在,则进行第三步判断;第三步,对第2个操作数进行判断,如果是寄存器,则识别为二元运算元操作指令。
[0124]
基于指令的分析结果,可以进一步对gadgets进行搜索:
[0125]
典型算术基本操作需要两个加载操作,一个加法运算操作和一个存储操作;算术基本操作识别过程包括:第一步:取第一条指令,判断该指令是否为加载指令,若是,则执行第二步;第二步,取第二条指令,判断该指令是否为加载指令,若是,则执行第三步;第三步,取第三条指令,判断该指令是否为某种op操作指令,若是,则执行第四步;第四步,取第四条指令,判断该指令是否为存储操作指令;如果以上四步全部符合,则将该四条指令识别为一个算术基本操作gadgets。
[0126]
典型赋值基本操作需要一个加载操作,一个存储操作;赋值基本操作识别过程包括:第一步:取第一条指令,判断该指令是否为加载操作指令,若是,则执行第二步;第二步,取第二条指令,判断该指令是否为存储操作指令;如果以上两步全部符合,则将该两条指令识别为一个赋值基本操作gadgets。
[0127]
典型解引用基本操作包含两个加载元操作,一个存储元操作;解引用基本操作识别过程包括:第一步:取第一条指令,判断该指令是否为加载操作指令,若是,则执行第二步;第二步,取第二条指令,判断该指令是否为加载指令,同时需要判断第2个操作数是否为第一条指令第1个操作数寄存器中的地址;如果以上两步全部符合,则将该两条指令识别为
一个解引用基本操作gadgets。
[0128]
需要说明的是,上述三种基本操作仅仅是典型的基本操作,在实际应用中,也可能存在一些变体,例如,其中一种变体的形式为第一条指令不变,但定义的后续(第二条、第三条、第四条等)的指令形式并非是第一条指令的直接后续指令,中间允许存在其他形式指令,只需要满足前置指令和后继指令之间,相关上下文不发生改变即可;在实际应用中,根据基本操作的具体形式完成gadgets的搜索即可。
[0129]
本实施例的步骤(s2)中,动态污点分析中的污染源包括:外部输入和漏洞覆盖内存;外部输入,即程序所有外部输入的数据;漏洞覆盖内存,即通过程序的漏洞覆盖,能够修改的所有非控制数据内存单元;
[0130]
动态污点分析的污点传播规则如下:
[0131]
对于加载元操作指令,其二进制指令形式化描述为“mov寄存器,地址”,若指令中的地址或地址的值是污染源或被污染,则指令中的寄存器被污染;
[0132]
对于存储元操作指令,其二进制指令形式化描述为“mov地址,寄存器”,若指令中寄存器被污染,则指令中地址和地址的值被污染;
[0133]
对于二元运算元操作指令,其二进制指令形式化描述为“op寄存器1,寄存器2”,若指令中,至少一个寄存器被污染,则第一寄存器(即寄存器1)被污染;若仅第一寄存器(即寄存器1)被污染,则第二寄存器(即寄存器2)不被污染;
[0134]
基于所定义的污染源和污点传播规则,本实施例中,动态污点分析的执行方式为:在目标二进制代码中用户输入的api函数处进行动态插桩第二回调函数;第二回调函数用于对api函数进行分析,基于所定义的污染源和污点传播规则确定能够被污染的内存空间;比如对系统调用read函数进行插桩,回调函数通过对read函数进行分析,获取read函数中buf的地址和函数返回值n,其中buf是污染范围的起始地址,n是污染范围的大小,则[buf,buf+n)内存空间即为污染源空间,利用所定义的污染传播规则进行数据流跟踪,即可获得污点分析空间;基于本实施例所定义的污点传播规则所确定的污点分析空间,既可以是漏洞所在栈帧的局部变量空间,也可以是其他栈帧的局部变量,还可以是目标代码data段的全局变量空间。
[0135]
在确定污点分析空间后,获取指令内存和数据内存地址,判断是否在该污点分析空间内,如果在空间内,则认为该内存被污染,如果不在空间内,则认为没有污染。若指令内存和数据内存地址中的任意一个被污染,则判断该指令被污染;若gadgets所对应的代码判断中,存在被污染的指令,则判断该gadgets被污染。
[0136]
本实施例所确定的污点分析空间是内存中复用者可控的空间,该空间为符号执行提供了可修改的内存信息。
[0137]
本实施例的步骤(s3),从所有被污染的gadgets中筛选出可复用的gadgets并计算到达可复用gadgets的路径约束,包括:获取污点内存区域,获取符号执行起点位置,获取符号执行输入信息,符号变量初始化,gadgets路径搜索策略,gadget路径搜索,符号执行仿真模拟,路径约束求解。
[0138]
具体地,对于任意一个可用gadgets,执行如下步骤:
[0139]
(s31)将所选定的可用gadgets作为目标gadgets,并确定符号执行的起点位置;
[0140]
符号执行的起点位置,可以是目标二进制代码中的任意位置,为了提高符号执行
的效率,作为一种优选的实施方式,本实施例中,具体以程序崩溃指令地址作为符号执行的起点位置,该起点位置的获取方式具体包括:
[0141]
运行目标二进制代码的漏洞poc脚本,并将poc脚本中的payload作为输入,以触发目标二进制代码的漏洞,使程序崩溃,将此时的崩溃指令地址作为符号执行的起点位置,并获取符号执行的现场上下文信息;
[0142]
本实施例中,选取公开的漏洞poc脚本即可;poc脚本中的payload为一串特定的输入,该输入可用于触发目标二进制代码中的漏洞,或者激活特定的gadgets;
[0143]
符号执行的现场上下文信息包括:dump崩溃现场的内存、寄存器及其值等数据信息;
[0144]
(s32)将位于污点分析空间内的内存单元字节设置为符号变量,并将这些符号变量进行初始化;
[0145]
污点分析空间为步骤(s2)中通过动态污点分析技术确定的被污染的内存空间;
[0146]
若分支跳转的约束条件中包含符号变量,则称该分支为符号化分支;
[0147]
(s33)获得目标二进制代码的静态控制流程图,以采用静态分析技术穷举目标二进制代码所有的执行路径,并采用静态分析技术穷举目标程序所有的执行路径,将其中无法到达目标gadgets的执行路径作为黑名单路径,保存到路径搜索配置文件中;将poc脚本执行过程中获取到的从符号执行起点位置到达目标gadgets的poc执行路径确定为白名单路径,写入路径搜索配置文件中;
[0148]
可选地,本实施例中,获得目标二进制代码的静态控制流程图的具体方式是:将目标二进制代码进行反汇编,得到目标程序,提取目标程序的静态控制流程图(control flow graph,cfg);
[0149]
(s34)利用符号执行引擎从符号执行起点位置开始执行目标二进制代码,并将路径搜索配置文件导入符号执行引擎,以使符号执行引擎在执行过程中根据黑名单路径和白名单路径实现启发式分支跳转;
[0150]
由于本实施例以崩溃指令地址作为符号执行的起点位置,因此,在利用符号引擎从起点位置开始执行目标二进制代码之前,会先根据符号执行的现场上下文信息恢复现场;
[0151]
本实施例的步骤(s34)中,符号执行引擎从符号执行起点位置开始执行目标二进制代码,即执行仿真模拟的过程,具体过程如下:
[0152]
从恢复后的现场开始仿真执行指令,同时根据指令语义修改相应的符号状态和符号表达式;在遇到符号化分支时,根据路径探索策略选择跳转方向并生成相应的路径约束;在仿真的初始时刻,将路径约束初始化为永真式,表明尚未执行任何分支,因此不存在约束;当仿真执行到分支跳转指令时,检查分支跳转的约束条件中是否包含符号变量(即是否被符号化);如果是,则说明此分支依赖于符号变量,为符号化分支,则根据路径探索策略选择是否遵守当前具体值所跳转的方向,并将分支约束添加到路径约束当中;跳转后,继续仿真模拟,直到遇到符号化分支时路径指示中已不存在下一个路径探索策略指示,或运行的指令总数超出了最大限制,或遇到了符号执行无法处理的特殊指令,或跳转总数超过了预设的跳转总数阈值,或搜索深度已经超过了预设的搜索深度阈值,或已经运行到了gadget所在位置,在仿真过程中,如果遇到了可能导致路径爆炸的系统调用、库调用等外部交互,
则使用摘要建模的手段,分析系统调用或库调用的语义以建立符号化模型,模拟外部交互的效果;
[0153]
符号执行引擎实现分支跳转时,优先跳转至位于poc执行路径上的gadgets,由此能够使得到达gadgets的路径最短,时间最快;
[0154]
(s35)若符号执行引擎在预设的跳转总数阈值和搜索深度阈值内,到达目标gadgets,则转入步骤(s36);否则,说明该gadgets不可复用,转入步骤(s37);
[0155]
(s36)根据步骤(s32)中定义的符号变量,将到达目标gadgets的执行路径的约束条件符号化,得到路径约束表达式,求解路径约束表达式,得到目标gadgets的路径约束值;若求解成功,则判定目标gadgets为可复用gadgets,并转入步骤(s37);若求解不成功,且路径搜索配置文件中还存在未搜索过的路径,则转入步骤(s34),开始搜索下一条路径;若求解不成功,且路径搜索配置文件中不存在未搜索过的路径,则说明该gadgets不可复用,转入步骤(s37);
[0156]
可选地,本实施例中,直接利用公开的路径约束求解器对所建立的路径约束表达式进行求解;若求解成功,最终求解得到的路径约束值为一串内存值或地址值,通过程序输入或者漏洞利用的输入该路径约束值,即可让程序在不改变目标原本cfg执行流的情况下,到达该gadgets;
[0157]
本实施例通过设置跳转总数阈值和搜索深度阈值,对跳转总数和搜索深度进行限制,能够限制路径约束表达式的复杂度,有效缓解路径爆炸问题,提高路径约束值求解成功的概率;
[0158]
(s37)针对目标gadgets的分析结束。
[0159]
实施例2:
[0160]
一种指令级代码复用方法,用于在不改变控制流的情况下实现对目标二进制代码的复用;本实施例提供的指令级代码复用方法包括:
[0161]
对于目标二进制代码,执行本发明提供的上述指令级代码复用分析方法,获得目标二进制代码中的可复用gadgets及相应的路径约束值;
[0162]
建立目标二进制代码的内存污染依赖表;内存污染依赖表记录了污染源地址到污染目的地址的映射关系;
[0163]
根据所需实现的复用功能,执行相应的复用策略;复用策略包括单个gadgets单次复用策略、单个gadgets多次复用策略、多个gadgets单次复用策略和多个gadgets多次复用策略。
[0164]
本实施例中,内存污染依赖表的建立方式包括:
[0165]
在第一回调函数中增加利用五元组《污染源编号,污染源地址,污染目的地址,源染色序列,目的染色序列》记录各指令中地址关系,其中,污染源编号用于唯一标识污染源;污染源地址和污染目的地址分别为污染源在内存中的地址和被污染的内存单元地址;源染色序列和目的染色序列分别是污染源地址和污染目的地址染色后的序列值;
[0166]
每执行一条指令,则更新相应的五元组,所有指令执行结束后,完成一轮染色,执行至少轮染色后,筛选出源染色序列和目的染色序列相同的五元组,提取其中的污染源地址和污染目的地址,建立映射关系并记录到内存污染依赖表中;n表示染色所使用
的颜色总数,t表示污染源编号的字节总数,表示向上取整,执行轮染色后,达到染色稳定稳定的状态;
[0167]
每一轮染色包括如下步骤:
[0168]
(t0)将第一条指令作为当前指令;
[0169]
(t1)若当前指令中包含污染源,则将污染源编号和污染源在内存中的地址更新到五元组中,并转入步骤(t2);否则,转入步骤(t3);
[0170]
(t2)对污染源编号进行染色,得到源染色序列,并更新到五元组中;对污染源染色的方式为:
[0171]
预先定义n种不同的颜色,对应的颜色编号依次为1~n;可选地,本实施例中,n=8,相应地,颜色编号依次为1~8;
[0172]
对污染源内存地址以字节为单位,依次染色为第1~8种颜色,根据并污点传播规则对污染目的地址进行染色,得到源染色序列和目的染色序列,并更新到五元组中;
[0173]
(t3)若还存在未执行的指令,则取当前指令的下一条指令,并转入步骤(t1);否则,当前的一轮染色结束。
[0174]
基于本实施例所建立的上述内存污染依赖表,可以清楚地知道,修改源地址内存某一个字节的值,可以对应影响目的地址中哪个字节的值。
[0175]
本实施例中,单个gadgets单次复用策略的执行方式包括:
[0176]
(a1)选取可实现复用功能的一个可复用gadgets,并获取其路径约束值;
[0177]
(a2)通过程序输入或者漏洞利用的输入,输入所获取的路径约束值,到达所选取的可复用gadgets;
[0178]
(a3)确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能。
[0179]
本实施例中,单个gadgets多次复用策略的执行方式包括:
[0180]
(b1)选取可实现复用功能的一个可复用gadgets,并获取其路径约束值;
[0181]
(b2)通过程序输入或者漏洞利用的输入,输入所获取的路径约束值,到达所选取的可复用gadgets;
[0182]
(b3)确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能,完成一次复用;
[0183]
(b4)根据需要执行的复用次数,多次执行步骤(b2)~(b3),实现单个gadgets多次复用。
[0184]
本实施例中,多个gadgets单次复用策略的执行方式包括:
[0185]
(c1)选取可实现复用功能且满足复用条件的多个可复用gadgets,并获取各可复用gadgets的路径约束值;
[0186]
复用条件为:前置gadgets中存储元操作的地址与后继gadgets中加载元操作的地址相同;所选取的多个可复用gadgets中,先、后执行的可复用gadgets分别为前置gadgets和后继gadgets;
[0187]
(c2)按照前置和后继关系,将所选取的可复用gadgets有序组织到一起;
[0188]
图2所示,为多个gadgets单次复用策略的一个示例,其中gadgets1、gadgets3、gadgets4、gadgets5为基于多个gadgets单次复用策略选取的4个可复用gadgets,基于复用条件确定gadgets之间的前置和后继关系后并进行有序组织后,各gadgets的执行顺序如图2所示;
[0189]
(c3)按序依次到达所选取的可复用gadgets,每次到达可复用gadgets后,确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能;所有选取的可复用gadgets执行完成后,实现多个gadgets单次复用;
[0190]
其中,到达可复用gadgets的方式为:通过程序输入或者漏洞利用的输入,输入该可复用gadgets的路径约束值,到达该可复用gadgets。
[0191]
本实施例中,多个gadgets多次复用策略的执行方式包括:
[0192]
(d1)选取可实现复用功能且满足复用条件的多个可复用gadgets,并获取各可复用gadgets的路径约束值;
[0193]
(d2)按照前置和后继关系,将所选取的可复用gadgets有序组织到一起;
[0194]
(d3)按序依次到达所选取的可复用gadgets,每次到达可复用gadgets后,确定复用功能所要操作的内存地址,作为污染目的地址,并通过内存污染依赖表确定对应的污染源地址,修改污染源地址处的内存值,使得所选取的gadgets被执行后实现不同的功能;所有选取的可复用gadgets执行完成后,实现多个gadgets一次复用;
[0195]
到达可复用gadgets的方式为:通过程序输入或者漏洞利用的输入,输入该可复用gadgets的路径约束值,到达该可复用gadgets;
[0196]
(d4)根据需要执行的复用次数,多次执行步骤(d3),实现多个gadgets多次复用。
[0197]
本实施例的步骤(c1)和步骤(d1),还包括:
[0198]
若所选取的多个可复用gadgets中,存在前置gadgets和后继gadgets不满足复用条件的情况,则判断前置gadgets中存储元操作的地址和后继gadgets中加载元操作的地址是否均在污点分析空间中,若是,则将前置gadgets中存储元操作的地址和后继gadgets中加载元操作的地址修改为一致,以保证所选取的多个可复用gadgets满足复用条件。
[0199]
本实施例所提供的上述指令级代码复用方法,通过对目标代码溢出漏洞的利用,只覆盖栈空间中局部变量内存单元的值,不覆盖返回地址的值,该方法发现的指令级代码复用路径完全严格遵循目标代码原本cfg执行流。
[0200]
以下结合一个具体的代码复用实例,对上述指令级代码复用方法的执行过程做进一步的解释说明。
[0201]
图3是某目标代码反汇编控制流程图,图中,节点a~h是基本块,在g和h块中存在两类代码片段,其中所显示的代码片段,即经过实施例1提供的指令级代码复用分析方法获取得到的部分可复用gadgets为便于描述,g块中的可复用gadgets记为x,h块中的可复用gadgets记为y。图4所示为该目标代码执行漏洞函数时栈空间布局图,其中ebp-0x04~ebp-0x150的内存空间为漏洞可以覆盖的空间,即攻击者可以修改的内存空间。
[0202]
复用第一步:在第一次触发漏洞函数,引导程序执行a-》b-》e-》g这条路径,见图3,达到g块;通过对buffer填充数据,致使栈溢出覆盖到ebp-0x20和ebp-0xc的位置,通过对覆
盖数据进行设计,可使得相应内存单元赋特定的值,如表1所示。
[0203]
表1对0x80e1d60内存写入55功能复用语义内存赋值表
[0204]
内存地址值备注ebp-0xc0x00000037该值是十进制55ebp-0x200x80e1d60该值是目标代码进程数据段的内存地址
[0205]
当程序执行如图5所示右侧第一行代码时,cpu从ebp-0xc内存单元中取出0x00000037值放到eax寄存器中,执行第二行代码时,则将eax寄存器的值存放到ebp-0x20内存单元中值作为内存地址的内存单元中,此过程则实现了对0x80e1d60内存单元赋值55的功能。因此,通过对该gadgets的复用,即可完成一个任意内存写入任意值的功能。此过程,即单个gadgets单次复用策略的执行过程。
[0206]
复用第二步:复用者在第二次触发漏洞函数,如同第一次漏洞利用过程,如表2所示,实现对0x80e18ac内存单元赋值62的功能语义。
[0207]
表2对0x80e18ac内存写入62功能复用语义内存赋值表
[0208]
内存地址值备注ebp-0xc0x0000003e该值是十进制62ebp-0x200x80e18ac该值是目标代码进程数据段的内存地址
[0209]
复用第一步和复用第二步,通过对x的多次复用,实现了对0x80e1d60内存单元和0x80e18ac内存单元赋值的功能语义,这两步即实现了单个gadgets多次复用的过程。
[0210]
复用第三步:在第三次触发漏洞函数,引导程序执行a-》b-》e-》h这条路径,如图3所示,达到h基本块。通过类似的方式,通过表3赋值规则,实现对内存地址0x80e1d60和0x80e18ac值得相加功能的复用语义,将相加的结果存放到0x80e1d60内存中。
[0211]
表3相加功能复用语义内存赋值表
[0212]
内存地址值备注ebp-0x200x80e1d600x80e1d60是内存地址,值等于55ebp-0x300x80e18ac0x80e18ac是内存地址,值等于62ebp-0x500x80e1d600x80e1d60是内存地址,存放相加后结果
[0213]
经过上述三步的复用过程,通过漏洞对特定内存单元赋值特定的值(值可以是具体的十六进制数值,也可以是有效的地址),将目标代码gadgets合理组织起来,最终实现了任意两个数相加的功能复用语义。
[0214]
实施例3:
[0215]
一种计算机算可读存储介质,包括存储的计算机程序,该计算机程序被处理器执行时,控制所述计算机可读存储介质所在设备执行上述实施例1提供的指令级代码复用分析方法,或上述实施例2提供的指令级代码复用方法。
[0216]
本领域的技术人员容易理解,以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1