程序逆向分析在软件供应链污染检测中的应用研究综述

2020-03-06 12:55武振华颜学雄
计算机应用 2020年1期
关键词:污点静态程序

武振华,张 超,孙 贺,颜学雄

(1.战略支援部队信息工程大学 数学工程与先进计算国家重点实验室,郑州 450001;2.清华大学 网络科学与网络空间研究院,北京 100084; 3.陆军工程大学 指挥控制工程学院,南京 210007)

0 引言

近年来,软件供应链(Software Supply Chain, SSC)安全问题频发,在给用户的隐私和财产带来巨大损失的同时,也对软件供应链的安全防护提出了新的考验和挑战。有别于传统的针对软件自身程序漏洞进行的攻击,软件供应链攻击者侧重利用软件供应链上的安全漏洞,在合法软件的开发编译、分发交付以及安装使用等环节中进行劫持或篡改,借助用户和软件供应商之间的信任关系,在合法软件的外衣下,突破安全产品的防线,获得用户的信任,悄然实施攻击[1]。这种攻击的结果导致了软件供应链污染。

目前关于软件供应链安全的研究刚刚起步,文献[2]列举了多个宏观层面的研究,概述了软件供应链定义、安全威胁、防御手段等方面的内容。在具体技术方面,文献[1]对软件供应链污染技术、软件供应链污染主动防御方法以及针对WordPress的供应链安全污染检测技术进行了研究。目前尚未有工作对软件供应链安全研究的其他问题进行研究和综述。

文献[3]指出,自动化程序分析技术是软件供应链安全研究的重点内容,但是当前多数软件供应链污染检测研究仍处于手工或半自动分析阶段。多数工作利用手动分析或自动化分析工具辅助分析的方法进行研究,鲜有工作能够实现自动化分析并检测软件是否被污染。

自动化程序逆向分析技术一直是信息安全领域研究的热点和重点问题之一,已有大量工作对程序逆向分析和恶意代码检测技术进行了研究。在基础程序分析方法方面,文献[4]对静态分析方法进行了深入研究;文献[5]对动态分析方法进行了综述;在现今主流的程序分析技术方面,文献[6]对符号执行和污点分析技术进行了综述;在程序分析技术的应用方面,文献[7]对恶意代码分析技术进行了全面的研究,但是尚未有工作系统性地分析现有程序逆向分析方法及其应用技术(恶意代码检测)是否可以满足软件供应链安全研究的需要。

本文主要关注针对二进制程序的软件供应链的污染检测技术,在软件供应链下游发现供应链中存在的污染问题。本文主要工作及贡献包括:

1)对软件供应链污染检测问题进行了深入剖析和阐述;

2)指出了软件供应链污染检测问题与传统恶意程序分析和检测问题的联系和区别;

3)介绍了目前使用的程序逆向分析方法及其在软件供应链污染检测中的应用;

4)展望了软件供应链污染检测中亟待解决的问题及若干可行并值得进一步研究的课题。

针对上述问题,本文详细分析了22个软件供应链污染事件;对97篇高水平论文进行了分析和介绍,文献主要来自中文核心期刊以及中国计算机学会(China Computer Federation, CCF)A类会议、期刊;内容涵盖了程序分析技术以及软件供应链污染研究前沿研究。论文搜索关键词包括(中英文的)程序分析、逆向工程、静态分析、动态分析、符号执行、污点分析、软件供应链、软件供应链污染等。绝大多数论文下载自谷歌学术、知网、百度学术等知名学术搜索平台,内容涵盖了信息学科下主流数据库,包括国际计算机协会(Association for Computing Machinery, ACM)、电气和电子工程师协会(Institute of Electrical and Electronics Engineers, IEEE)、爱思唯尔、斯普林格等。

1 软件供应链污染检测问题

1.1 研究背景

软件供应链是指软件从软件供应商到达用户手中并被用户使用的整个过程中相关环节的连接,从软件设计开始,到代码编写与软件生成,再到软件分发与用户下载,并最终由用户使用的一个软件供应商与软件用户之间,紧密围绕软件,由开发环节(上游)、交付环节(中游)和使用环节(下游)三大环节所组成的链状结构[1,8]。软件供应链攻击是指攻击者利用软件供应商与最终用户之间的信任关系,在合法软件的开发、传播和升级过程中进行劫持或篡改,从而绕过传统安全产品检查并达到非法目的的攻击类型[1,9]。如图1所示,软件供应链攻击可能发生在软件供应链的任意环节。软件供应链攻击的结果是造成了软件供应链污染,攻击者在用户运行了被污染的软件后开始实施后续攻击。与传统的漏洞挖掘利用和终端病毒感染不同,软件供应链污染更加强调由于第三方原因造成的软件供应链上的软件产品的安全威胁,主要包括攻击者攻击造成的软件篡改或使用第三方代码库而引入的恶意代码及安全漏洞。表1中总结了近几年软件供应链安全事件中,攻击者使用的攻击方式和最终导致污染的位置。

