首页> 中国专利> 一种基于插桩的基本块粒度下工控协议语法逆向分析方法

一种基于插桩的基本块粒度下工控协议语法逆向分析方法

摘要

本发明公开了一种基于插桩的基本块粒度下工控协议语法逆向分析方法,具体包括:对工控协议二进制可执行程序实现指令、基本块和函数粒度的动态插桩,在动态污点分析过程中记录指令粒度的污点传播信息以及基本块粒度、函数粒度、逻辑判断和跳转信息,生成程序运行时日志文件。日志文件通过重排序和相关分析算法,实现基本块粒度下的工控协议字段边界识别。本方法相较于函数粒度下的字段边界识别方法,可以获取更多基本块粒度下的程序上下文信息,从而识别出在同一函数下处理的不同字段,提升了字段边界识别精度。

著录项

说明书

技术领域

本发明涉及工业通信网络协议与协议逆向工程技术领域,特别涉及一种基于插桩的基本块粒度下工控协议语法逆向分析方法。

背景技术

工控协议作为现代工业控制系统网络拓扑的重要组成部分,在工控系统安全研究中有着重要的意义。对于工控协议的安全研究可以大体分为两部分:协议本体安全性研究以及协议安全应用。其中,协议本体安全性研究的一个热门领域是对于协议实现程序的模糊测试:通过预先设定一定的协议输入格式作为种子,模糊测试工具可以产生不同的输入以测试协议实现程序中存在的缓冲区溢出等脆弱性。在协议安全应用中,通过报文解析可以构建入侵检测系统,这也是轻量级工控系统网络安全加固的研究热点。上述两个领域的发展都离不开工控协议标准的获取。

协议标准可以分为协议语法、协议语义和协议状态机三部分。协议语法刻画了协议的字段边界;协议语法描述了协议各个字段的具体功能和含义;而协议状态机则是协议报文时序关系的体现。出于市场占有、安全等多方面因素考虑,工控厂商通常选择开发独有的协议用于其生产的设备通信,并保留其协议标准不进行公开。对于安全领域的研究者而言,这意味着其需要通过各种方式——软件逆向、数据比对等手段进行协议的格式信息获取,而这一过程无疑需要耗费大量的时间。此外,工控协议通常采用二进制协议,其格式有着严格的规定,并且隐去了语义信息,使得人工进行协议逆向难度倍增。

目前针对工控二进制协议的自动化逆向方法采用动态污点分析技术,从函数粒度上进行字段边界的划分,这种逆向方法在分析通过条件分支语句而非函数封装实现的协议功能时会出现无法准确划分字段边界的情况。本发明基于基本块粒度的细粒度协议逆向分析方法可以有效解决上述问题。

发明内容

本发明的目的在于针对现有技术的不足,提出一种基于插桩的基本块粒度下工控协议语法逆向分析方法。

本发明的目的是通过以下技术方案实现的:一种基于插桩的基本块粒度下工控协议语法逆向分析方法,该方法包括以下步骤:

S1:对工控协议的二进制可执行程序进行插桩,获取指令及函数粒度的运行时信息,将网络接收函数接收的协议报文数据标记为污点源数据;记录污点源数据及后续污点数据的污点状态信息,在程序运行过程中,依据污点传播规则,追踪污点数据在内存和寄存器中的传播情况,获取协议报文数据和程序上下文的关系。

S2:对函数粒度进行插桩,获取函数名称、函数进入和退出信息;对基本块粒度进行插桩,获取基本块入口地址和长度信息;对指令粒度的逻辑判断和条件跳转相关汇编指令进行插桩,用于标记逻辑边界。

S3:依据S1和S2设计的插桩方法,记录程序运行时上下文信息,形成格式化日志文件。

S4:对日志文件进行预处理,剔除网络接收函数不相关线程日志,并依据地址数据进行函数日志、基本块日志、指令日志的重排序。

S5:对预处理后日志文件进行分析,以逻辑判断和条件跳转指令为逻辑边界划分依据,将日志中记录的基本块序列划分为多个逻辑块,构建逻辑块和协议报文数据的关联关系,依据关联关系进行协议报文字段边界的划分,从而完成语法判别。

进一步地,所述步骤S1具体包括:

