一种面向C++二进制文件的控制流图生成方法及电子装置

    专利查询2023-08-10  114

    一种面向c++二进制文件的控制流图生成方法及电子装置
    技术领域
    :1.本发明属于软件逆向分析
    技术领域
    :,具体涉及一种面向c++二进制文件的控制流图生成方法及电子装置。
    背景技术
    ::2.控制流图(controlflowgraph,cfg)是一个过程或程序的抽象表现,是用在编译器中的一个抽象数据结构,由编译器在内部维护,代表了一个程序执行过程中会遍历到的所有路径。它用图的形式表示一个过程内所有基本块执行的可能流向,也能反映一个过程的实时执行过程。3.从francese.allen于1970年提出控制流图的概念之后,控制流图成为了编译器优化和静态分析的重要工具。面对无法获取源码的程序,研究人员不得不需要通过逆向工程的手段对程序代码进行分析。而在分析过程中,一个精确而完善的控制流图能过帮助研究人员对程序结构进行直观的认识,以辅助其进一步的深入分析与理解。4.为获取更利于分析的控制流图,众多科研人员对此进行了研究。例如中国专利申请cn106775913a公开的一种目标代码控制流图生成方法、中国专利申请cn103577242a公开的针对已调度汇编代码的控制流图重构方法、中国专利申请cn108958793a公开的一种基于改进gn算法的程序控制流图划分方法及中国专利申请cn109408034公开的一种面向对象程序的控制流图构造方法等。5.c++语言由于其高性能、稳定和多态的特性,一直是大型商业软件的主流选择。由tiobe发布的2002年到现在的编程语言热度发展趋势统计图可知,c++语言一直稳定在前三的位置。但由于现有控制流图的生成方案中,由于下述原因导致控制流图的建立不准确,无法分析大型的二进制文件:6.1)现有方法将虚函数表与构造函数进行配对,在编译优化的情况下,基类的构造函数可能内联进派生类的构造函数中,或者构造函数全部内联进普通函数中,这样将导致该配对方法失效;7.2)现有方法根据连续地址空间上的offsettotop字段来进行虚函数表的合并,并且一个虚函数表只与一个类绑定,然而在编译优化的情况下此类方法并不适用;这是因为在编译优化的情况下,同一个类的不同虚函数表可能分布在不连续的地址空间;不同的类可能共享相同的虚函数表,因此会导致类的缺失;8.3)现有方法通过遍历所有函数来搜索构造函数,这在面对大型二进制文件时会显著增加分析时间的开销;9.4)现有方法无法处理数据间接引用的问题,导致无法处理虚基类表读写操作分别在不同函数的情况,进而无法识别虚继承,从而在编译优化的情况下,构造函数内联情况会扰乱控制流的分析;10.5)现有方法会对所有函数生成cfg,这在分析大型二进制文件时会极大的增加时间开销。技术实现要素:11.为解决上述问题,本发明提出一种面向c++二进制文件的控制流图生成方法及电子装置,依据c++二进制接口(abi)实现的特点,依据构造函数与析构函数,生成一种能够反映c++二进制文件中虚继承关系的控制流图。12.为达到上述目的,本发明采用以下技术方案:13.一种面向c++二进制文件的控制流图生成方法,其步骤包括:14.1)从c++二进制文件中提取虚函数表与符号表;15.2)依据所述符号表获取每一虚函数表中的析构函数,并将虚函数表与相应析构函数进行配对;16.3)对每一虚函数表进行交叉引用查询,得到构造函数;17.4)通过构造函数、析构函数与直接或间接调用构造函数或析构函数的函数,生成控制流图。18.进一步地,通过以下步骤提取虚函数表:19.1)运行时类型信息;20.2)依据运行时类型信息指针获取的附加信息,得到虚函数表信息。21.进一步地,通过以下步骤提取符号表:22.1)通过虚函数表,得到虚函数表地址与虚函数表包含的虚函数地址;23.2)通过c++二进制文件中提取的虚基类表,得到虚基类表地址与虚基类表字段内容;24.3)根据虚函数表地址、虚函数地址、虚基类表地址与虚基类表字段内容,得到符号表。25.进一步地,通过以下策略获取每一虚函数表中的析构函数:26.1)遍历每一虚函数表中的函数,得到具有虚函数表内存覆写操作的第一函数;27.2)依据所述符号表,获取第一函数的第一后面指令或调用第一函数的上层函数的第二后面指令中具有delete操作的第一函数,得到析构函数。28.进一步地,覆写操作包括:movqword[rsi+0x8]或vftptr;delete操作包括:calldelete()。[0029]进一步地,通过以下步骤获取所述构造函数:[0030]1)交叉引用查询每一虚函数表,排除掉析构函数,获取第三函数;[0031]2)遍历第三函数,获取具有虚函数表内存覆写操作的第四函数;[0032]3)获取第四函数的第一前序指令和调用第三函数的上层函数的第二前序指令中具有new操作的第四函数,得到构造函数。[0033]进一步地,覆写操作包括:movqword[rsi+0x8]或vftptr;new操作包括:callnew()。[0034]进一步地,通过以下步骤生成控制流图:[0035]1)根据跳转语句,对构造函数地址与析构函数地址组成的集合中每一函数进行基本块划分;[0036]2)将包含直接跳转语句或条件跳转语句的基本块,与跳转目标所在的基本块连接;[0037]3)将包含非系统调用的call指令的基本块与相应call指令指向函数地址所在的基本块连接,其中将不存在集合中的相应call指令指向函数地址所在的基本块,添加进集合;[0038]4)若跳转语句的跳转目标地址在已分析基本块中,且不是已分析基本块的起始地址或结束地址,则将该已分析基本块对于跳转目标地址进行分割;[0039]5)分别对循环结构的走向循环路径分支与无返回的路径结构的走向路径分支进行标记。[0040]一种存储介质,所述存储介质中存储有计算机程序,其中,所述计算机程序被设置为运行时执行上述所述的方法。[0041]一种电子装置,包括存储器和处理器,所述存储器中存储有计算机程序,所述处理器被设置为运行所述计算机以执行上述所述的方法。[0042]与现有技术相比,本发明方法的优点是:[0043]1)由于为了防止内存泄漏,析构函数一般被设置为虚函数,即析构函数不存在函数内联问题,而本发明通过将虚函数表与析构函数进行配对,保证了配对的有效性;[0044]2)本发明通过析构函数来合并虚函数表,而且不限于一对一的匹配,也可以一对多匹配;[0045]3)本发明采用启发式搜索构造函数的方法,对虚函数表进行交叉引用查询,排除掉先前识别的析构函数,剩下的再通过语义筛选,找到构造函数;[0046]4)本发明采用过程间的方法来解决数据间接引用的问题,从而可以识别虚继承;以构造函数或析构函数为起点,从整体角度进行分析,构造对象内存布局,从而可以抵抗构造函数内联带来的影响;[0047]5)本发明只对构造函数和析构函数及其相关的函数生成控制流图,通常只占总函数的20%左右,适用于分析大型的c++二进制文件。附图说明[0048]图1本发明控制流图的生成流程图。[0049]图2本发明一实施例的跳转析构函数示意图。具体实施方式[0050]为了使本
    技术领域
    :的人员更好地理解本发明实施例中的技术方案,并使本发明的目的、特征和优点能够更加明显易懂,下面结合和事例对本发明中技术核心作进一步详细的说明。[0051]如图1所示,本发明的控制流图生成包括以下步骤:[0052]1.从二进制文件中提取基本信息[0053]从二进制文件里提取基本信息,包括:虚函数表(vftable),虚基类表(vbtable),符号表。[0054]1)提取虚函数表依据的特征有:[0055]a)位置在只读段上,如.rdata;[0056]b)存储的地址在代码段上,如.text;[0057]c)第一项有交叉引用,将虚函数表赋值给虚函数表指针(vftptr);[0058]d)若有运行时类型信息(rtti),则运行时类型信息指针(rttiptr)在虚函数表前面。[0059]具体的,若a)-c)的特征都存在时,即可从二进制文件中提取虚函数表,并可通过d)提取到该虚函数表的一个附加信息。[0060]2)提取虚基类表依据的特征有:[0061]a)位置在只读段上,如.rdata;[0062]b)固定两个字段,且字段长度固定为4字节,第一个字段为vftable偏移,固定为-4(32位程序)或-8(64位程序),第二个字段为虚基类偏移;[0063]c)第一项有交叉引用,将vbtable赋值给虚基类表指针(vbtptr)。[0064]同上,若a)-c)的特征都存在时,即可从二进制文件中提取虚基类表。[0065]3)符号表信息提取具体包括以下步骤:[0066]步骤a):通过上述虚函数表依据特征提取虚函数表,并记录下虚函数表地址和所包含的虚函数地址;[0067]步骤b):通过上述虚基类表依据特征提取虚基类表,并记录下虚基类表地址和虚基类表字段里的内容;[0068]步骤c):根据虚函数表地址和所包含的虚函数地址及虚基类表地址和虚基类表字段里的内容,提取符号表信息。[0069]2.析构函数与构造函数分析[0070]在本步骤中,搜索每个虚函数表中的析构函数,并将虚函数表与析构函数进行配对,然后对每个虚函数表进行交叉引用查询,启发式搜索构造函数。[0071]具体地,因为过程间静态污点分析不是对所有函数进行分析,而是从析构函数(dtor)或者构造函数(ctor)开始,所以需要先从二进制文件中识别出析构函数和构造函数,并将析构函数与虚函数表进行配对。[0072]在真实世界的二进制文件中,同一个类的不同虚函数表中只有一个记录着析构函数,其他的虚函数表里不存在析构函数。但是通过仔细分析和观察可以发现,如图2所示,不存在析构函数的虚函数表中都存在一种跳转析构函数的wrapper函数,该函数主要的作用是修改this指针,然后再跳转到真正的析构函数。本发明通过探测语义来寻找语义上相同的析构函数作为启发式,合并同一个类的不同虚函数表。析构函数具有的语义主要是以下两个:[0073]1)覆写操作,例如movqword[rsi+0x8],vftptr;[0074]2)delete操作,例如calldelete()。[0075]析构函数分析具体包括以下步骤:[0076]步骤1:遍历每个虚函数表中的函数,检测其是否具有虚函数表的内存写入操作,即覆写操作,若存在则执行步骤2;[0077]步骤2:搜索该函数后面的指令和调用该函数的上层函数的后面的指令,检测其中是否具有delete操作,这里采用模式匹配的方法,通过信息提取中的符号表得到一个函数的符号,将常见的delete符号与之匹配,若匹配则具有delete操作,并执行步骤3,否则返回步骤1;[0078]步骤3:将虚函数表与识别的析构函数进行配对,若虚函数表未遍历完,则执行步骤1,否则结束;[0079]在复杂的编译优化的情况下,构造函数可能全部被内联进普通函数内,所以本发明搜索得到的构造函数并不一定是真正的构造函数,而是包含构造函数行为的函数。本发明的构造函数具有的语义主要是以下两个:[0080]1)覆写操作,例如movqword[rsi+0x8],vftptr;[0081]2)new操作,例如callnew()。[0082]构造函数分析具体包括以下步骤:[0083]步骤1:交叉引用查询每一个虚函数表,排除掉析构函数,遍历剩下的函数,检测其是否具有覆写操作,若存在则执行步骤2;[0084]步骤2:搜索该函数前面的指令和调用该函数的上层函数的前面的指令,检测其中是否具有new操作,这里采用模式匹配的方法,通过信息提取中的符号表得到一个函数的符号,将常见的new符号与之匹配,若匹配则具有new操作,并执行步骤3,否则返回步骤1;[0085]步骤3:将识别出的构造函数加入构造函数列表中,若函数遍历完成则结束,否则执行步骤1。[0086]3.控制流图的生成[0087]在本步骤中,依据构造函数、析构函数及直接或间接调用构造函数或析构函数的其它函数,生成对应的控制流图。[0088]本发明采用了部分cfg生成的策略,只对构造函数和析构函数及其相关的函数生成cfg,具体包括以下步骤:[0089]步骤1:将构造函数和析构函数的地址放在同一集合中,遍历该集合,并对每个函数以跳转语句进行基本块的划分,每个函数以函数起始地址所在的基本块为起始点,每个基本款以用于划分的跳转语句作为末尾;[0090]步骤2:对于每个基本块,若包含直接跳转语句或者条件跳转语句,则将跳转目标所在的基本块与该基本块相连接;[0091]步骤3:对于每个基本块,若存在call指令,通过符号表模式匹配是否为系统调用,若是则直接丢弃,否则将call指令指向的函数地址所在的基本块与该基本块相连接,若call指令指向的函数地址不存在集合中,则将其添加进集合中;[0092]步骤4:在处理跳转语句时,若跳转目标地址在已经分析过的基本块中,且不是该基本块的起始地址和结束地址,则将该基本块对于跳转目标地址进行分割;[0093]步骤5:若遇到循环结构时,将走向循环路径的分支标记为loop;[0094]步骤6:若遇到无返回的路径结构(noreturn)时,将走向noreturn路径的分支标记为noreturn。[0095]尽管为说明目的公开了本发明的具体内容、实施算法以及附图,其目的在于帮助理解本发明的内容并据以实施,但是本领域的技术人员可以理解:在不脱离本发明及所附的权利要求的精神和范围内,各种替换、变化和修改都是可能的。本发明不应局限于本说明书最佳实施例和附图所公开的内容,本发明要求保护的范围以权利要求书界定的范围为准。当前第1页12当前第1页12
    技术特征:
    1.一种面向c++二进制文件的控制流图生成方法,其步骤包括:1)从c++二进制文件中提取虚函数表与符号表;2)依据所述符号表获取每一虚函数表中的析构函数,并将虚函数表与相应析构函数进行配对;3)对每一虚函数表进行交叉引用查询,得到构造函数;4)通过构造函数、析构函数与直接或间接调用构造函数或析构函数的函数,生成控制流图。2.如权利要求1所述的方法,其特征在于,通过以下步骤提取虚函数表:1)运行时类型信息;2)依据运行时类型信息指针获取的附加信息,得到虚函数表信息。3.如权利要求1所述的方法,其特征在于,通过以下步骤提取符号表:1)通过虚函数表,得到虚函数表地址与虚函数表包含的虚函数地址;2)通过c++二进制文件中提取的虚基类表,得到虚基类表地址与虚基类表字段内容;3)根据虚函数表地址、虚函数地址、虚基类表地址与虚基类表字段内容,得到符号表。4.如权利要求1所述的方法,其特征在于,通过以下策略获取每一虚函数表中的析构函数:1)遍历每一虚函数表中的函数,得到具有虚函数表内存覆写操作的第一函数;2)依据所述符号表,获取第一函数的第一后面指令或调用第一函数的上层函数的第二后面指令中具有delete操作的第一函数,得到析构函数。5.如权利要求4所述的方法,其特征在于,覆写操作包括:mov qword[rsi+0x8]或vftptr;delete操作包括:call delete()。6.如权利要求1所述的方法,其特征在于,通过以下步骤获取所述构造函数:1)交叉引用查询每一虚函数表,排除掉析构函数,获取第三函数;2)遍历第三函数,获取具有虚函数表内存覆写操作的第四函数;3)获取第四函数的第一前序指令和调用第三函数的上层函数的第二前序指令中具有new操作的第四函数,得到构造函数。7.如权利要求6所述的方法,其特征在于,覆写操作包括:mov qword[rsi+0x8]或vftptr;new操作包括:call new()。8.如权利要求1所述的方法,其特征在于,通过以下步骤生成控制流图:1)根据跳转语句,对构造函数地址与析构函数地址组成的集合中每一函数进行基本块划分;2)将包含直接跳转语句或条件跳转语句的基本块,与跳转目标所在的基本块连接;3)将包含非系统调用的call指令的基本块与相应call指令指向函数地址所在的基本块连接,其中将不存在集合中的相应call指令指向函数地址所在的基本块,添加进集合;4)若跳转语句的跳转目标地址在已分析基本块中,且不是已分析基本块的起始地址或结束地址,则将该已分析基本块对于跳转目标地址进行分割;5)分别对循环结构的走向循环路径分支与无返回的路径结构的走向路径分支进行标记。9.一种存储介质,所述存储介质中存储有计算机程序,其中,所述计算机程序被设置为
    运行时执行权利要求1-8中任一所述方法。10.一种电子装置,包括存储器和处理器,所述存储器中存储有计算机程序,所述处理器被设置为运行所述计算机程序以执行如权利要求1-8中任一所述方法。

    技术总结
    本发明提供一种面向C++二进制文件的控制流图生成方法及电子装置,包括:从C++二进制文件中提取虚函数表与符号表;依据所述符号表获取每一虚函数表中的析构函数,并将虚函数表与相应析构函数进行配对;对每一虚函数表进行交叉引用查询,得到构造函数;通过构造函数、析构函数与直接或间接调用构造函数或析构函数的函数,生成控制流图。本发明采用过程间的方法来解决数据间接引用的问题,从而可以识别虚继承;以构造函数或析构函数为起点,从整体角度进行分析,构造对象内存布局,从而可以抵抗构造函数内联带来的影响;只对构造函数和析构函数及其相关的函数生成控制流图,适用于分析大型的C++二进制文件。型的C++二进制文件。型的C++二进制文件。


    技术研发人员:龚晓锐
    受保护的技术使用者:中国科学院信息工程研究所
    技术研发日:2020.11.23
    技术公布日:2022/5/25
    转载请注明原文地址:https://tc.8miu.com/read-18049.html

    最新回复(0)