主动防御和被动检测是保障软件安全的两种重要手段。其中,主动防御侧重于阻断攻击者的攻击,主要包括针对软件开发商、开源软件管理平台、软件发布平台和用户终端的安全防护,旨在从源头上遏制恶意代码的植入和扩散。文献[10]对软件供应链各个环节的主动防御策略进行了较为详细的阐述。

图1 软件供应链攻击示意图Fig. 1 Schematic diagram of SSC attack

表1 软件供应链污染事件污染方式总结 Tab. 1 Summary of pollution methods of SSC pollution events

续表

被动检测是假定可能有攻击存在,在生成的软件中检测是否存在污染。软件供应链污染检测属于被动检测,主要包括对开源代码、开源软件包、软件安装包和软件可执行程序的安全性检测。这其中,安全性检测又包括恶意代码检测和漏洞挖掘,检测对象包括程序源代码和程序可执行文件。程序逆向分析技术是安全性检测的基础,文献[11]对其进行了详细阐述。文献[5]对恶意程序检测技术进行了全面的综述。文献[12]对软件安全漏洞检测技术进行了总结。

1.2 软件供应链下游的污染检测

软件供应链下游的污染检测是针对软件的可执行文件或提供的服务进行的污染检测。检测目标是表1中“污染位置”列所示的软件形态。由于软件供应链污染检测涵盖内容过于繁杂,涉及不同编程语言、编译环境、运行环境等,后文主要针对传统的C/C++语言编写、编译得到的程序进行阐述。

1.2.1 研究意义

软件供应链上游的软件厂商和中游的分发平台可能受到成本、效率和利润等因素的制约,不可避免地遗留一些安全漏洞。这些漏洞可能被攻击者利用,导致软件供应链的污染,因此软件供应链的污染源很难被完全消除,仍需要在软件发布之后,即在软件供应链下游对发行的软件进行污染检测。

同时,在软件供应链下游的污染检测能够发现上游、中游的所有污染。从表1中很容易看出,软件供应链污染的代码最终必须要在下游用户端执行才能发挥其效用,因此,软件供应链下游的污染检测能够极大弥补主动防御的不足,对软件进行更加全面的扫描。

再者,软件供应链下游的软件样本比较容易获取。研究人员可以更加容易地获取软件样本进行研究。

1.2.2 问题分析

软件供应链下游的软件供应链污染检测问题与恶意代码检测问题没有本质区别,都是对程序是否恶意的判定。检测流程是,首先搜集软件特征,之后对特征进行结果判定。目前主流的人工智能(Artificial Intelligence, AI)技术完全可以实现高精度的结果判定,但是,其前提条件是要能够搜集到完整的或者关键的软件特征。如果无法搜集到污染代码或污染行为,即使是最先进的AI技术也无法作出准确的判断。然而,在搜集软件特征方面,软件供应链污染检测比传统的恶意代码检测更加复杂,表现在如下几方面。

首先,软件供应链下游的污染检测比传统的恶意代码更为隐蔽,被植入的代码常与正常程序代码混淆在一起,当软件供应链上游被污染时,恶意代码还可能带有合法的软件厂商的签名。由于多数安全防护软件使用白名单机制过滤掉可信任厂商发布的软件,因此其中的污染代码比传统恶意代码更难被发现。

其次,很多被污染的软件会提示用户在使用过程中关闭安全防护软件从而实施攻击,导致程序难以被安全防护软件集成的云查杀系统发现,导致被污染软件可以长期在网络上传播。

再次,软件供应链上的安全检测目标不仅包括软件的可执行程序,还包括软件的安装程序,然而软件的安装过程往往需要借助用户交互来完成;同时,很多软件厂商使用自定义的打包工具发布软件安装包,且不支持静默安装,对于大量存在的此类安装包,现有方法很难实现自动化的用户交互并完成软件安装过程,因此导致其中的污染代码难以被发现。

最后,攻击者还可能在软件中植入恶意代码,这些代码可能隐藏在软件程序的任何角落中,只有当用户通过用户界面(User Interface, UI)使用软件的特定功能,这些代码才能被触发。此时,这些恶意代码极难被分析人员发现。

1.2.3 程序逆向分析与软件供应链污染检测

传统的恶意代码分析技术使用的特征主要分为语法特征和语义特征两大类。程序的语法特征需要通过解析程序的二进制执行,并转换为高级语言(反汇编、反编译)。程序的语义特征主要包括应用程序接口(Application Programming Interface, API)调用和执行过程中的系统状态改变情况。

然而由于代码混淆技术的广泛使用,恶意代码经常主动识别当前的运行环境,或者设置触发条件来执行恶意行为。