S11:对工控协议的二进制可执行程序进行插桩,具体使用程序插桩框架Pin进行指令粒度和函数粒度的插桩。

S12:对于函数粒度使用回调函数识别函数名称,进行Linux x86-64操作系统标准库网络接收函数recv、recvfrom、recvmsg的判断,并将其接收的工控协议报文数据标记为污点源数据。

S13:对污点源数据和后续传播的污点数据记录污点状态信息,包括污点数据对应的工控协议报文数据中字节偏移地址、数据长度、数据移位情况、数据是否被标记为污点状态。

S14:对于指令粒度使用回调函数识别指令的操作符和操作数,对于mov,add,or和移位指令,识别指令的操作数,如果操作数中存在污点数据,则更新污点数据信息。

S15:对于使用污点数据为操作数的指令,使用回调函数在日志文件中记录其汇编指令、操作数、污点数据信息。

进一步地,所述步骤S2具体包括:

S21:在函数进入和退出时进行函数名称、函数状态、线程ID、起始地址、结束地址和返回地址的记录;

S22:在跳转至新基本块时,进行基本块入口地址、基本块占用字节长度、线程ID信息的记录;

S23:针对每一条执行的指令进行字节码的反汇编,若指令为cmp、test或条件跳转相关指令,进行汇编指令、线程ID、指令长度信息的记录。

进一步地,所述步骤S3具体包括:依据S1和S2设计的插桩方法,在程序运行过程中将函数、基本块和指令粒度日志有序记录至txt格式日志文件中。

进一步地,所述步骤S4具体包括:

S41:剔除没有出现污点数据的线程ID对应的日志记录,包括指令、基本块和函数粒度;剔除系统调用函数的日志记录;

S42:进行日志记录的重排序,具体规则为:函数的进入日志在相关基本块日志前、基本块日志在相关指令日志前、函数的退出日志在函数的返回指令日志后;

S43:将重排序后的日志记录输出到新的日志文件中。

进一步地,所述步骤S5具体包括:

S51:对S4处理得到的日志文件进行离线分析,其中函数日志表征一个函数节点,基本块日志表征一个基本块节点,一个基本块起始到结束间的污点数据相关指令日志表征一个报文数据节点,在分析过程中逐渐建立以下关系:函数节点下包含多个基本块节点序列,基本块节点的末端为报文数据节点,形成一个树状图结构;

S52:使用rsp值是否变化以及是否出现逻辑判断和条件跳转指令判断是否存在逻辑边界,依据逻辑边界对基本块节点及其子节点中的报文数据节点进行合并,合并后的一个基本块节点包含多个基本块,刻画了一个程序实现时的逻辑块;

S53:对于程序中可能存在的循环结构体,进行循环判断,合并循环结构体中的基本块和报文数据节点;

S54:针对构建的树状图结构,进行协议报文字段边界划分。

进一步地,所述S54中协议报文字段边界划分依据如下:

规则a:同一协议字段的字节会在相同的逻辑块中进行处理,如果两个字节出现在不同的报文数据节点中,即认为其是不同的字段;

规则b:对于通过寄存器移位操作合并的字节,统一认为其属于同一字段,规则b优先级高于规则a;

规则c:如果一个字节通过规则b被划分到不同的字段中,则将包含该字节的字段合并;

规则d:通过规则a、b、c划分后剩余的字节,连续的字节自动合并为同一字段。

与现有的函数粒度下的工控协议逆向分析方法相比,本发明具有以下优势:

1.将分析粒度由函数粒度细化到基本块粒度,在程序动态运行过程中可以捕获更多的程序上下文信息;

2.针对未封装至函数进行处理而使用条件分支进行功能实现的字段,可以使用基本块粒度下的条件跳转作为逻辑边界,得到更准确的字段边界;

3.同样具有对二进制协议实现程序分析的普适性,且不影响分析速度。

附图说明

图1是本发明方法的架构图;

图2是本发明方法中动态污点分析方法涉及的污点状态初始化和污点传播示意;

图3是以自定义测试协议为例的函数粒度分析结果树状图;

图4(a)、图4(b)是以自定义测试协议为例的基本块粒度分析结果树状图;

图5是以Modbus/TCP协议为例的结果树状图。

