一种基于动态污点分析的工业通信协议逆向分析方法转让专利

申请号 : CN201910401745.1

文献号 : CN110213243B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 程鹏郑豪陈积明孙优贤

申请人 : 浙江大学

摘要 :

本发明公开了一种基于动态污点分析的工业通信协议逆向分析方法,包括:对协议可执行程序动态插桩,对协议报文接收和处理的相关函数与指令进行监控,并在此基础上进行动态污点分析。在动态污点分析过程中记录相应信息,输出到日志文件,并根据日志文件分析协议格式。本方法能够基于工业控制系统通信协议的可执行程序在动态运行中自动分析出协议格式信息,不需要获得程序的源代码,避免了繁琐耗时的人工动态调试分析过程,使得对工业控制系统中未知通信协议的格式逆向分析过程变得简单高效。

权利要求 :

1.一种基于动态污点分析的工业通信协议逆向分析方法,其特征在于,包括以下步骤:步骤1:对工业控制系统中未知协议的可执行程序进行插桩,所述插桩具体为基于动态二进制插桩工具提供的多粒度插桩接口对工业控制系统中未知协议的可执行程序进行插桩,所述多粒度插桩接口包括动态库、函数、指令,然后通过分析报文接收函数,定位通信过程中报文数据的内存位置与长度,并将这些数据标记为污点数据,完成污点初始化;

步骤2:对可执行程序中的内存拷贝函数和数据读写汇编指令进行插桩,监控所有污点数据在程序动态运行过程中的传播过程,并将传播到的寄存器和内存全部标记为污点,完成污点的传播;

步骤3:在可执行程序运行过程中记录函数调用的上下文,并记录所有涉及污点数据的指令和函数操作,将这些记录输出到日志文件;

步骤4:编写脚本分析日志文件,针对可执行程序,构建包含污点数据的函数调用关系图,判断报文的字段边界,输出该未知协议的格式。

2.根据权利要求1所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤1和步骤2中,在使用Pintool工具对操作系统的标准动态库进行函数粒度插桩时,将标准动态库的函数包装一层外层函数,将包装后的函数编译成本地动态库,并使可执行程序优先选择本地动态库库中函数,完成对函数入口和出口的插桩;所述外层函数与原函数的名称与参数类型相同。

3.根据权利要求1所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤1和步骤2中,a.使用map数据结构保存每个污点数据的污点状态,用于记录和查询可执行程序运行过程中各个寄存器和内存的污点信息;

b.对于每个寄存器和内存,记录的污点信息包括:是否污点、污点数据源地址、污点数据字节数、是否大端序;

c.提供函数接口处理污点传播的多种情况,包括污点数据读写,污点数据与、或、移位计算。

4.根据权利要求1所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤1具体包括:a.对标准动态库中recv,recvfrom,recvmsg函数作为污点输入源进行插桩;

b.对Unix/Linux的系统调用read函数作为污点输入源进行插桩。

5.根据权利要求1所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤2具体包括:a.对寄存器、内存、立即数之间的数据传送指令插桩,分析污点数据的传播过程;

b.对读取多个字节相关的算数运算指令插桩,分析污点数据的字节组合情况;

c.对标准动态库中memcpy,memmove函数插桩,分析污点数据的整体拷贝情况。

6.根据权利要求1所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤3具体包括,a.对可执行程序中任意一个函数,记录可执行程序运行过程中函数进入和退出状态;

b.对步骤1和步骤2中的污点相关指令和函数,记录可执行程序运行过程中所有涉及污点数据的指令和函数操作;

c.两类记录按时序顺序输出到日志文件,污点数据信息嵌套在函数上下文记录中。

7.根据权利要求1所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤4中,基于日志文件进行离线分析,将日志中的每个函数视为一个函数节点,每个函数内部的污点数据视为一个数据节点,两类节点在处理过程中形成父子节点关系,通过脚本输出包含污点数据的函数调用关系图。

8.根据权利要求7所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤4中,判断报文的字段边界基于以下判别规则:a.数据节点中单独字节视为一个协议字段;

