结构解析方法、装置、电子设备和存储介质
文献发布时间:2023-06-19 11:57:35
相关申请的交叉引用
本申请要求于2020年07月08日提交中国专利局的申请号为2020106515596、名称为“SSA结构解析方法、装置、电子设备和存储介质”的中国专利申请的优先权,其全部内容通过引用结合在本申请中。
技术领域
本申请涉及程序语言技术领域,具体而言,涉及一种结构解析方法、装置、电子设备和存储介质。
背景技术
随着网络技术的不断发展,通过不同类型的程序语言编写形成的应用程序也日益增多。为了保证应用程序的使用体验,在发布新的应用程序之前,通常会对该应用程序进行漏洞分析。
白盒测试技术是一种常用的漏洞分析技术,白盒测试技术一般可被分为静态分析和动态分析两类技术。静态分析主要有:控制流分析技术、数据流分析技术、信息流分析技术。在使用数据流分析技术进行白盒测试时,需要先将源程序解析为数据流,再对数据流进行分析。
目前,现有的白盒测试软件在测试golang语言时,无法将具体的代码内容与具体的包对应起来,导致在对数据流分析时,无法进行跨包数据流追踪,因此,只能在golang语言的单文件包中生效。
发明内容
有鉴于此,本申请的目的在于提供一种结构解析方法、装置、电子设备和存储介质,实现源代码的跨包数据流检测。
第一方面,本发明实施例提供一种结构解析方法,应用于电子设备,所述方法包括:
根据数据流解析规则对程序语言的源代码进行解析,获得多个解析节点,所述解析节点表征所述程序语言的源代码的语法结构及所述程序语言的执行路径信息;
将所述多个解析节点进行关系的关联,以获得可用于数据流分析的结构数据。
在可选的实施方式中,所述根据数据流解析规则对程序语言的源代码进行解析,获得多个解析节点的步骤,包括:
通过抽象语法树解析规则对所述程序语言的源代码进行解析,获得至少一个抽象语法树节点,所述抽象语法树节点表征所述程序语言的源代码的语法结构;
通过控制流解析规则对所述程序语言的源代码进行解析,获得至少一个控制流图节点,所述控制流图节点表征所述程序语言的执行路径信息。
在可选的实施方式中,在所述通过抽象语法树解析规则对所述程序语言的源代码进行解析,获得至少一个抽象语法树节点的步骤之后,所述结构解析方法还包括:
对所述至少一个抽象语法树节点进行静态单赋值转换,获得所述程序语言的源代码对应的静态单赋值结构数据,所述静态单赋值结构数据表征所述程序语言的源代码的完整文件结构。
在可选的实施方式中,所述通过控制流解析规则对所述程序语言的源代码进行解析,获得至少一个控制流图节点的步骤包括:
遍历所述完整文件结构中的每个文件,获得全部所述控制流图节点之间的对应关系,以构成所述程序语言的执行路径信息。
在可选的实施方式中,所述遍历所述完整文件结构中的每个文件,获得全部控制流图之间的对应关系,以构成所述程序语言的执行路径信息的步骤,包括:
遍历所述完整文件结构中的每个文件,确定全部所述控制流图节点的边信息的执行逻辑关系,以获得所述全部所述控制流图节点之间的对应关系。
在可选的实施方式中,所述通过抽象语法树解析规则对所述程序语言的源代码进行解析,获得至少一个抽象语法树节点的步骤,包括:
对所述程序语言的源代码进行解析,转换成对应的标记序列Token,其中,所述标记序列Token包括标识符、关键字、分隔符、操作符、文字和注释中的至少一种;
通过所述抽象语法树解析规则对所述标记序列Token进行语法分析,根据语法特征将标记序列Token构建为所述至少一个抽象语法树节点。
在可选的实施方式中,所述方法还包括:
根据漏洞分析规则及数据流分析方法对所述结构数据进行漏洞分析,获得漏洞检测结果。
第二方面,本发明实施例提供一种结构解析装置,应用于电子设备,所述装置包括:
源代码解析模块,用于根据数据流解析规则对程序语言的源代码进行解析,获得多个解析节点,所述解析节点表征所述程序语言的源代码的语法结构及所述程序语言的执行路径信息;
节点关联模块,用于将所述多个解析节点进行关系的关联,以获得可用于数据流分析的结构数据。
第三方面,本发明实施例提供一种电子设备,包括:处理器、存储介质和总线,存储介质存储有处理器可执行的机器可读指令,当电子设备运行时,处理器与存储介质之间通过总线通信,处理器执行机器可读指令,以执行如前述实施方式任一方法的步骤。
第四方面,本发明实施例提供一种计算机可读存储介质,计算机可读存储介质上存储有计算机程序,计算机程序被处理器运行时执行如前述实施方式任一方法的步骤。
基于上述任一方面,本申请对程序语言的源代码进行解析得到表征源代码语法结构和执行路径信息的解析节点,将解析节点进行关系的关联,以获得结构数据。由此,解析节点中包括有程序语言源代码的执行路径信息和语法结构,在通过结构数据进行数据流分析时,即可实现源代码的跨包数据流检测。
另外,在一些实施例中,通过结构数据进行数据流分析,以实现对源代码的白盒测试,还可以降低漏洞的误报率。
附图说明
为了更清楚地说明本申请实施例的技术方案,下面将对实施例中所需要使用的附图作简单地介绍,应当理解,以下附图仅示出了本申请的某些实施例,因此不应被看作是对范围的限定,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他相关的附图。
图1为本申请实施例提供的数据流分析技术的系统架构图;
图2为本申请实施例提供的SSA结构解析方法的流程图之一;
图3为本申请实施例提供的图1中的步骤S103的子步骤流程图;
图4为一种常见的CFG结构数据的示意图;
图5为本申请实施例提供的SSA结构解析方法的流程图之二;
图6为一个待分析的CFG结构的示意图;
图7为本申请实施例提供的SSA结构解析方法的流程图之三;
图8为本申请实施例提供的SSA结构解析装置100的功能模块图;
图9为本申请实施例提供的电子设备的架构图;
图10为本申请实施例提供的结构解析方法的流程图;
图11为本申请实施例提供的图10中的步骤S301的子步骤流程图;
图12为本申请实施例提供的图10中的步骤S301的另一子步骤流程图;
图13为本申请实施例提供的结构解析方法的另一流程图;
图14为本申请实施例提供的结构解析装置400的功能模块图。
附图说明:60-电子设备;61-处理器;62-存储器;63-总线;100-SSA结构解析装置;101-CFG节点划分模块;102-解析模块;103-关联模块;104-漏洞分析模块;105-源代码分析模块;106-源代码输入模块;400-结构解析装置;401-源代码解析模块;402-节点关联模块。
具体实施方式
为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,应当理解,本申请中附图仅起到说明和描述的目的,并不用于限定本申请的保护范围。另外,应当理解,示意性的附图并未按实物比例绘制。本申请中使用的流程图示出了根据本申请的一些实施例实现的操作。应该理解,流程图的操作可以不按顺序实现,没有逻辑的上下文关系的步骤可以反转顺序或者同时实施。此外,本领域技术人员在本申请内容的指引下,可以向流程图添加一个或多个其他操作,也可以从流程图中移除一个或多个操作。
另外,所描述的实施例仅仅是本申请一部分实施例,而不是全部的实施例。通常在此处附图中描述和示出的本申请实施例的组件可以以各种不同的配置来布置和设计。因此,以下对在附图中提供的本申请的实施例的详细描述并非旨在限制要求保护的本申请的范围,而是仅仅表示本申请的选定实施例。基于本申请的实施例,本领域技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本申请保护的范围。
本申请实施例中将会用到术语“包括”,用于指出其后所声明的特征的存在,但并不排除增加其它的特征。
首先,需要说明的是,程序语言的源文件通过各种不同的程序语言编写获得,程序语言是用来定义计算机程序的形式语言,用来向计算机发出指令,使计算机能够实现各种不同的功能。目前的程序语言包括很多,例如C语言、C++、golang语言、VB语言、JAVA语言等等。不管是由于程序逻辑导致的对数据的不当处理,或者是对API(调用接口)的不当调用,都会给整个程序带来风险。因此,需要对程序源文件进行漏洞检测,从而保证系统的安全性。
目前,漏洞检测的方法有白盒测试法和黑盒测试法。在此处,盒子指的是被测试的软件(即程序)。白盒,顾名思义即盒子是可视的,在测试时可以清楚盒子内部的结构以及运行逻辑。
黑盒测试也称功能测试,它是通过测试来检测软件的每个功能是否都能正常使用。在测试中,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测试,黑盒测试只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息。黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面和软件功能进行测试。
本申请的应用场景为程序语言的白盒测试中的数据流分析技术。下面,结合图1对数据流分析技术进行介绍。图1为本申请实施例提供的数据流分析技术的系统架构图。在通过数据流分析技术分析程序语言的源代码时,首选需要将源代码输入至程序语言解析引擎中进行初步解析,将源代码转换为SSA(Static Single-Assignment,静态单赋值)结构,再对该SSA结构进行数据流分析,从而获得分析结果。
而在数据流分析的过程中,由于现有的白盒测试算法无法将golang的具体代码与具体的包对应起来,因此,无法实现源代码的跨包数据流检测。
本申请为了解决这一技术问题,提出了一种SSA结构解析方法,对源代码对应的SSA结构进行进一步解析为CFG(Control flow graph,控制流图)结构,从而实现对golang语言的跨包数据流检测。
请参照图2,图2为本申请实施例提供的SSA结构解析方法的流程图之一。该解析方法应用于电子设备,包括:
步骤S101,根据数据流解析规则,划分出多个CFG节点。
具体地,该CFG节点可以为CFG结构(即控制流图)中的不同的节点类型,不同名称的CFG节点根据其不同的功能用于存放不同的代码信息。
步骤S102,针对每一个CFG节点,从程序语言的源代码的数据类型中查找与各CFG节点对应的目标节点,并抽取目标节点中的信息写入与该目标节点对应的CFG节点中,获得解析后的CFG节点。
其中,源代码的数据类型包括多个AST节点类型及多个SSA节点类型。
具体地,AST节点可以为抽象语法树AST(Abstract Syntax Tree)中包括的不同的节点类型,SSA(Static Single-Assignment)节点可以为SSA结构中包括的不同的节点类型。
步骤S103,将解析后的CFG节点进行关系的关联,以获得可用于数据流分析的CFG结构数据。
在上述步骤中,源代码被解析为CFG结构数据,且CFG结构数据中包括的各个CFG节点中包含有源代码的路径信息及各个包的信息,由于在同一个路径下的各个包的名称是唯一的,通过包的名字和路径就可以找到各个包中的方法,因此,通过上述将源代码解析为CFG结构数据即可实现源代码的跨包数据流分析。
需要说明的是,本申请实施例的应用场景为白盒测试技术中的数据流分析技术。数据流是一组有序的,有起点和终点的字节的数据序列,包括输入流和输出流。节点是一种表示具体代码单元的数据结构,其中包含了源代码的详细信息。
在上述实施例的具体实施过程中,首先需要根据数据流的解析规则,划分出多个CFG节点。
在一种实施方式中,CFG节点可以包括:META_DATA节点、FILE节点、METHOD节点、METHOD_PARAMETER_IN节点、METHOD_RETURN节点、MODIFIER节点、TYPE节点、TYPE_DECL节点、TYPE_PARAMETER节点、TYPE_ARGUMENT节点、MEMBER节点、NAMESPACE_BLOCK节点、LITERAL节点、CALL节点、LOCAL节点、IDENTIFIER节点、RETURM节点、BLOCK节点、METHOD_INST节点、ARRAY_INITIALIZER节点、METHOD_REF节点、CONTROL_STRUCTURE节点等,且不同的节点具有不同的数据结构,用于存放不同的代码信息。
另外,不同的CFG节点具体不同的注释内容。例如,“IDENTIFIER”节点的注释为“Anarbitrary identifier/reference”,即表示“IDENTIFIER”节点用于存放标识符;“METHOD”节点的注释为“Amethod/function/procedure”,即表示“METHOD”节点用于存放方法、函数或步骤。
可选地,在本实施例的一种实施方式中,源代码的数据类型可以包括多个AST节点类型及多个SSA节点类型。例如,AST节点可以包括:ArrayType节点、BadExpr节点、BasicLit节点、BinaryExpr节点、CallExpr节点、ChanType节点、CompositeLit节点、Ellipsis节点、FuncLit节点、FuncType节点、Ident节点、IndexExpr节点、InterfaceType节点、KeyValueExpr节点、MapType节点、ParenExpr节点、SelectorExpr节点、SliceExpr节点、StarExpr节点、StructType节点、TypeAssertExpr节点、UnaryExpr节点等;SSA节点可以包括:Alloc节点、BinOp节点、Builtin节点、Call节点、ChangeInterface节点、ChangeType节点、Const节点、Convert节点、DebugRef节点、Defer节点、Extract节点、Field节点、FieldAddr节点、FreeVar节点、Function节点、Global节点、Go节点、If节点、Index节点、IndexAddr节点、Jump节点、Lookup节点、MakeChan节点、MakeClosure节点、MakeInterface节点、MakeMap节点、MakeSlice节点、MapUpdate节点、Next节点、Panic节点、Parameter节点、Phi节点、Range节点、Return节点、RunDefers节点、Select节点、Send节点、Slice节点、Store节点、TypeAssert节点、UnOp节点等。
具体地,在本实施例中,不同的AST节点及不同的SSA节点的数据结构不同,且存放的代码信息也不相同。
另外,每一个AST节点以及SSA节点均有其各自的注释内容。例如,AST节点“ArrayType”对应的注释内容为“An ArrayType node represents an array or slicetype”,即表示该“ArrayType”用于存放数组或切片类型;“Ident”对应的注释内容为“AnIdent node represents an identifier”,即表示该节点用于存放标识符;SSA节点“Send”对应的注释内容为“The Send instruction sends X on channel Chan”,即表示该节点用于在通道chan上发送X。
需要说明的是,上述描述仅为对本申请实施例提供的多个AST节点类型以及多个SSA节点类型中的部分节点的注释的举例说明,在本实施例中,每个节点均包括各自对应的注释,在此不再一一列举。
另外,在本实施例的其他实施方式中,源代码的数据类型还可以包括更多数量(或更少数量)的AST节点类型以及更多数量(或更少数量)的SSA节点类型,例如,源代码的数据类型还可以包括46种AST节点类型或是57种SSA节点类型。本申请不对AST节点类型和SSA节点类型的具体数量进行限定。
在后续的步骤中,针对上述的每一个CFG节点,根据各个节点的注释内容从程序语言的源代码的数据类型包括的AST节点类型或者SSA节点类型中查找与各CFG节点对应的目标节点,并抽取该目标节点中的信息写入与该目标节点对应的CFG节点中,从而获得解析后的CFG节点。
例如,针对CFG节点中的IDENTIFIER节点,可以从AST节点类型中找到Ident节点,其中,Ident节点的注释内容为“An Ident node represents an identifier”,由此,可以认为AST节点类型中的Ident节点即是与CFG节点中的IDENTIFIER节点对应的目标节点,随后将Ident节点中的信息抽取出来写入CFG节点中的IDENTIFIER节点中,完成一次解析,获得解析后的IDENTIFIER节点,即获得一个解析后的CFG节点。
采用同样的方式,可以根据各个AST节点类型的注释内容以及各个SSA节点类型的注释内容从AST节点或者SSA节点中查找到每个CFG节点对应的目标节点,并将查找到的各个目标节点中的信息抽取出来,写入对应的CFG节点中,完成对所有CFG节点的解析,解析完成后的CFG节点中包含有源代码的路径信息及各个包的信息。
最后,将各个解析后的CFG节点进行关联,即可获得可用于数据流分析的CFG结构数据。
进一步地,为了表示程序源代码的整个执行逻辑,还需要将解析获得的多个CFG节点进行关联。下面对CFG节点的关联步骤进行详细描述。
请参照图3,图3为本申请实施例提供的图1中的步骤S103的子步骤流程图。在本实施例中,步骤S103具体包括以下子步骤:
子步骤S1031,根据源代码解析CFG节点的对应关系,连接CFG节点。
子步骤S1032,根据源代码上下文的执行逻辑连接CFG边。
子步骤S1033,根据CFG节点之间的包含关系连接AST边。
在具体的实施方式中,各个解析后的CFG节点中包括有源代码的信息,源代码之间的对应关系即为各个解析后的CFG节点之间的对应关系。因此,对源代码进行解析即可获得各个CFG节点之间的对应关系,再根据各CFG节点之间的对应关系将各个CFG节点连接起来。
进一步地,在子步骤S1031中,该子步骤具体包括:循环遍历源代码中所有CFG节点的对应关系,并将CFG节点进行连接与对应。
在本实施例中,边是指不同节点之间的对应关系的表示。根据源代码上下文之间的执行逻辑连接CFG节点的边,使CFG节点之间的连接线可以用于指示整个CFG结构数据的执行逻辑。
如图4所示,图4为一种常见的CFG结构数据的示意图。CFG结构(控制流图)也叫控制流程图,是一个过程或程序的抽象表现,通过一个抽象数据结构代表了一个程序执行过程中会遍历到的所有路径。控制流图可以表示一个源代码在执行过程内所有基本块执行的可能流向,也可以用于反映一个过程的实时执行过程。
在图4中,该CFG结构包括多个CFG节点(例如图4中的A、B、C、D、E等节点),且多个CFG节点之间通过有序箭头连接,该有序箭头用于表示源代码的上下文执行逻辑,例如,源代码的执行顺序从CFG节点A执行到CFG节点B,从CFG节点C到CFG节点D和CFG节点F,从CFG节点D和CFG节点F再到CFG节点E,从CFG节点G到CFG节点H和CFG节点I,再从CFG节点H到CFG节点G。
值得说明的是,图4仅为本申请对CFG结构的一个示意图,在本申请的其他实施例中,不同的源代码可以对应不同的CFG结构图,在此不作具体限定。
将源代码解析为CFG结构数据,使得每个CFG节点中都包含有源代码的各个路径及各个包的信息,同时,还可以通过箭头方向表示源代码的执行逻辑,便于后续进行数据流分析。
针对每个程序源代码的执行过程,通常用四元组G=(N,E,Entry,Exit)表示该过程的控制流图。其中,N是CFG节点的集合;E是边的集合,每条边是一个有序的节点对 此外,在具体的实施方式中,还可以根据各个CFG节点之间的包含关系连接AST边。具体地,不同的CFG节点之间有对应关系,例如,一个CFG节点A用于表示源代码的一个方法,而另一个CFG节点B则表示该方法的参数,则节点B就被包含于节点A内,通过此种包含关系连接AST边,即可将各个CFG节点之间的包含关系表示出来,便于后续分析。 例如,CFG节点中的CALL节点中包含的信息为“a=b”,其中,a是一个ident节点,b有可能为任意一个节点,那么,节点a和节点b就被包含于CALL节点中,即CALL节点的出边为节点a和节点b,节点a和节点b的入边为CALL节点。通过此种方法可以对AST边进行连接,从而将各个节点之间的包含关系展示出来。 进一步地,为了对源代码进行漏洞分析,在解析了源代码的SSA结构,获得CFG结构之后,还需要通过相应的数据流分析技术对该CFG结构进行分析,从而漏洞分析的检测结果。 具体地,如图5所示,图5为本申请实施例提供的SSA结构解析方法的流程图之二,在步骤S103之后,该方法还可以包括: 步骤S104,根据漏洞分析规则及数据流分析方法对CFG结构数据进行漏洞分析,获得漏洞检测结果。 在具体的实施方式中,可以结合参照图1,将源代码解析后获得的CFG结构数据以及漏洞分析规则输入至数据流分析算法中进行数据分析,即可输出分析结果,该分析结果用于表征源代码中是否存在代码漏洞,以及具体的代码漏洞出现在哪一段代码中。 具体地,在本实施例中,漏洞分析规则可以按照预设的频率进行更新,其中收录了源代码编写过程中出现频率较高的漏洞的分析方法,通过该分析方法,可以分析出大多数经常出现的漏洞,从而保证源代码的正常运行。另外,漏洞分析规则按照预设的频率进行更新,可以保证该漏洞分析规则可以适用于大部分的新型漏洞,提高漏洞检测的准确率。 具体地,如图6所示,图6示出了一个待分析的CFG结构数据。下面结合到达-定值分析来介绍数据流分析的过程。 定值是对某个变量的赋值,假设变量x的定值为y,如果存在一条紧随在定值y后面的程序点到达某一个程序点z的路径,并且在这条路径上y并没有被“kill”(也就是说,变量x没有被重新赋值为其他值),我们就说定值到达程序点z。 在图6中,到达-定值问题的传递函数被定义为:Out[s]=In[s]+gen-kill。gen集合是块内(即B 随后开始循环迭代,在每轮迭代中,每个块的In/Out集合都在更新,直到所有的In[s]与Out[s]都不发生变化,此时就是最终的数据流分析结果。 上述方式对源代码的控制流图(即CFG结构数据)进行数据流分析,解决了目前的数据流分析无法跨包分析的技术问题,实现源代码的跨包数据跟踪,降低了漏洞的误报率,提高了检测结果的可信度。 进一步地,由于程序语言有很多种不同的类型,例如C++、java、golang等,且针对不同类型的程序语言的解析方法也有所不同,因此,在对程序语音的源代码解析之前,还需要分析程序语言的类型。具体步骤请参照图7,图7为本申请实施例提供的SSA结构解析方法的流程图之三。在本实施例中,在步骤S102之前,SSA结构解析方法还包括: 步骤S201,对源代码进行分析,获得对应的程序语言类型。其中,程序语言类型包括go语言。 步骤S202,根据程序语言类型将源代码输入至对应的解析引擎中进行解析。其中,解析引擎包括go语言解析引擎。 需要说明的是,程序语言是用来定义计算机指令执行流程的形式化语言。每种程序语言都包含一整套词汇和语法规范,这些规范通常包括数据类型和数据结构、指令类型和指令控制、调用机制和库函数等。 程序由多条语句组成,一个语句就是一条指令(可以包含多个操作)。语句有规定的关键字(命令)和语法结构,程序语言利用串行的方法编写程序语句。语言中的控制指令(如顺序、选择、循环、调用等)可以改变程序的执行流程,用来控制计算机的处理过程。 在具体的实施过程中,在将源代码解析为CFG节点之前,还需要对源代码进行分析,从而获得该源代码的程序语言类型,即明确该源代码是用何种程序语言编写的。例如,该源代码的程序语言类型可以是C语言、golang语言、JAVA语言等多种程序语言中的任意一种。 具体地,针对不同语言类型编写的程序源文件,需要相同语言类型编写的前端解析程序进行前端解析工作,以保留了原有语言特征,从而不会漏掉任何细节,大幅提高后续检测的准确性。 因此,在对源文件进行程序语言分析,获得对应的程序语言类型(例如golang语言)之后,然后根据该程序语言类型获取对应的解析引擎,该解析引擎为采用与该程序语言类型相同语言编写的源代码解析算法。 例如,在本实施例的一个实施方式中,在对源代码解析,获得该源代码的程序语言类型为golang语言后,则将该源代码输入至golang解析引擎中进行后续解析。 在具体的实施过程中,步骤S202,根据程序语言类型将源代码输入至对应的解析引擎中进行解析,具体包括:对源代码进行词法分析及语法分析,获得该源代码的SSA结构数据。 首先,需要说明的是,SSA(Static Single-Assignment,静态单赋值)是一种中间表示形式,由于源代码中各个包的名字在SSA中仅被赋值一次,因此被称为单赋值。语法分析是编译过程的一个逻辑阶段,语法分析的任务是对结构上正确的源代码进行上下文有关性质的审查,进行类型审查。语法分析用于审查源代码有无语义错误,为代码生成阶段收集类型信息。 具体地,在本实施例中,将源代码输入与其程序语言对应的解析引擎之后,该解析引擎则对该源代码进行词法分析及语法分析,从而将该源代码转换为SSA结构,其中,SSA结构包括多个上述实施例中描述的SSA节点。 词法分析的作用就是解析源代码文件,将文件中的字符串序列转换成Token序列,方便后面的处理和解析。语法分析的输入就是词法分析输出的Token序列,这些序列会按照顺序被语法分析器进行解析,语法的解析过程就是将词法分析生成的Token按照语言定义好的文法(Grammar)自下而上或者自上而下的进行规约,每一个golang语言的源代码文件最终会被归纳成一个SourceFile结构。 进一步地,在本实施例中,对源代码进行词法分析和语法分析,以获得SSA结构的步骤具体包括以下方法: 对源代码进行词法解析,转换成对应的标记序列Token。其中,标记序列Token包括标识符、关键字、分隔符、操作符、文字和注释中的至少一种。 对标记序列Token进行语法分析,根据语法特征将标记序列Token构建为抽象语法树AST。 根据抽象语法树,结合源代码的语法特征,将抽象语法树转换为SSA结构数据。 具体地,在上述本步骤中,以golang语言进行举例说明。golang语言的源代码存储在cmd/compile目录中,golang解析引擎一般承担着词法分析、语法分析、类型检查和中间代码生成等工作。 在将golang语言输入至golang解析引擎之后,golang解析引擎首先对由golang语言编写获得的源代码进行词法分析,将源代码转换为一系列的Token。Token是一组预定义的、能够识别的字符串,通常由名字和值构成,其中,名字一般是词法的类别,例如标识符、关键字、分隔符、操作符、文字和注释等。 随后golang解析引擎扫描Token,根据golang语言的语法特征构建出源代码的抽象语法树(Abstract Syntax Tree,AST)。抽象语法树(AST)是源代码语法的结构的一种抽象表示,它用树状的方式表示编程语言的语法结构。抽象语法树中的每一个节点都表示源代码中的一个元素,每一颗子树都表示一个语法。作为一种常用的数据结构,抽象语法树抹去了源代码中不重要的一些字符、空格、分号或者括号等等。 每个抽象语法树都是对应的源代码的确切表示,可以用于确定结构正确的程序是否存在一些类型不匹配或不一致的问题。其中,节点对应于源代码的各种元素,例如表达式、声明和语句等。 Golang解析引擎根据构建出的所有抽象语法树,结合golang语言的语义特征,按照特定的顺序对抽象语法树中定义和使用的类型进行检查。 通过对每一棵抽象语法树的遍历,对每一个节点都进行验证以保证当前节点上不会出现类型错误的问题。另外,类型检查的阶段不止会对树状结构的节点进行验证,同时也会对一些内建的函数进行展开和改写,例如make关键字在这个阶段会根据子树的结构被替换成makeslice或者makechan等函数。 当golang解析引擎将源代码转换成抽象语法树并对整棵树的语法进行解析及类型检查之后,就可以认为当前文件中的源代码基本上不存在无法编译或者语法错误的问题了,随后golang解析引擎就会将输入的抽象语法树AST转换成中间代码,即SSA结构。SSA结构是一种具有特定属性的低级中间表示法(intermediate representation),可以更轻松地实现优化并最终生成机器码。 在将抽象语法树转换为SSA结构的过程中,将完成内置函数(functionintrinsics)的处理。这些内置函数属于特殊的函数,golang解析引擎逐个分析这些内置函数并决定是否用深度优化的代码替换它们。 综上,通过各程序语言的解析引擎可以将不同语言类型的源代码转换为SSA结构,然后通过上述多个实施例提供的SSA结构解析方法对源代码的SSA结构进行解析,获得该源代码的CFG结构数据,随后通过数据流分析技术对该源代码的CFG结构数据进行数据流分析,实现了源代码的跨包数据流分析,同时也降低了漏洞检测的误报率,提高了漏洞检测结果的可信度。 基于同一发明构思,本申请实施例中还提供了与SSA结构解析方法对应的SSA结构解析装置100,由于本申请实施例中的装置解决问题的原理与本申请实施例上述SSA结构解析方法相似,因此装置的实施可以参见方法的实施,重复之处不再赘述。 具体请参照图8,图8为本申请实施例提供的SSA结构解析装置100的功能模块图。在本实施例中,该装置应用于电子设备,包括:CFG节点划分模块101、解析模块102、关联模块103。 其中,CFG节点划分模块101,用于根据数据流解析规则,划分出多个CFG节点。 解析模块102,用于针对每一个CFG节点,从程序语言的源代码的数据类型中查找与各CFG节点对应的目标节点,并抽取目标节点中的信息写入与该目标节点对应的CFG节点中,获得解析后的CFG节点,其中,源代码的数据类型包括多个AST节点类型及多个SSA节点类型。 关联模块103,用于将解析后的CFG节点进行关系的关联,以获得可用于数据流分析的CFG结构数据。 进一步地,请继续参照图8,在本实施例中,SSA结构解析装置100还包括: 漏洞分析模块104,用于根据漏洞分析规则及数据流分析方法对CFG结构进行漏洞分析,获得漏洞检测结果。 其中,更进一步地,在本实施例中,关联模块103包括以下子模块: 节点连接子模块,用于根据源代码解析CFG节点的对应关系,连接CFG节点。 CFG边连接子模块,用于根据源代码上下文的执行逻辑连接CFG边。 AST边连接子模块,用于根据CFG节点之间的包含关系连接AST边。 可选地,在本实施例中,节点连接子模块,具体用于:循环遍历源代码中每行代码中所有CFG节点的对应关系,并将CFG节点进行连接与对应。 进一步地,请继续参照图8,在本实施例中,SSA结构解析装置100还可以包括: 源代码分析模块105,用于对源代码进行分析,获得对应的程序语言类型,其中,程序语言类型包括go语言。 源代码输入模块106,用于根据程序语言类型将源代码输入至对应的解析引擎中进行解析,其中,解析引擎包括go语言解析引擎。 具体地,在本实施例中,源代码输入模块106,包括分析子模块; 其中,分析子模块用于对源代码进行词法分析及语法分析,获得该源代码的SSA结构数据。 更进一步地,在本实施例中,分析子模块具体用于: 对源代码进行词法解析,转换成对应的标记序列Token,其中,标记序列Token包括标识符、关键字、分隔符、操作符、文字和注释中的至少一种; 对标记序列Token进行语法分析,根据语法特征将标记序列Token构建为抽象语法树AST; 根据抽象语法树,结合源代码的语法特征,将抽象语法树转换为SSA结构数据。 关于装置中的各模块的处理流程、以及各模块之间的交互流程的描述可以参照上述方法实施例中的相关说明,这里不再详述。 本申请实施例还提供了一种电子设备60,如图9所示,为本申请实施例提供的电子设备60的结构示意图,包括:处理器61、存储器62、和总线63。存储器62存储有处理器61可执行的机器可读指令(比如,图8中的装置中CFG节点划分模块101、解析模块102、关联模块103、漏洞分析模块104、源代码分析模块105、源代码输入模块106功对应的执行指令等),当电子设备60运行时,处理器61与存储器62之间通过总线63通信,机器可读指令被处理器61执行时执行上述实施例一至五中任意一个实施例的方法。 本申请实施例还提供了一种存储介质,该存储介质上存储有计算机程序,该计算机程序被处理器61运行时执行上述任一实施例的方法的步骤。 具体地,该存储介质能够为通用的存储介质,如移动磁盘、硬盘等,该存储介质上的计算机程序被运行时,能够执行上述任一实施例的方法,从而解决目前的数据流分析技术无法实现跨包分析的问题,进而降低漏洞分析的误报率,提升分析结果的可信度。 在一些实施例中,处理器61可以包括一个或多个处理核(例如,单核处理器61(S)或多核处理器61(S))。仅作为举例,处理器61可以包括中央处理单元(Central ProcessingUnit,CPU)、专用集成电路(Application Specific Integrated Circuit,ASIC)、专用指令集处理器61(Application Specific Instruction-set Processor,ASIP)、图形处理单元(Graphics Processing Unit,GPU)、物理处理单元(Physics Processing Unit,PPU)、数字信号处理器61(Digital Signal Processor,DSP)、现场可编程门阵列(FieldProgrammable Gate Array,FPGA)、可编程逻辑器件(Programmable Logic Device,PLD)、控制器、微控制器单元、简化指令集计算机(Reduced Instruction Set Computing,RISC)、或微处理器61等,或其任意组合。 所属领域的技术人员可以清楚地了解到,为描述的方便和简洁,上述描述的电子设备和装置的具体工作过程,可以参考方法实施例中的对应过程,本申请中不再赘述。在本申请所提供的几个实施例中,应该理解到,所揭露的电子设备、装置和方法,可以通过其它的方式实现。以上所描述的装置实施例仅仅是示意性的,例如,模块的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,又例如,多个模块或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些通信接口,装置或模块的间接耦合或通信连接,可以是电性,机械或其它的形式。 作为分离部件说明的模块可以是或者也可以不是物理上分开的,作为模块显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。 另外,在本申请各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。 功能如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个处理器61可执行的非易失的计算机可读取存储介质中。基于这样的理解,本申请的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本申请各个实施例方法的全部或部分步骤。而前述的存储介质包括:U盘、移动硬盘、ROM、RAM、磁碟或者光盘等各种可以存储程序代码的介质。 另外,在本申请各个实施例中的各功能单元可以集成在一为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,应当理解,本申请中附图仅起到说明和描述的目的,并不用于限定本申请的保护范围。另外,应当理解,示意性的附图并未按实物比例绘制。本申请中使用的流程图示出了根据本申请的一些实施例实现的操作。 应该理解,流程图的操作可以不按顺序实现,没有逻辑的上下文关系的步骤可以反转顺序或者同时实施。此外,本领域技术人员在本申请内容的指引下,可以向流程图添加一个或多个其他操作,也可以从流程图中移除一个或多个操作。 另外,所描述的实施例仅仅是本申请一部分实施例,而不是全部的实施例。通常在此处附图中描述和示出的本申请实施例的组件可以以各种不同的配置来布置和设计。因此,以下对在附图中提供的本申请的实施例的详细描述并非旨在限制要求保护的本申请的范围,而是仅仅表示本申请的选定实施例。基于本申请的实施例,本领域技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本申请保护的范围。 可选地,为了解决上文中针对源代码的跨包数据流检测的问题,本申请还提供另一种可能的实现方式。 请参照图10,图10为本申请实施例提供的结构解析方法的流程图之一。该解析方法应用于电子设备,包括: 步骤S301,根据数据流解析规则对程序语言的源代码进行解析,获得多个解析节点。 可选地,该数据流解析规则可以与图2中步骤S101中的数据流解析规则为同一规则,其可以被定义为对源代码进行标记化与解析的规则,其作用在于将源代码中的每个源文件构造为语法结构,且当该源代码存在跨多个源文件的数据流时,获得该程序语言的源代码在不同源文件之间的执行路径信息,即该解析节点表征程序语言的源代码的语法结构及所述程序语言的执行路径信息。 需要说明的是,所谓标记化中的标记可以指上文所述“标记序列token”,其可被设置为一组预定义的、可被识别的字符串;语法结构可以采用抽象语法树来实现,即可以为前文所述AST节点;执行路径信息可以采用前文所述CFG节点实现。 步骤S302,将多个解析节点进行关系的关联,以获得可用于数据流分析的结构数据。 在上述步骤中,由于在同一个路径下的语法结构是唯一的,通过语法结构和执行路径就可以找到语法结构中的方法,因此,通过上述将源代码解析为结构数据即可实现源代码的跨包数据流分析。 在上述实施例的具体实施过程中,首先需要根据数据流解析规则对程序语言的源代码进行解析,获得多个解析节点。可选地,该解析节点可以为上文所述AST节点、CFG节点(即控制流图节点)或两者组合。在此基础上,本申请提供另一种可能的实现方式,请参照图11,图11为本申请实施例提供的图10中的步骤S301的子步骤流程图。在本实施例中,步骤S301具体包括以下子步骤: 子步骤S3011,通过抽象语法树解析规则对程序语言的源代码进行解析,获得至少一个抽象语法树节点。 可选地,参见前文,可通过抽象语法树解析规则对程序语言的源代码进行词法分析,即可通过token对源代码进行标记,构成标记序列token。 其中,抽象语法树节点表征程序语言的源代码的语法结构。 子步骤S3012,通过控制流解析规则对程序语言的源代码进行解析,获得至少一个控制流图节点。 其中,控制流图节点表征程序语言的执行路径信息。 需要说明的是,抽象语法树节点与控制流图节点的生成顺序没有先后的限定,也就是说,本申请实施例中的步骤S3011和步骤S3012不做先后顺序限定。 具体地,在本步骤中,以golang语言进行举例说明。golang语言的源代码存储在cmd/compile目录中,golang解析引擎一般承担着词法分析、语法分析、类型检查和中间代码生成等工作。 在将golang语言的源代码输入至golang解析引擎之后,golang解析引擎可以对由golang语言编写获得的源代码进行词法分析,将源代码转换为一系列的Token。随后golang解析引擎扫描Token,根据golang语言的语法特征构建出源代码的抽象语法树(AbstractSyntax Tree,AST)。 在将golang语言的源代码输入至golang解析引擎之后,golang解析引擎可以对由golang语言编写获得的源代码进行解析,参见前文,可以划分出多个控制流图节点。 在上述实施例的具体实施过程中,为了实现对程序语言的源代码中涉及跨包/不同文件结构的执行路径信息识别,首先需要对该程序语言的源代码的整体文件结构或包结构进行识别,为此,在一种可能的实现方式中,本方法利用能够体现程序语言的源代码的完整文件结构的静态单赋值结构数据,该数据可以包含上文SSA节点。在此基础上,本申请提供另一种可能的实现方式,结合图12,图12为本申请实施例提供的图10中的步骤S301的另一子步骤流程图,在步骤S3011之后,步骤S301还可以包括以下子步骤: 步骤S3013,对至少一个抽象语法树节点进行静态单赋值转换,获得程序语言的源代码对应的静态单赋值结构数据。 可选地,参见前文,可以通过源代码的语法特征将抽象语法树节点转换为静态单赋值结构数据。 可选地,参见前文,当golang解析引擎将源代码转换成抽象语法树并对整棵抽象语法树的语法进行解析及类型检查之后,可以将输入的抽象语法树节点转换成中间代码,即静态单赋值结构数据。静态单赋值结构数据是一种具有特定属性的低级中间表示法(intermediate representation),可以更轻松地实现优化并最终生成机器码。需要说明的是,静态单赋值结构数据可以包括至少一个前文的SSA节点。 对于子步骤S3012,参见前文,针对上述的每一个控制流图节点,可以根据各个控制流图节点的注释内容从抽象语法树节点或者静态单赋值节点中查找与各控制流图节点对应的目标节点,并将查找到的各个目标节点中的信息抽取出来,写入对应的控制流图节点中,完成对所有控制流图节点的解析,解析完成后的控制流图节点中包含有源代码的执行路径信息及语法结构。最后,将各个控制流图节点进行关联,即可获得可用于数据流分析的控制流图结构数据。 在上述实施例的具体实施过程中,可以通过遍历的方式获取控制流图节点之间的对应关系,在此基础上,本申请提供另一种可能的实现方式,在本申请实施例中,步骤S3012具体可以包括以下子步骤: 遍历完整文件结构中的每个文件,获得全部控制流图节点之间的对应关系,以构成程序语言的执行路径信息。 具体地,可以遍历完整文件结构中的每个文件,确定全部控制流图节点的边信息的执行逻辑关系,以获得全部控制流图节点之间的对应关系。 例如,对于一个go语言中的测试命令“test.go”,当完整文件结构为:“a/b/c/test1.go”及“a/b/test.go”时,说明测试命令“test.go”分别位于文件a-b-c下以及文件a-b下;该测试命令“test.go”实际上存在一个跨越文件c与b的跨包数据流,以及其执行路径信息跨越了文件c与b。那么参见上文,可通过上文步骤S3013,来获得该静态单赋值结构数据,该静态单赋值结构数据可以体现该程序语言的代码包含a、b、c三个文件,以及其之间的层级关系。进而通过遍历每个文件,即可获得测试命令“test.go”全部控制流图节点之间的对应关系,以构成程序语言的执行路径信息。 在一种可能的实现方式中,上述抽象语法树节点与控制流图节点存在多种可能的连接关系,例如,抽象语法树节点与抽象语法树节点之间的连接关系、控制流图节点与控制流图节点之间的连接关系,以及抽象语法树节点与控制流图节点之间的连接关系,为了体现各个节点之间的连接关系,在一种可能的方式中,引入了边信息的概念,其可以包括进边和出边; 其中,进边表示与上一个节点的连接关系,出边表示与下一个节点的连接关系。当上述节点包括边信息时,可以通过边信息来体现该节点与其他节点的连接关系,因此,在获得节点时,可以得到节点的边信息。 具体的,当该节点为抽象语法树节点时,抽象语法树节点的边信息表示在一条程序语言的代码语句中,语句中各节点的包含关系;当该节点为控制流图节点时,控制流图节点的边信息表示的是控制流的顺序,也就是代码中每一条语句的执行顺序。 例如,源代码可以为“a=b.c(e)”,通过抽象语法树解析规则对源代码进行解析得到三个抽象语法树节点,分别为identifier节点-a,call节点-b,identifier节点-e;通过控制流解析规则对源代码进行解析,获得一个控制流图节点,即根据整行赋值语句代码生成一个call节点-stmt节点。 其次,对抽象语法树节点进行转换,得到静态单赋值结构数据,stmt节点的出边信息会连接a、b节点,a、b节点的入边信息会连接stmt节点,b节点的出边信息会连接e节点,e节点的入边信息会连接b节点。然后,可以遍历静态单赋值结构数据中的每个文件,确定全部控制流图节点的边信息的执行逻辑关系,stmt节点的入边信息会连接这行代码的上一行,下一行代码则连接stmt的出边信息。 对于步骤S302,需要说明的是,各个解析后的控制流图节点中包括有源代码的信息,源代码之间的对应关系即为各个解析后的控制流图节点之间的对应关系。因此,对源代码进行解析即可获得各个控制流图节点之间的对应关系,再根据各控制流图节点之间的对应关系将各个控制流图节点连接起来。 在本实施例中,边是指不同节点之间的对应关系的表示。根据源代码上下文之间的执行逻辑连接控制流图节点的边信息,使控制流图节点之间的连接线可以用于指示整个控制流图结构数据的执行逻辑。可选地,参见前文,图4提供了一种常见的控制流图结构数据的示意图。 进一步地,为了对源代码进行漏洞分析,在对源代码进行解析,获得结构数据之后,还需要通过相应的数据流分析技术对结构数据进行分析,从而得到漏洞分析的检测结果。具体地,如图13所示,图13为本申请实施例提供的结构解析方法的另一流程图,在步骤S302之后,该方法还可以包括: 步骤S303,根据漏洞分析规则及数据流分析方法对结构数据进行漏洞分析,获得漏洞检测结果。 可选地,该漏洞分析规则可以与图5中的步骤104中的漏洞分析规则为同一规则,其可以被定义为从数据中分析出漏洞的规则,其可以按照预设的频率进行更新,其中收录了源代码编写过程中出现频率较高的漏洞的分析方法,通过该分析方法,可以分析出大多数经常出现的漏洞,从而保证源代码的正常运行。另外,漏洞分析规则按照预设的频率进行更新,可以保证该漏洞分析规则可以适用于大部分的新型漏洞,提高漏洞检测的准确率。 在具体的实施方式中,可以结合参照图1,将源代码解析后获得的结构数据以及漏洞分析规则输入至数据流分析算法中进行数据分析,即可输出分析结果,该分析结果用于表征源代码中是否存在代码漏洞,以及具体的代码漏洞出现在哪一段代码中。 上述方式对源代码的控制流图结构数据进行数据流分析,解决了目前的数据流分析无法跨包分析的技术问题,实现源代码的跨包数据跟踪,降低了漏洞的误报率,提高了检测结果的可信度。 综上,通过各程序语言的解析引擎可以将不同语言类型的源代码转换为静态单赋值结构数据,然后通过上述多个实施例提供的结构解析方法对源代码的静态单赋值结构数据进行解析,获得该源代码的结构数据,随后通过数据流分析技术对结构数据进行数据流分析,实现了源代码的跨包数据流分析,同时也降低了漏洞检测的误报率,提高了漏洞检测结果的可信度。 基于同一发明构思,本申请实施例中还提供了与结构解析方法对应的结构解析装置400,由于本申请实施例中的装置解决问题的原理与本申请实施例上述结构解析方法相似,因此装置的实施可以参见方法的实施,重复之处不再赘述。 具体请参照图14,图14为本申请实施例提供的结构解析装置400的功能模块图。在本实施例中,该装置应用于电子设备,包括:源代码解析模块401和节点关联模块402。 源代码解析模块401,用于根据数据流解析规则对程序语言的源代码进行解析,获得多个解析节点,所述解析节点表征所述程序语言的源代码的语法结构及所述程序语言的执行路径信息。 节点关联模块402,用于将所述多个解析节点进行关系的关联,以获得可用于数据流分析的结构数据。 需要说明的是,源代码解析模块401还可以执行上述步骤S3011和步骤S3012实现对应效果。关于装置中的各模块的处理流程、以及各模块之间的交互流程的描述可以参照上述方法实施例中的相关说明,这里不再详述。
- 结构解析方法、装置、电子设备和存储介质
- PLC梯形图解析方法、装置、电子设备及可读存储介质