具体实施方式

下面结合附图和具体实施例对本发明作进一步详细说明。

本发明的基本架构如图1所示,本发明实施例中,待测工控协议的二进制可执行程序作为程序插桩模块的输入,插桩模块使用Pin进行开发,通过c++语言定制指令、基本块和函数粒度的回调函数,接收工控协议报文数据作为污点源数据,并进行程序动态运行过程中的污点传播和程序运行上下文记录。使用Pin动态运行程序后,通过脚本向对应网络端口发送待分析报文,插桩模块监测并将动态写入程序运行日志,日志包括污点传播、函数进入退出、基本块进入以及逻辑判断、条件跳转指令的记录。动态生成日志后,通过日志分析模块对日志进行离线处理,日志分析模块主要包括三个部分,首先对日志进行清洗,过滤不需要分析的线程日志,并对日志进行重排序以符合直观语义,便于后续分析;梳理后的日志记录顺序即程序运行时的正确顺序,通过这种顺序,构建函数节点、基本块节点和协议报文字节数据节点的树状关系,并可视化输出;最后通过字段边界判别规则,进行报文的字段边界划分并输出至命令行。通过上述处理,最终得到待测试协议报文对应的语法信息。

本发明实施例提供的基于插桩的基本块粒度下工控协议语法逆向分析方法,具体实现流程如下:

S1:图2显示了动态污点分析方法在本发明中的应用思路。对于Linux x86-64操作系统中的网络接收函数recv、recvfrom和recvmsg函数,使用Pin提供的RTN_InsertCall函数获取对应函数参数信息,以定位接收的报文字节地址并将其标记为污点源数据;在程序运行过程中,保存特定地址、寄存器对应的污点信息,并对内存拷贝、算术运算、移位指令这些会导致污点状态变化的指令单独编写污点传播规则相应的回调函数,使用INS_InsertCall函数进行指令的分析和回调函数的调用。这些信息将被写入日志文件中。

S2:除动态污点分析所必须的插桩过程外,分别对函数、基本块和指令粒度进行插桩,其中函数使用RTN_InsertCall进行插桩,并使用RTN对应API函数获取函数名称、函数状态、线程ID、起始地址、结束地址和返回地址信息;对基本块使用BBL_InsertCall函数,记录新基本块入口地址、基本块占用字节长度、线程ID信息;对于指令,若其为cmp、test或条件跳转相关指令,记录具体汇编指令、线程ID、指令长度信息,具体实现举例如下:

S3:编译pintool,并使用Pin和该pintool运行协议可执行二进制elf程序,并对协议对应端口发送待分析报文,获取运行时日志文件。得到的日志文件格式摘要如下:

具体地,Function行表征函数的进入和退出状态,并解析了函数名称;Block行表征进入了新的基本块,并获取其中的入口指令地址、rsp、基本块大小信息;Misc行记录了cmp、test语句以及条件跳转语句;Instruction行记录了污点传播的指令信息。

S4:进行输出日志的整理,具体如下:

S41:协议程序在具体实现时通常采用单独的线程进行数据的接收和处理,对于其他线程而言,并没有继续分析的价值,通过检索Instruction记录对应的线程ID可以锁定需要分析的线程,剔除多余的信息;此外,在运行过程中,动态链接库可能通过过程链接表(plt)方式进行调用,在优化等级较高时Pin将无法追踪函数的返回地址,会对后续分析造成影响,因此函数名带有“@plt”相关字符串的函数记录也会被一并剔除。

S42:Pin在处理指令级的信息和基本块级信息时,会优先插桩指令层的回调函数,后进行基本块的起始判断,因此在初始日志中,相关的日志顺序会存在错位现象,具体如下:

在分析时,合理的顺序应是函数进入相关日志行在所包含的基本块日志行前,函数退出日志行作为结束,基本块日志行在其包含的指令日志前,因此有必要进行顺序整理,在整理顺序过程中涉及到函数、基本块和指令行的调换,主要通过比对地址的值判断是否需要调整顺序。

S43:将重排序后的日志记录输出到新的日志文件中。

S5:通过日志记录的程序运行信息还原树状图结构,恢复协议报文的格式信息,具体步骤如下:

S51:对S4处理得到的日志文件进行离线分析,其中函数日志表征一个函数节点,基本块日志表征一个基本块节点片段,一个基本块起始到结束间的污点数据相关指令日志行表征一个报文数据节点,在分析过程中逐渐建立以下关系:函数节点下包含多个基本块节点序列,基本块节点的末端为报文数据节点,形成树状图关系;

S52:基本块粒度下的协议逆向依据为同一字段中的字节会在相同的条件分支中进行处理,条件分支在汇编指令层通常表现为cmp、test指令和条件跳转指令的结合,在分析时,若cmp、test和跳转指令连续出现,则认为是编程逻辑上的分界标识,将前面的基本块节点和附带的数据节点进行合并。rsp的值被用于辅助判断函数的进入和退出,通常函数进入和返回时有对堆栈的操作,这会导致rsp值的变化,因此rsp变化时,需要新建一个基本块节点。具体的,当rsp值减小时,新建基本块节点作为当前节点的子节点,rsp值增大时,新建基本块节点作为当前函数节点的子节点,rsp值不变时,则依据逻辑判断和条件跳转指令判断是否新建基本块节点;

S53:使用逻辑判断和条件跳转指令划分逻辑边界会导致在循环结构体中每一个循环都单独生成基本块节点,从而使其子节点中的报文数据节点包含的报文字节被错误识别为不同字段,因此需要进行已执行基本块信息的记录,当访问已遍历的基本块时,即认为存在循环体,与前面节点进行合并,对于循环调用函数的情况,报文数据会首先按函数粒度进行分割,因此可以仅考虑末端函数节点下基本块的循环结构,可以在函数进入和退出时,将记录清零,减少内存开销;

S54:针对构建的树状图结构,进行报文的边界划分,具体依据如下:

规则a:同一协议字段的字节会在相同的逻辑块中进行处理,如果两个字节出现在不同的报文数据节点中,即认为其是不同的字段;

规则b:对于通过寄存器移位操作合并的字节,统一认为其属于同一字段,规则b优先级高于规则a;

规则c:如果一个字节通过规则b被划分到不同的字段中,则将包含该字节的字段合并;

规则d:通过规则a、b、c划分后剩余的字节,连续的字节自动合并为同一字段。

具体实现中,对每个数据节点进行编号,并构建报文字节与包含该字节数据节点编号的字典映射关系,通过实现上述规则判断的逻辑完成字段边界识别。

以C语言实现的自定义测试代码为例,下面的源码展示了对协议实现程序存储数据的某一位进行值设定的功能,在该实现中,一个字节被用于表示数据中需要修改的位的偏移量,另一个字节表示将该位置0或置1。由于两个字节在同一函数dataHolding下使用,基于函数粒度的协议逆向并不能准确分析得到两个字节之间的边界,而本发明中的细粒度分析方法可以准确定位两个字节的边界。

图3展示了基于函数粒度的上述协议报文语法逆向分析可视化结果,其中矩形节点表示函数节点,而椭圆形节点表示数据节点,涉及上述功能实现的第4、5字节边界并没有被区分;图4(a)、图4(b)展示了添加基本块粒度后的报文语法逆向分析可视化结果,圆矩形节点即细化粒度后的基本块序列,图4(b)展示了节点C后续子节点,可以看到节点C后续节点中第4、第5字节出现在不同的数据节点中,因此其边界被准确识别。

图5展示了对Modbus/TCP开源实现协议程序libmodbus的分析可视化结果,由于整棵树过大,因此选取了部分节点作为示意。发送的报文为“\x01\x11\x00\x00\x00\x06\x01\x03\x00\x02\x00\x08”,分析字段边界后命令行输出结果如下,直观地得到了字段分割结果:

本发明的逆向分析结果依赖于提取被分析程序在设计开发时对协议报文字段的语义实现,对于在协议程序编程中未被使用的字段,则无法准确分析其内部更具体的边界分割情况,这些字段通常在安全研究等后续应用中不具有关键作用,因此对本发明的后续应用制约不大。

上述实施例用来解释说明本发明,而不是对本发明进行限制,在本发明的精神和权利要求的保护范围内,对本发明作出的任何修改和改变,都落入本发明的保护范围。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号