传统的单纯依靠被动监控程序执行的方法很难搜集到恶意代码的真实语义,所以,对于带有反分析技术的恶意代码,无论搜集其语法特征还是语义特征,都需要用到程序逆向分析技术。又由于软件供应链下游的污染检测目标主要为可执行程序,因此,需要用到程序逆向分析技术对其进行分析。

后文将首先介绍当前程序逆向分析技术在软件供应链下游的污染检测中的应用,并分析当前技术在解决软件供应链污染检测问题时仍存在的具体问题,最后提出了若干可行的解决思路。

2 程序逆向分析技术的应用

现有的程序分析方法主要包括静态分析、动态分析、符号执行和污点分析。静态分析和动态分析是检测代码安全的基本方法,两者的区别在于获取信息的方式不同:静态分析方法的数据源是可执行文件中的数据,动态分析的数据源是动态执行过程中获取的运行时数据。符号执行和污点分析技术是应用最广泛的二进制程序分析技术,静态分析方法和动态分析方法均可以实现这两种技术。

本文总结了近十年来国内外发生的百余起软件供应链安全事件,标注了安全人员在分析事件样本时使用的程序分析方法,部分结果如表2所示。

传统的静态分析方法在目前软件供应链污染检测中起到了非常重要的作用,分析人员在事件的分析过程中无一例外地使用了交互式反汇编器专业版(Interactive Disassembler Professional, IDA Pro)[35]工具查看反汇编、反编译代码以及程序中各个函数的控制流图。大多数事件的分析过程也用到了动态分析方法,表2标注了事件分析中使用的具体的动态分析方法。同时,符号执行和污点分析两栏标注了自动化分析该事件的样本时否需要该项技术,例如对不存在对抗的样本可以直接用动态跟踪技术跟踪程序行为,而对存在对抗的样本,如“隐魂”木马,在自动化分析时则要借助符号执行和污点分析技术实现。目前供应链污染问题的检测尚处于人工分析阶段,在现有软件供应链污染事件报告中很少提及自动化分析技术的应用。

表2 软件供应链安全事件中使用的程序逆向分析方法 Tab. 2 Program reverse analysis method used in SSC security events

2.1 静态分析

静态分析以静态反汇编[36]技术为核心。静态反汇编技术是指将程序可执行文件中保存的二进制机器码(machine code)解码为汇编代码的过程。主流的静态分析算法包括线性扫描和递归沉降算法[37]。区别是递归沉降算法解析控制流转移指令的目标地址,下一条要解析的指令地址是上一条指令的控制流后继指令的地址,而不是该指令的结束地址。IDA Pro[35]、Capstone[38]、Binary ninja[39]和Ghidra[40]等是使用比较广泛的反汇编及逆向分析工具。

静态分析的最大优势是能够对整个程序的指令进行全面的分析。表2中所示几乎所有软件供应链安全分析工作都使用了静态反汇编或静态分析工具。这些静态分析工具均除提供反汇编功能外,还提供了基于反汇编指令的进一步分析结果,包括可执行文件结构解析、控制流分析[41]、数据流分析[42]、库函数识别[43]、反编译等。

可执行文件结构包含了大量有利于逆向分析的信息,不同平台的可执行文件结构的不同,以Windows PE结构为例,其中的段属性信息指示了数据的类型,反汇编方案只需要针对可执行属性的数据进行分析;导入表信息指示了程序使用的动态链接库及动态链接函数。

控制流分析主要是识别函数中的基本块以及基本块间的流转关系。数据流分析主要识别指令操作数间的依赖关系,一般基于控制流分析实现。数据依赖分析是现在应用最广泛的数据流分析方法,程序切片[44]、污点分析[45]、约束求解[46](符号执行[47])等技术都直接或间接地应用了数据依赖分析技术。同时,主流的静态分析工具在静态反汇编过程中都会默认实现控制流和数据流分析,用于获取控制流图和代码间的引用关系。

库函数识别是静态分析方法优势的重要体现。静态链接库函数体嵌入在程序代码中,由于二进制程序中没有符号表信息,静态链接库函数需要用特定的方式进行识别。目前通用的方法是通过对已知静态链接库函数建模得到唯一的特征,并在程序分析时分析各个库函数,查看其特征是否与已知静态链接库函数的特征一致。例如在CCleaner事件[27]中,奇安信安全团队通过分析异常库函数发现恶意代码被植入在C语言动态运行库(C Run-Time library, CRT)中[48],进而推断出实施攻击的方法。