b.数据节点中作为整体读取的多个字节视为一个协议字段;

c.数据节点中不连续的字节,前一个字节的末尾和后一个字节的起始均视为字段边界;

d.数据节点中前后均为字段边界的字节视为一个协议字段。

说明书 :

一种基于动态污点分析的工业通信协议逆向分析方法

技术领域

[0001] 本发明涉及工业通信网络与协议逆向工程技术领域,特别涉及一种基于动态污点分析的工业通信协议逆向分析方法。

背景技术

[0002] 随着工业网络的发展,许多工业控制系统应用的协议使用基于TCP协议栈的应用层协议。与互联网协议不同,在工业控制系统应用的众多协议之中,许多都是不同厂商私有的非标准非公开协议。而在工业控制系统安全越发重要的今天,这些非标准非公开协议给诸如防火墙,入侵检测,深度包解析等安全防御机制带来了挑战。
[0003] 传统的协议逆向分析方法基于人工分析,具有耗时,易错,不通用等缺点。目前有许多研究和应用工具针对以文本格式为主的计算机协议,而缺乏针对基本采用二进制格式的工业控制协议的逆向分析方法,且工业控制协议具有的内在格式特点也是之前的方法不曾考虑的。因此,针对工业控制协议特点的协议逆向分析方法目前工业控制安全系统所需要的。

发明内容

[0004] 本发明的目的在于针对现有工业通信协议逆向分析技术的不足,提出一种基于动态污点分析技术的工业通信协议的逆向分析方法。
[0005] 本发明的目的是通过以下技术方案实现的:一种基于动态污点分析的工业通信协议逆向分析方法,该方法包括以下步骤:
[0006] 步骤1:对工业控制系统中未知协议的可执行程序进行插桩,通过分析报文接收函数,定位通信过程中报文数据的内存位置与长度,并将这些数据标记为污点数据,完成污点初始化。
[0007] 步骤2:对可执行程序中的内存拷贝函数和数据读写汇编指令进行插桩,监控所有污点数据在程序动态运行过程中的传播过程,并将传播到的寄存器和内存全部标记为污点,完成污点的传播。
[0008] 步骤3:在可执行程序运行过程中记录函数调用的上下文,并记录所有涉及污点数据的指令和函数操作,将这些记录输出到日志文件。
[0009] 步骤4:编写脚本分析日志文件,针对可执行程序,构建包含污点数据的函数调用关系图,判断报文的字段边界,输出该未知协议的格式。
[0010] 进一步地,所述步骤1和2中,基于动态二进制插桩工具提供的多粒度插桩接口对工业控制系统中未知协议的可执行程序进行插桩,所述多粒度插桩接口包括动态库、函数、指令。
[0011] 进一步地,所述步骤1和步骤2中,在使用Pintool工具对操作系统的标准动态库进行函数粒度插桩时,由于标准动态库一般经过编译器优化,Pintool无法定位到函数的退出位置;基于此缺陷,将标准动态库的函数包装一层外层函数,将包装后的函数编译成本地动态库,并使可执行程序优先选择该库中函数,完成对函数入口和出口的插桩;所述外层函数与原函数的名称与参数类型相同。
[0012] 进一步地,所述步骤1和步骤2中,
[0013] a.使用map数据结构保存每个污点数据的污点状态,用于记录和查询可执行程序运行过程中各个寄存器和内存的污点信息;
[0014] b.对于每个寄存器和内存,记录的污点信息包括:是否污点、污点数据源地址、污点数据字节数、是否大端序;
[0015] c.提供函数接口处理污点传播的多种情况,包括污点数据读写,污点数据与、或、移位计算。
[0016] 进一步地,所述步骤1具体包括:
[0017] a.对标准动态库中recv,recvfrom,recvmsg函数作为污点输入源进行插桩;
[0018] b.对Unix/Linux的系统调用read函数作为污点输入源进行插桩。
[0019] 6.根据权利要求1所述基于动态污点分析的工业通信协议逆向分析方法,其特征在于,所述步骤2具体包括:
[0020] a.对寄存器、内存、立即数之间的数据传送指令插桩,分析污点数据的传播过程;
[0021] b.对读取多个字节相关的算数运算指令插桩,分析污点数据的字节组合情况;
[0022] c.对标准动态库中memcpy,memmove函数插桩,分析污点数据的整体拷贝情况。
[0023] 进一步地,所述步骤3具体包括,
[0024] a.对可执行程序中任意一个函数,记录可执行程序运行过程中函数进入和退出状态;
[0025] b.对步骤1和步骤2中的污点相关指令和函数,记录可执行程序运行过程中所有涉及污点数据的指令和函数操作;
[0026] c.两类记录按时序顺序输出到日志文件,污点数据信息嵌套在函数上下文记录中。
[0027] 进一步地,所述步骤4中,基于日志文件进行离线分析,将日志中的每个函数视为一个函数节点,每个函数内部的污点数据视为一个数据节点,两类节点在处理过程中形成父子节点关系,通过脚本输出包含污点数据的函数调用关系图。
[0028] 进一步地,所述步骤4中,判断报文的字段边界基于以下判别规则:
[0029] a.数据节点中单独字节视为一个协议字段;
[0030] b.数据节点中作为整体读取的多个字节视为一个协议字段;
[0031] c.数据节点中不连续的字节,前一个字节的末尾和后一个字节的起始均视为字段边界;
[0032] d.数据节点中前后均为字段边界的字节视为一个协议字段。
[0033] 与现有技术相比,本发明具有以下优势:
[0034] 1.不需要程序源码,只需要运行协议可执行程序,且没侵入性。
[0035] 2.通过动态污点分析,准确分析出协议各个字节在程序运行过程中的流向,以得出准确的协议字段分界结果。
[0036] 3.不针对特定协议程序,具有普适性。