反编译是将汇编代码翻译成高级语言的过程,目前主流反编译工作需识别不同的处理器架构,仅支持一部分架构的汇编语言。高级语言能够帮助分析人员更好地理解程序逻辑,极大地提高了人工分析样本的效率;但是,恶意程序常在运行过程中动态解密、释放指令或数据[49-50],静态分析方法很难检测该问题。Oh等[51]为提高静态分析的准确度,提出了基于贝叶斯优化的自适应学习方案,并以此建立面向数据流和上下文的部分静态分析工具。Jeong等[52]通过非线性的上下文选择,建立识别上下文敏感函数的学习方法,并设计了数据驱动的上下文敏感的指针分析方案。但这两种方案并不能从根本上解决问题,动态分析方法更适合对其进行分析。

2.2 动态分析

动态分析以动态跟踪技术为核心。在动态跟踪过程中获取原始数据,之后再利用这些数据进行后续分析。动态跟踪可以获得不同语法语义级别的数据,跟踪过程中可以按照指令、基本块、函数等不同粒度搜集程序本身的语法信息,也可以在程序运行过程中搜集系统信息,根据系统状态的变化来表征程序行为;或在运行时搜集系统调用信息,用来刻画程序行为;或者监控内存权限变化,例如先写后执行(execute-after-write)[53-54]或先重构导入表信息再执行(execute-after-rebuild)[55]等特征来表征程序的自脱壳行为。

目前主流的动态分析平台主要采用三种方式构建运行环境。第一种是基于QEMU[56]的全系统模拟方案。混合符号执行(concolic execution)方案S2E(Selective Symbolic Execution)[57]、TEMU(BitBlaze[58]的动态跟踪模块)均基于QEMU实现。全系统模拟的好处是能够获得整个系统的信息。例如表2中列举的“隐魂”“异鬼”木马病毒事件,恶意代码与正常程序安装包捆绑发布,并注册系统服务或安装程序驱动,借助服务或驱动实现恶意代码持久化以及其他部分功能。此时,基于全系统模拟的分析平台能够在动态分析过程中发现这些行为。

第二种方式是使用代码插桩的方式进行动态跟踪,包括动态插桩和静态插桩两种方式。动态代码插桩是在程序运行过程中插入分析代码。Intel Pin[59]是使用最广泛的动态插桩方式,例如DynamoRIO[60]、Mayhem[61]等均基于Pin实现。此外DynInst[62]和Valgind[63]也是比较著名的动态插桩工具。静态插桩方法主要以二进制重写(Binary Rewrite)为核心,代表性的工作包括MIL[64]和Pebil[65]等。由于动态插桩需要在程序执行时执行额外操作,以调用执行跟踪的回调函数,因此静态插桩方法的开销普遍低于动态插桩方法;但是由于静态插桩方式在程序执行之前完成插桩,当恶意程序引用恶意的第三方库,或存在自修改代码,或静态分析被干扰时,该方法将造成漏报。

第三种方式是使用硬件特性记录程序的执行序列。典型工作是Intel Processor Tracing (PT)[66],信息搜集工作位于硬件CPU上,需要主机提供硬件支持。由于该技术采用硬件机制实现,因此跟踪速度最快,特别适用于构建基于Fuzzing技术的漏洞挖掘方案;但是PT获取的信息不完整,跟踪得到的信息需要额外计算时间进行解码。

绝大多数软件供应链安全威胁检测都需要借助动态分析方法来完成,表2中标注了各个事件的分析过程中具体涉及的动态分析方法,包括了在动态执行过程中对程序本身以及各种系统资源,如系统资源、服务、驱动、流量信息等的监控。此外,表2中标注的“动态字符串提取”和“监控代码动态释放”是指污染代码会在动态执行过程中从数据段解密出敏感API名称字符串和敏感操作指令,从而对抗静态分析;“溯源分析”和“系统日志分析”是指利用攻击者在系统或软件中留下的痕迹定位污点源的过程,常用于软件供应链污染源头定位工作。

动态分析方法的瓶颈在于分析覆盖率有限,很容易受到恶意程序作者的恶意干扰。例如“隐魂”木马使用多种反分析技术,防止分析系统搜集到程序恶意行为。对此,研究者们提出了路径探索[67]和透明分析[68]技术。其中路径探索技术是应用最广泛的提高动态分析覆盖率的方法。该技术通过求解不同路径约束的程序输入,引导程序控制流向更高覆盖率方向转移。透明分析着力于构建被分析样本无法感知的分析系统,防止被分析程序因为检测到分析环境而不再执行恶意行为。当程序设定只有在满足特定条件时才会触发恶意代码时,例如分布式拒绝服务(Distributed Denial of Service, DDoS)[69]攻击程序,透明分析平台依然无法搜集到恶意行为,因此,路径探索技术更适用于恶意程序分析工作,该技术已经成为符号执行引擎的内置模块,能够显著减少人工分析的工作量。

2.3 符号执行

动态符号执行又称混合符号执行(concolic execution)。其核心思想是在程序执行过程中搜集路径约束[47],之后根据路径探索策略[70]选择一个需要继续探索的路径,并且求解[71]满足该路径的约束的程序输入,使得控制流向目标路径转移。绝大多数符号执行引擎会将指令转换为中间语言(Intermediate Language, IL),在中间语言上实施符号执行。IR能够消除复杂指令集中存在的指令二义性问题[58]。目前使用最广泛的IR包括Vex[63]、底层虚拟机(Low-Level Virtual Machine, LLVM)[72]等,但文献[73]指出将指令lift为IR会影响分析的效率,进而提出了直接针对特定指令的快速混合符号执行和模糊测试方法。

程序执行路径的路径约束可以在程序执行过程中获取,如S2E[57],被称作在线分析;也可以在程序执行结束后对得到的指令trace进行分析后获取,如Sage[74],被称作离线分析。离线分析模式需要每次从程序入口点开始执行程序进行分析,好处是分析系统不需要维护程序状态,减少了由于保存程序状态而造成的内存开销;在线分析模式不需要重复执行不同路径间的重复指令,但是会随着正在分析的路径数目增大逐渐耗尽系统资源。对此,Mayhem[61]提出了混合模式的符号执行方法。

符号执行技术依靠路径探索策略选择下一个需要分析的路径及需要求解的路径约束。根据不同应用,符号执行引擎会选择不同的路径探索策略,例如:在恶意程序分析和模糊测试应用中,广度优先和深度优先策略应用最为广泛;而在漏洞挖掘应用中,敏感操作优先策略应用更多。具体应用可以定义自己的敏感操作规则,从而使能够引导控制流至敏感操作的路径被优先分析。例如S2E提出了一种面向符号化数据(data-based selection)的路径探索策略,优先执行对污点进行操作的路径。

由于符号执行会造成较大的时间开销,文献[75]中提出了选择符号执行的概念,并实现了能够在动态执行过程中选择部分代码进行符号执行,而剩余代码具体执行(concrete execution)。Chipounov等[57]根据这一思想实现了著名的符号执行引擎S2E,并从一致性角度提出了针对不同应用的六种分析模型[76]。此外,一些符号执行引擎通过静态方法获取元数据,但是也实现混合符号执行的功能。例如二进制程序分析框架Angr[77]首先将程序可执行文件中所有二进制码转换为vex语言,并实施一系列静态分析方法,包括控制流图分析和程序依赖图分析,之后再实施符号执行。通过解释执行的方法弥补静态分析产生的误差。

符号执行的两大难题是路径空间爆炸和约束求解,程序切片[78-79]、程序抽象[80]和等价路径约减[81]等方式可以通过控制约束输入范围来减小程序路径空间,有效缓解路径空间爆炸问题;文献[82-83]利用查询缓存和重用的方式,在调用求解器前优化查询路径条件,以此来减少求解器的调用次数,降低求解时间,然而却对非线性算数运算的约束无能为力;文献[84]将约束转换为满足函数,并以此获取满足相应约束的值。

符号执行是实现路径探索、提高动态分析覆盖率的主要技术。表2中标注了符号执行的事件均需要借助路径探索技术才能搜集到表达程序真实意图的执行路径。在现有软件供应链污染分析报告中,绝大多数还依靠人工分析实现对程序执行路径的探索。Sun等[85]提出了面向深度学习的动态符号执行方法,该符号执行方法将测试需求表示为量化线性运算(quantified linear arithmetic),以神经元覆盖为目标测试深度神经网络的鲁棒性。符号执行策略的更加智能化[86]、与其他技术在不同层面的密切结合[73,87-88]以及面向大规模软件的高效的符号执行方法是下一步研究的重点和难点,也是符号执行的研究趋势。

2.4 污点分析

动态污点分析的主要流程是选择程序的某些输入标记为污点,在程序运行过程中根据污点传播规则标记数据依赖于污点的内存或寄存器。如果从程序中的敏感操作涉及到的数据被标记为污点,则需要对该操作进行进一步分析。

污点分析的一般步骤如下:首先,污点分析系统需要根据实际需求确定污染源。一般以程序外部输入作为污点源,包括程序命令行输入、网络输入、I/O、API返回值、系统状态(如注册表、进程控制块、线程控制块)等。文献[89]主张在恶意程序分析过程中考虑尽可能多的程序输入作为污点源;其次,污点传播规则定义了在何种情况进行污点传播。一般来说满足数据依赖于污点数据的指令的目的操作数会被标记为污点;最后,污点分析系统还需要指定需要执行进一步的敏感操作。一般来说,间接控制流转移(包括间接跳转和间接函数调用指令)、网络传出操作、I/O写操作等都会被标记为敏感操作。在漏洞挖掘应用中,可能产生漏洞的API调用也会被标记为敏感操作。