附图说明

[0037] 图1是本发明方法的架构图;
[0038] 图2是本发明方法中内存和寄存器设计类的UML图;
[0039] 图3是以modbus协议为例的结果树状图。

具体实施方式

[0040] 下面结合附图对本发明作进一步说明。
[0041] 本发明的基本架构如图1,协议可执行程序在动态污点分析环境中接收协议数据报文并运行。运行过程中污点分析程序将报文数据作为污点数据初始化,并监控相关函数和指令完成污点数据传播。此外污点分析程序将必要的信息输出到日志文件,经过分析脚本处理后输出协议格式信息。
[0042] 基于动态二进制插桩工具Pintool提供的对映像,函数,轨迹,指令等插桩接口,对目标协议的二进制可执行程序中污点分析相关的函数和指令进行插桩,记录协议数据在可执行程序中的传播过程。具体的,Pintool提供了RTN_InsertCall和InsertPredicatedCall函数来对函数和指令插入回调函数。
[0043] 操作系统中标准动态库经过编译器优化,插桩工具Pintool可能无法定位到函数返回指令地址。因而无法对函数返回位置插入回调函数。通过编写目标函数的包装函数,并将其编译成动态库。通过设定LD_PRELOAD关键字,可执行程序将优先加载其中同名函数,从而让Pintool准确定位。以recv函数的包装函数为例,包装函数和原函数同名、同类型,内部实现调用真实的recv函数
[0044]
[0045] 在数据污点传播过程中,对于每个包含污点数据的寄存器或内存,分别设计了RegT类和MemT类用于储存污点数据状态,包括污点源地址,数据长度,是否大端格式等,而且统一使用map数据结构来保存众多的污点数据。寄存器的map数据结构和相关算法包装在Register类中,内存的相应在Memory类中。各个类的关系与数据结构如图2所示。Memory类和Register类都对外提供了以下函数接口:
[0046] 1.isTainted方法:返回内存地址或寄存器是否被标记为污点数据。
[0047] 2.taint方法:将目标内存地址或寄存器标记为污点数据。
[0048] 3.untaint方法:去除目标内存地址或寄存器的污点标记。
[0049] 4.src方法:返回内存地址或寄存器污点数据源地址。
[0050] 5.offset方法:返回内存地址或寄存器污点数据对应报文数据偏移位置。
[0051] 6.size方法:返回内存地址或寄存器污点数据的字节长度
[0052] 7.value方法:返回内存地址或寄存器污点数据的值。
[0053] 其中寄存器的类相较于内存类多了shift字段和方法。shift字段和bigendian字段用于处理寄存器读取的数据是否为大端数据。例如,报文中两个字段0x010x11按照大端方式表示16进制数字0x111,小端CPU为了正确读取该数据需要单独读取两个字节按照指定方式拼接起来,其对应的二进制代码如下:
[0054]
[0055] 对于shr eax,0x8,eax被左移8bit,监控shr等指令,设置对应寄存器的shift属性。对于add eax,edx,两个字节按照大端格式读取,监控add等指令,设置对应寄存器的size、bigendian属性。
[0056] 通过Pintool函数插桩接口RTN_InsertCall,对网络接收函数插桩,包括标准动态库中的recv,recvfrom,recvmsg函数和Unix/Linux操作系统下的系统调用read函数。设计不同回调函数,定位这些函数中协议数据接收缓冲区地址和协议数据长度,并将对应内存区域标记为污点数据,完成协议数据污点初始化。以recv函数为例子,插桩接口RTN_InsertCall可以传递函数运行时的参数与返回值,其中参数buffer即协议数据接受位置。
[0057] RTN_InsertCall(
[0058] rtn,IPOINT_BEFORE,(AFUNPTR)recv_point,
[0059] IARG_ADDRINT,filter::entry,
[0060] IARG_FUNCARG_ENTRYPOINT_VALUE,0,//socket
[0061] IARG_FUNCARG_ENTRYPOINT_VALUE,1,//buf
[0062] IARG_FUNCARG_ENTRYPOINT_VALUE,2,//len
[0063] IARG_FUNCARG_ENTRYPOINT_VALUE,3,//flags
[0064] IARG_REG_VALUE,REG_RAX,//ret
[0065] IARG_END);
[0066] 通过Pintool指令插桩接口INS_InsertPredicatedCall,对数据移动指令mov,cmov,push,pop插桩,分析寄存器、内存、立即数之间存在的污点数据传播。通过Pintool函数插桩接口,对标准动态库中memcpy,memmove函数插桩,分析内存拷贝过程中污点数据的整体移动。对数据运算指令xor,and,or,shl,shr插桩,分析多个字节污点数据按照大端或者小端端序读取过程。在上述分析过程中,同时输出污点数据信息到日志文件,主要是涉及的污点数据所在原报文位置中的偏移量。
[0067] 通过Pintool函数插桩接口RTN_InsertCall对可执行程序中或者协议处理相关动态库中的每个函数插桩,记录函数进入和退出信息,包括函数名称或符号,线程ID,进入或者退出标记,函数返回地址,函数起始地址,函数结束地址。其中函数返回地址,函数起始地址,函数结束地址用于函数回溯调用者。
[0068] 程序运行过程中,如下格式的文本数据将被输出到日志文件。
[0069]
[0070] 通过Python脚本处理日志,遍历污点信息和函数上下文信息,构造包含污点数据的函数调用树状结构,并用pydot包提供的接口调用Graphviz中的dot可视化工具输出该树状结构。该树状结构中,每个函数以节点表示。每个节点包含子函数的节点或者函数中使用污点数据的信息。
[0071] 根据树状图显示的信息,按照设定规则刻画通信报文字节分割边界。其一,函数的边界作为通信报文字节边界,例如函数A只处理过字节2,那么字节2可视为一个协议字段,和字节1、字节3之间有字段边界。其二,函数中存在指令读取连续字节,例如函数B处理过多个字节按照格式1,[2,3],4总共4个字节,其中[2,3]表示读取字节2,3作为整体,那么字节2,3可视为一个协议字段,与字节1,4之间有字节边界。根据以上规则,最终得到该协议的格式信息。
[0072] 上述实施例用来解释说明本发明,而不是对本发明进行限制,在本发明的精神和权利要求的保护范围内,对本发明作出的任何修改和改变,都落入本发明的保护范围。