动态污点分析系统需要克服污点传播过程中可能发生的欠污染和过污染问题,文献[45,97]对此进行了比较详细的探讨,但是目前尚未有完全精确的解决方案。Yadegari等[98]提出了比特级污点分析方案,并将其应用于提高针对混淆代码的符号执行工作中[94],通过污点分析方法搜集能够引发控制流转移的路径约束。该方案还被用于进行控制流图化简[89]和分析由程序异常引发的控制流转移的程序路径[99]。文献[100]中提出了基于逆向计算的细粒度污点分析方法,通过规定逆向计算规则,考虑语句的语义逻辑,推算污点传播策略,有效减少了代码冗余和污点的过度传播。

随着技术的发展,污点分析和符号执行工作的界限越来越模糊,因为符号执行中对路径约束的搜集和求解在本质上也是数据依赖分析,并且例如上述Yadegari的几个工作,利用污点分析帮助符号执行技术完成路径约束的搜集。此外,符号执行和污点分析都可以通过前向或后向的方式实现。文献[95]实现了反向符号执行方法,如果在后向回溯一定步数内,没有发现能够引导新控制流的程序输入,则判定目标约束为无透明谓词。其后向回溯的过程既可以被看作逆向符号执行过程,也可以看作是逆向污点传播过程,因此可以认为,污点分析工作可以用作或者辅助符号执行的约束搜集方法获得更准确的路径约束。

污点分析的思想在软件供应链污染检测中使用非常广泛,特别是在存在信息泄露的事件中。将敏感数据标注为污点源,如果污点数据被网络发送,则说明发生了信息泄露。表2中标注了污点分析的事件多数发生了信息泄露。同样的,目前类似问题仍多数由人工检测完成。

2.5 现有工作的综合对比

现有二进制程序逆向分析工作或在上述某一方面进行了深入研究,或设计实现统一的分析平台,提供各种技术的调用接口。表3中列举了10余个经典的或近年来发表在高水平期刊、会议的二进制程序分析工具,总结了这些工作的适用场景、测试数据集以及对比方法。研究人员可以有针对性地在这些平台上进行软件供应链污染检测工作研究。

表3 二进制程序分析工具的适用场景 Tab. 3 Suitable scenarios for binary program analysis tools

续表

3 仍存在的问题

1.2.2节对软件供应链下游的污染检测问题进行了分析,本章聚焦于程序逆向分析方法,分析现有技术在解决软件供应链下游的污染检测问题中仍存在的问题及挑战。

3.1 程序逆向分析方法自身的局限性

在对程序的逆向分析时,准确识别程序中所有代码或行为至关重要,只有在获取程序中所有代码的基础上,才能进一步实现恶意代码检测工作;然而现有技术在这方面仍存在一些局限性。

3.1.1 传统逆向分析技术的局限

首先,文献[101-103]总结了静态分析方法分析对抗样本时的不足。例如,加壳[104]或代码自修改(self-modification)技术[49-50]的使用,可以将执行恶意行为的代码变成数据存储在二进制文件中,只有程序执行后原始代码才会被执行,静态分析方法很难准确通过指令解释执行的方法分析出原始程序代码;代码混淆技术[105],例如控制流扁平化、不透明谓词、花指令、API混淆等也会干扰静态分析的分析结果,导致误报或漏报;别名分析(Alias Analysis)、值域分析(Value Set Analysis)[106]等分析方法在反向数据流分析、间接控制流转移的目标预测等任务中均无法达到较高的实用性,准确率也偏低,进而导致静态分析方法无法有效准确地判定控制流可达性和发现控制流转移目标,最终导致静态分析方法出现漏报或误报。

此外,文献[107]对多种反汇编工作在x86/x64架构下的反汇编能力进行了全面深入的分析,总结了反汇编工作仍存在的问题。由于反汇编是所有静态分析方法的基础,反汇编能力有限在恶意程序分析领域影响更大。

其次,虽然符号执行、路径探索技术能够提高动态分析的覆盖率,恶意程序依然可以通过隐藏路径约束[94]、利用复杂数学变换攻击约束求解器[108]、使用单向函数阻碍约束求解[109]等技术干扰分析,使得动态分析方法很难搜集到程序的恶意行为。此外,符号执行技术还存在路径爆炸的问题,当程序中存在循环,或者圈复杂度非常大时,程序的所有可执行路径条数将过于庞大,无法逐一分析。此外,动态分析过程中缺乏全局信息,很难在动态执行过程中准确识别静态链接库函数。

3.1.2 缓解技术及其局限

为缓解上述问题,研究人员提出了大量缓解技术,以提高程序逆向分析技术的能力;但是这些技术仍然不能完全解决传统程序逆向分析技术在分析混淆代码时的问题。

首先,动静结合的分析方法能够从很大程度上克服动态分析覆盖率不足的缺点。传统的基于特征码的恶意代码检测、基于熵的分析方法以及静态间接控制流转移识别能够辅助恶意代码检测或指导动态分析朝着目标区域进行动态执行和分析。其中,基于特征码的方法能够从程序代码中找出包含恶意行为特征的字节序列,从而快速完成已知恶意代码的扫描;基于熵的方法能够帮助分析系统标注可能存在加壳行为的代码片段,动态分析应该尽量朝着能够加载或者执行这些数据或代码的方向运行;间接控制流转移指令指示了静态分析的分析盲区,动态分析方法需要对这些指令的位置作定向分析,以确定控制流转移目标,弥补静态分析的不足。文献[110]中提出了一种深度的动静结合分析框架,并实现了针对恶意程序的路径探索策略;但是该工作效率较低,不适用于大型软件的分析。目前尚未有工作实现了针对大型软件的深度的动静结合分析方法。文献[111]中提出了超集反汇编(Superset Disassembly)的方法,从任意一个可能成为合法指令的地址开始反汇编,从一定程度上缓解了静态反汇编方法无法获取间接控制流转移地址的问题,也能为提高动态分析覆盖率提供导向依据。

在API识别方面,文献[112]中提出了基于模式匹配的API识别方案,该方案虽然受到人工先验知识的制约,漏报率较高,但具备很强的可扩展性;不同于传统的静态分析方法需要比对完整的函数代码的签名来实现库函数识别,文献[113]中提出了一种基于函数参数识别的针对混淆程序的API识别方法,能够识别被混淆的API调用,该方案的准确性受制于函数参数识别的准确率,但其识别准确率较高,能够极大提高分析效率。

在控制流图恢复方面,文献[114]中提出了一种基于静态符号执行的,针对控制图扁平化的控制流图还原方案,针对LLVM混淆器(Obfuscator-LLVM, OLLVM)[102]的控制流扁平化结果较好,但是受制于静态符号执行中存在复杂约束无法求解问题。文献[115]中提出了基于强制执行的路径探索、异常恢复以及控制流图还原方案。文献[94]中提出了符号执行技术的增强方案,用于发现符号执行过程中被隐藏的路径约束,从而发现更多的隐藏的控制流转移。文献[99]中提出了一种针对异常处理机制的符号执行方法,能够发现被程序作者故意隐藏的基于异常的控制流转移。文献[95]中提出了不透明谓词检测手段,以判定路径可达性,从而去除控制流图中的不可达部分。

然而这些工作也都各自存在一些局限,只有恶意代码满足其提出的模型时才能取得较高的准确性。例如文献[94]需要flags寄存器参与计算才能准确识别路径约束并实现符号执行;文献[99]需要在动态触发异常的条件下才能实现异常控制流转移的准确识别;文献[95]的方法受制于反向回溯的步长限制,超过预设步长,该方法将出现漏报。其次,没有工作显示上述方法能够集成在同一个平台中执行,其检测目标均为单个可执行文件程序,没有工作显示这些方法能够在大型商用软件中高效执行。

综上所述,现有的程序逆向分析技术在对混淆代码的检测中仍存在诸多局限,恶意程序作者可以利用这些局限对抗分析,造成分析系统的漏报。特别是在软件供应链污染场景下,被测样本规模远大于恶意程序,给程序逆向分析技术带来了更多挑战。

3.2 程序逆向分析技术在SSC应用中存在的挑战

传统的恶意代码检测方案多仅针对单一可执行文件进行分析,导致使用程序分析方法进行软件供应链下游的污染检测时存在诸多挑战。

首先,从表1可知,软件供应链污染的目标包括软件安装包和软件可执行程序,但是大型软件的发布形式十分多样。为了检测可能存在的捆绑安装、内置后门等问题,分析系统需要能够处理任何一种软件发布形式,并从中提取相应的程序进行分析。

例如,大多数官方的Windows软件发布为一个独立的安装程序,需先运行安装程序,将软件运行所需要的所有文件释放到指定目录,并在系统中注册相关软件信息,才能使用该软件。同时一些软件也会以绿色压缩版的形式发布,即将所有程序运行所需文件打包在一个压缩包中,用户只需解压这些文件即可使用软件。这种绿色免安装的方式极易被攻击,但是由于使用方便无需安装,仍有大量用户使用。

分析系统需要能够自动执行或解压缩安装包,成功释放程序可执行文件,并监控整个安装和程序执行过程。目前尚未有工作能够实现自动、稳定的大规模软件安装方法来获取程序分析的二进制文件。

第二,商用软件往往包含多个模块、多个组件以及多种语言编写的代码,需要提出高效和统一的分析框架用于深入程序分析。此外,市场上的防病毒软件多使用白名单机制,如果程序的签名在白名单中则不再对其进行分析,而在软件供应链开发环节中植入的恶意代码,在下游程序签名发布之后往往会逃避防病毒软件的检测。由于无法保证软件供应链上游代码的安全性,传统的基于黑白名单的启发式分析策略在软件供应链安全研究中并不适用,需要对整个程序中所有的代码深入分析。

第三,商用软件多包含多种程序输入,例如配置文件、UI交互、网络通信、与操作系统交互等。这将导致动态分析方法将很难自动发现并提供有效的程序输入,从而引起与程序输入相关的代码无法正常执行,最终造成动态分析方法的分析覆盖率很难提升,进而导致恶意代码检测或漏洞挖掘方法出现漏报。同时,异步处理机制是常用的编程技术,而尚未有静态分析方法工作能够做到自动理解各种异步编程模型,并准确还原程序逻辑或控制流转移关系。

第四,现有工作多处于语法分析层面,鲜有工作能够自动准确理解程序语义,而程序语义理解在恶意代码检测和软件逻辑漏洞检测方面非常重要。基于机器学习和AI技术的恶意代码分析和检测工作能够部分缓解语义理解补充的问题,但是该方法依赖大量样本,而除C/C++语言外,其他编程语言的恶意代码样本量均达不到模型训练要求。在漏洞挖掘领域,针对逻辑漏洞的挖掘大多依靠人工完成,尚未有可靠的自动化方法完成该任务。在具有多模块的大型软件中,逻辑漏洞的挖掘变得更加困难,目前没有较为理想的解决方案。

4 总结与展望

对于发生在软件供应链上的安全事件,安全分析人员往往采取综合利用传统的程序逆向分析方法来分析还原事件真相,然而此方法大多依赖于手工的调查取证,很难实现对软件供应链上的软件进行快速、安全、自动的检测。针对软件供应链安全问题的特殊性以及现有的程序逆向分析方法的局限,可采取以下可行方案来弥补程序逆向分析方法在软件供应链安全研究中存在的缺陷和不足:

首先,在软件供应链下游进行研究的数据源为软件安装包或绿色版软件压缩包,因此,要进行该项研究,必须解决软件自动安装获取其可执行文件的问题。目前对软件自动安装的研究很少。可行的方案包括:1)基于规则的自动安装;2)借助文字识别的基于规则的自动安装;3)借助机器学习方法的自动安装;4)基于生成对抗网络的自动安装。

第二,在软件自动安装之后,结合Lehman软件进化法则[116]进行软件的家族分类和血统分析[117],此外,也可结合机器学习方法,可以利用已知版本号的软件及其元数据特征,训练血统预测模型,实现对未知软件的血统分析。将血统分析后的待测软件与同一家族中上一版本软件进行对比,获取待测软件中的差异代码;然而传统的恶意程序家族分类方法仅针对单个可执行文件进行分析,而商用软件大多包括多个可执行文件和配置信息,目前尚未有工作实现针对大型软件的家族分类和血统分析工作。尤其是针对绿色版软件,可执行文件释放到磁盘后并不会在系统配置信息中留下痕迹,例如版本号信息等,对于这类软件的血统分析工作需要进一步研究。

第三,获取待测软件的差异性代码后,只需利用程序逆向分析方法对这些差异代码进行检测分析,以此来过滤掉软件中大量的安全代码,极大减少分析的代码量,提高检测效率。在软件代码深入分析方面,可以利用动静结合的分析框架、基于非一致执行的分析方法可以帮助分析系统部分解决深层次路径无法覆盖的问题。

第四,对于基于异步模型的代码触发问题,分别针对UI、网络连接等常见场景进行各个击破是可行的解决办法。基于反馈的UI自动触发技术可以避开代码层面的异步触发模型,通过监控模拟鼠标点击的程序状态改变以及代码片段间的数据依赖关系,可以提高带UI界面程序的代码覆盖率。通过劫持系统调用,可以控制程序的网络连接状态,自动填充模拟数据报文,并结合基于二进制代码分析的协议逆向技术[118],可以推断报文格式,进而更好地实现模糊测试、生成程序输入报文。

第五,针对程序的语义理解问题,可以通过API调用来表征程序语义,并自动查询API手册得到API的具体解释,通过拼接API解释的方法,将程序表征为自然语言文字。一方面可以利用自然语言表示辅助程序语义理解;另一方面,由于在不同编程语言中具有相同功能的API的自然语言解释十分相近,可以通过该方式实现跨编程语言的程序分析。

猜你喜欢
污点静态程序
最新进展!中老铁路开始静态验收
莫让“污点”变“终点”
静态随机存储器在轨自检算法
动得多,还要坐得少——评WHO《身体活动与静态行为指南》
给Windows添加程序快速切换栏
黑蚂蚁
试论我国未决羁押程序的立法完善
猜猜他是谁
污点
“程序猿”的生活什么样