精华内容
下载资源
问答
  • 漏洞检测方法如何选?详解源代码与二进制SCA检测原理
    2021-12-07 16:58:16
    摘要:本文探讨的是SCA具体的检测原理,源代码SCA检测和二进制SCA检测有哪些相同点和不同点,在进行安全审计、漏洞检测上各自又有什么样的优势和适用场景。

    本文分享自华为云社区《源代码与二进制文件SCA检测原理》,作者:安全技术猿。

    1、源代码与二进制的关系和特点

    SCA(Software Composition Analysis)软件成分分析,通俗的理解就是通过分析软件包含的一些信息和特征来实现对该软件的识别、管理、追踪的技术。SCA具体的检测原理又是如何实现的,源代码和二进制文件的SCA检测又有哪些相同点和不同点,下面内容就来回答一下上述疑问。

    对应编译类型的语言(C/C++/Go/Rust),都是遵循:源代码—>编译—>链接—>二进制文件的过程。影响二进制文件的因素包括不同的CPU架构(ARM、X86、PPC、MIPS…),不同的操作系统(Wndows、Linux、iOS、Android…),不同的编译优化选项(O0~O3),即使是同一套源代码,最终编译生成的二进制文件之间也是差别非常大的。注:上述影响因素不涉及java语言

    从上面可知源代码和二进制文件之间存在巨大的差别,源代码是基于高阶语言来编写,是给人看的,人看了很方便理解其中语句的语义;而二进制是由流(指令流或字节流)来构成的,是给计算机“看”的,对人来说是非常不友好,不好理解。

    源代码包含了变量符号类型、函数名称、类名称、代码逻辑结构等大量丰富的代码信息,相反为保留二进制文件的紧凑性,编译生成的二进制文件中会丢弃掉很多运行时用不到的信息,只保留程序正确运行必要的信息,比如被丢弃的信息有变量类型、变量名称等符号信息,可能被保留的有类名称、函数名称等信息,一定会保留的有常量字符串数据。另外为了保证程序的正确运行,还会有保留一个相应的配置信息,比如jar包中的manifest信息、POM信息、maven信息、资源文件等。基于这些特点源代码SCA和二进制SCA的检测原理也存在很大的不同。

    2、源代码SCA检测原理

    由于源代码中包含有丰富的程序信息,因此源代码的SCA检测既有大颗粒度的检测方法,也有细颗粒度的检测方法。

    2.1 大颗粒度检测方法

    根据源代码文件的相似度来判断属于什么组件和版本;文件相似度可以基于hash的严格匹配方法,也可以根据文本相似度匹配方法;这种匹配方法的优点是效率高,匹配速度极快,确定是也很明显,基于hash的容易漏报,基于文本相似度的准确率低;

    2.2 细颗粒度检测方法

    经过源代码—>词法分析—>Token提取—>语法分析—>AST抽象语法树—>语义分析过程来提取相应的数据,再通过机器学习、NLP、CFG调用图、DFG数据流图等等匹配算法进行代码相似度的检测,这种基于语义的代码相似度检测与基于文本相似度检测相比准确率高;

    2.3 具备包管理机制的语言:

    比如Java、Go,可以通过引用的开源软件包信息来实现开源软件的关联分析,这种方法可以几乎可以100%准确的分析出引用的开源软件名称。

    3、二进制SCA检测原理

    虽然好多源代码中具有的信息在二进制文件中不存在,但是对于常量字符串、部分类名称、函数名称、以及一些配置信息还是存在的,并且这些信息具备一定的不变性,即受cpu架构、不同编译优化选项的影响很小,因此二进制SCA主要从二进制文件中提取这些方面的不同特征,再运用匹配算法进行相似度计算,并根据相似度门限来检测出引用的开源软件名称和版本号。

    结合分析二进制代码中的CFG调用图、DFG数据流图等信息进行更加精准的检测,但由于这些分析需要对二进制文件进行指令反汇编,导致分析时间非常的长,分析效率低下,因此这种SCA检测方法不适合对大规模二进制文件进行扫描。

    4、源代码SCA和二进制SCA功能对比

    可以试试下面的漏扫服务,看看系统是否存在安全风险:>>>漏洞扫描服务

    点击关注,第一时间了解华为云新鲜技术~

     

    更多相关内容
  • FIT:基于深度学习和图匹配的二进制软件漏洞检测,谢卓思,梁洪亮,近年来,二进制软件在日常生活中起到越来越重要的作用,而其安全现状却不容乐观。为此,该文提出了一种基于特征学习和图匹配的混
  • 因此,二进制代码分析被用于许多原因,包括软件取证,恶意软件分析,性能分析和调试。文献中有很多二进制代码分析方法,其中最常用的有符号执行、concolic执行、静态污染分析和动态污染分析为了验证我根据之前一篇...

    源代码在大多数软件安全分析的情况下是不可用的。因此,二进制代码分析被用于许多原因,包括软件取证,恶意软件分析,性能分析和调试。文献中有很多二进制代码分析方法,其中最常用的有符号执行、concolic执行、静态污染分析和动态污染分析为了验证我根据之前一篇文章所提出的一种想法,准备一步步进行实现。首先需要建立自己的污点分析工具,污点分析分为静态和动态。对于动态污点分析已经有一系列工具被提出,本文将进行详细介绍。
    为了改善符号执行中发现的一系列问题,研究者们开始污点分析,最早的污点分析是由Funnywei提出的(Bufer Overfow Vulnerability Mining Model [Z/OL])。污点分析以三元组的形式表现:污点源(source)、污染汇聚点(sink)、无害处理(sanitizer)。接下来用一个例子来详细描述一下污点分析三元组在具体程序中的表现。
    污点分析三元组示例
    污点分析通过对系统中敏感数据进行标记,继而跟踪标记数据在程序中的传播以检测系统安全问题。上图是一段Android应用程序代码,运行该段程序会导致用户的密码数据通过发送信息的方式泄露;污点分析可以有效地检测该问题。污点分析首先要识别引入敏感数据的接口(污染源)并进行污点标记,如上图第4行引入密码数据的passwordText接口为污点源,并对pwd变量进行污点标记。如果被标记的变量又通过程序依赖关系传播给其他变量,那么根据相关传播规则继续标记对应的变量,例如上图中pwd变量的污点标记按照箭头进行传播,所以第5行的leakedPwd变量和第6行的leakedMessage变量都将会被标记,当被标记的变量达到信息泄露的位置(污点汇聚点)时,则根据对应的安全策略进行检测上图中第8行带污点标记的leakedMessage变量可以传播到发送信息的sendTextMessage接口,这就意味着这里是敏感数据会被泄露的地方。在第9行,密码数据通过加密转化后赋值给sanitized变量,继续传播sanitizedPwd变量并不会产生泄露问题,也就是说,如果污点变量经过一个使数据不再携带隐私信息的接口处理(无害处理),那么就可以移除污点数据的污点标记。
    总结一下,污染源是将一些不可信或机密的输入数据引入应用程序的地方,这些输入数据可能来自应用程序API或网络接口。污点汇聚点是应用程序中执行安全操作(例如敏感的银行事务)的敏感点,需要对其进行保护,以免应用程序的完整性、机密性和可用性受到侵犯。无害处理指的是通过删除有害操作(如可能导致应用程序运行出其预期操作[7]的恶意程序),被污染的输入数据不再被认为对应用程序的信息安全有害的过程。
    污染分析方法有两种,静态污染分析(STA)和动态污染分析(DTA)。在STA中,分析程序通过检查中间代码而不执行应用程序来测试应用程序。静态污染分析主要是通过两个步骤进行的,包括对中间代码进行反汇编和对得到的汇编代码进行分析。它有时可能使用二进制代码进行应用程序安全分析。然而,由于源代码很少附带COTS软件,这使得STA方法更难对抗恶意程序,从而减少了它的应用。类似地,用STA方法分析二进制代码也经历了复杂和挑战。例如,具有强大规避技术的恶意软件可以很容易地避开STA方法。这些限制促使我们确定替代方法,这些方法可以克服这些缺陷,从而准确可靠地分析应用程序。
    另一方面,在DTA中,应用程序将在运行时测试可能的漏洞[12]。STA和DTA方法各有优缺点。例如,在应用程序中进行信息流分析时,DTA可能会受到运行时开销的影响,这可能会导致无法分析所有代码,从而导致无法发现一些潜在的威胁。另一方面,由于STA只分析应用程序代码而不执行它,它可能会受到准确性问题的影响。因此,一些研究人员提出了将这两种技术结合起来分析应用程序缺陷或漏洞的工具:

    1. Constructing a hybrid taint analysis framework for diagnosing attacks on binary programs
    2. TeICC: targeted execution of inter-component communications in Android
    3. A hybrid analysis framework for detecting web application vulnerabilities

    一些研究人员在DTA前后使用STA方法:

    1. A hybrid analysis framework for detecting web application vulnerabilities
    2. Combined approach to solving problems in binary code analysis

    例如,在这样做时,在DTA之后使用STA,以查看使用DTA后的分析是否遗漏了任何可疑的东西。可以在DTA之前使用STA来分析应用程序在实际环境中执行代码之前的行为。
    通常,DTA方法是在硬件级或代码级实现的。例如,一些DTA方法是在硬件内部实现的。尽管这种实现提供的开销相对最低,但由于它需要对处理器进行重大的架构和微架构更改,因此灵活性较差,实用性较差。通过使用源代码工具来跟踪受污染数据的传播,DTA也可以在软件的代码级执行。这种方法也不太实用,因为在大多数应用程序中,源代码很难用于安全性分析。然而,为了在不修改硬件或源代码的情况下执行数据流跟踪,DTA方法如:

    1. Dytan: a generic dynamic taint analysis framework
    2. libdft: Practical dynamic data flow tracking for commodity systems
    3. Argos: an emulator for fingerprinting zero-day attacks for advertised honeypots with automatic signature generation
    4. BitBlaze: A new approach to computer security via binary analysis
    5. Dta++: dynamic taint analysis with targeted control-flow propagation

    使用二进制代码执行安全分析。这种方法被更广泛地使用,因为它支持各种各样的分析。对于我来说,使用二进制代码的DTA方法是我们感兴趣的焦点。

    展开全文
  • 该策略主要通过标记所有输入函数的返回值为污染数据(系统输入,其他输入函数等),污染通过程序的执行以一种直接的方式传播,例如,一个操作数被污染,则二进制操作的结果也会被污染。如果右值被污染,则被复制的...

    动态污点分析

    Example

    动态污染关键点

    一个污点分析的策略要解决三个问题:1)一个污点是如何引入程序中;2)污染的数据如何在指令的执行中进行传播;3)受污染数据如何被检测出来。

    1. 污染的引入(污点如何引入程序)
      污染引入规则指明了污染具体事如何传入软件系统。典型的惯例事将所有变量、内存单元等初始化为未受污染的状态。我们只将一个用户输入表示为get_input(.)调用,实际中get_input(.)表示系统系统调用返回的值,库调用返回的值等。污染策略通常还会区分不同的输入源。如:面向网络输入源可能总是会引入污染,而从可信配置文件读取的文件就不会。此外,可以独立跟踪特定的污染源。
    2. 污染的传播(污染的数据如何在指令的执行中进行传播)
      污染引入规则指明了污染具体事如何传入系统。由于污染表示是一个比特位,所以通常使用命题逻辑来表示传播策略。
    3. 污染检测(受污染数据如何被检测出来)
      通常的做法是使用污染状态决定运行时程序的行为(例如,一个攻击检测者遇见一个跳转目标地址被污染会停止执行)。通常在操作执行前添加检测器,根据结果来执行相应的动作。

    典型的污染策略

    动态污染分析的一个典型应用是攻击检测,如下图给出了一个典型的攻击检测策略(污染跳转策略),通常将这种策略实现选择进行对比来提出污点分析中的难点会更加具体,这种策略重点在攻击检测,而其他的污染分析还是和通常的污点分析很相似。
    跳转污点分析,其中P(.)代表参数被省略,污染状态通过布尔值来表示,T,F
    上图表示跳转污点分析,其中P(.)代表参数被省略,污染状态通过布尔值来表示,T,F

    跳转污点分析策略主要目的是保护可能存在脆弱点的程序免受控制流劫持的攻击,主要思路是:一个输入源的值绝对不能覆盖一个控制流的值例如,一个返回地址或函数指针。但是,控制流的漏洞可以用输入源的值覆盖跳转目标(例如,返回地址指向的内容)。跳转污点分析策略通过确保被污染的跳转目标永远不会被使用,从而确保了对此类攻击不会产生有效的攻击。这种污染策略并不适用于所有的程序,因为它不考虑内存地址是否会收到污染,所以可能会mis一些攻击。
    该策略主要通过标记所有输入函数的返回值为污染数据(系统输入,其他输入函数等),污染通过程序的执行以一种直接的方式传播,例如,一个操作数被污染,则二进制操作的结果也会被污染。如果右值被污染,则被复制的变量也被污染,等等。

    x := 2*get_input(.)
    y := 5 + x
    goto y
    

    通过上面的例子可以看到,这段程序通过grt-input()获取输入,假设是20之后乘2。由于所有的输入都被标记为污染,所以2*get_input(.)也被标记为污染的二进制,x被标记为污染的变量。在第二行,x被加上5赋值给y,所以y也是被污染的变量。在第三行程序跳转到地址y,因为y被污染了,所以程序被停止。

    动态污点分析的难点

    • 污染地址:需要区分内存地址和内存单元,这两个并不是对于所有的情况都恰当;
    • 污染不足:动态污点分析不能恰当的处理一些信息流的类型;
    • 过污染:决定什么时候引入污染比决定什么时候传播污染容易多了;
    • 检测的时机 VS 攻击的时机:当攻击时才检测,动态污点分析告警太迟了;

    1.污染地址
    内存操作包含两个值:被引用的内存单元的地址,存储在这个内存单元的值。在之前跳转污染策略中跟踪内存地址污染状态和内存单元存储的值污染状态是独立分开的。这一策略类似于指针的污染状态(对应本例中的地址)和内存单元中存放地址指向的对象(对应本例中的内存单元)是分开的方法。(* A theory of type qualifiers*这篇文章介绍过)选择污点分析策略
    上图表示选择污点分析策略

    x := get_input(.)
    y := load(z + x)
    goto y
    

    用户提供一个作为表格索引的输入,然后将表查找的结果用作跳转的目标地址。假设地址是固定宽度(32bit),攻击者能选择任意的x值来发现他希望找到的地址。这样攻击者就能跳转到内存中任何未被污染的地方。在很多程序中,这将允许用户违反程序的预期控制流,从而违反安全原则。因为跳转污点分析策略是允许攻击者跳转到未污染的内存地址,但是攻击者能通过覆盖其他的地方来决定位置。(可以通过上面两个例子对比跟具体的了解)解决办法:可以通过同时检查内存单元值和内存地址是否被污染来确定。( Dynamic taint analysis for automatic detection, analysis, and signature generation of exploits on commodity software,Dawn Song写的)
    然而,被污染的地址政策也有问题。例如,tcpdump程序具有与上述程序类似的合法代码。在tcpdump中,首先读取网络数据包。数据包的第一个字节被用作一个函数指针表的索引来打印数据包类型,例如,如果数据包的字节0是4,IPv4打印机被选择然后被调用。在上面的代码中z代表函数调用表的基址,x是数据包的第一个字节。因此,受污染的地址修改将导致tcpdump的每一次重要运行都会引发一个受污染的错误。其他代码结构,如switch语句,也会导致类似的表查找问题。这就导致了过污染的问题。

    2.控制流污点分析
    动态污染分析跟踪数据流污染。然而,信息流也可以通过控制依赖关系发生。如果说语句s1控制语句s2是否执行,那么语句s2依赖于语句s1。在A theory of type qualifiers中可以找到后支配因子的控制依赖的精确定义。

    x := get_input(.)
    if x = 1 then goto 3 else goto 4
    	y := 1
    z := 42
    

    这个程序中y就是控制依赖第2行,因为是否执行第3行取决于第2行的判断,而第4行就不是控制依赖于第2行,不论第2行结果如何都会执行第4行。如果不能计算控制的依赖,基于控制流污点分析就不能实现。但是因为控制依赖污点分析需要同时处理多条路径,所以单纯的动态污点分析是不能够完成多条路径同时分析,只能支持一次一条路径。所以有两类解决办法:1)用静态分析补充动态分析,静态分析可以计算控制依赖关系,因此可以用来计算控制依赖污染。静态分析可以应用于整个程序,或者动态污点分析的集合。2)使用启发式,根据场景做出特定于应用程序的选择是过污染还是污染不足。
    3.净化处理
    如上所述的动态污染分析只会增加污染;它永远不会删除它。这导致了污染传播的问题:随着程序的执行,越来越多的值被污染,通常污染的精度越来越低。污染分析中的一个重大挑战是确定什么时候可以从值中去除污染。我们称之为污染消毒问题。
    一个常见的例子是给计算常数的程序消毒:例如,b = a ⊕ a,因为b一直都等于0而不会依赖a的取值。x86程序经常用这种结构去给寄存器置零。所以,可以对这一类函数进行消毒(TEMU和TaintCheck就有针对常数函数的处理方法)。
    还有是依赖于应用程序的消毒:如果程序自己执行消毒,攻击探测器可能更希望找到污染清楚的值。例如,如果应用程序逻辑检查数组的索引是否在数组大小内,则可以认为表查找的结果是未受污染的。
    4.检测的时间 VS 攻击的时间
    动态污染分析用于在污染的变量以不安全的方式使用时的一个标记,但是不能保证程序的完整性在此前有没有被破坏。
    这个问题的一个例子是检测时间/攻击间隙时间,当污染分析用于攻击检测时发生。考虑一个典型的返回地址覆盖漏洞。在这类攻击中,用户可以利用攻击者提供的shellcode地址覆盖函数返回地址。受污染的跳转策略将捕捉此类攻击,因为在覆盖期间返回地址将被污染。受污染的跳转策略经常用于检测针对潜在未知漏洞的此类攻击。
    但是,当第一次覆盖返回地址时,受污染的跳转策略不会引发错误,只有当它以后被用作跳转目标时才会报错。因此,直到函数返回,漏洞才会被报告。从第一次覆盖返回地址到检测到攻击之间,可能会发生任意的影响,例如,脆弱函数发出的任何调用仍将在警报发出之前发出。如果这些调用有副作用,例如,包括文件操作或网络功能,即使程序被中止,这些影响也会持续存在。
    动态污点分析的关键问题是,仅靠动态污染分析跟踪的信息太少了。在返回覆盖攻击中,抽象机器将需要跟踪返回地址的位置,并验证它们没有被覆盖。在二进制代码设置中,这是困难的。
    检测时间/攻击间隔时间的另一个例子是检测整数溢出攻击。单独的污染分析并不检查溢出:它只是标记哪些值来自污染源。攻击检测器需要在污染分析之外添加额外的逻辑来发现此类问题。

    正向符号执行

    通过构建一个表示程序执行的逻辑公式,正向符号执行可以让我们推理出一个程序执行多个个不同输入时的行为,因此对程序行为的推理可以简化为逻辑执行。
    正向符号执行的优点之一是,它可以用于一次推断多个输入。例如,下面例子的程序,2^32个可能的输入中只有一个会导致程序获得真值的分支。向前符号执行可以通过考虑采用真分支和假分支的两个不同输入类来推断程序。

    x := 2*get_input(.)
    if x-5 == 14 then goto 3 else goto 4
    
    

    正向符号执行和常规执行的主要区别是,当get input(·)被符号化地计算时,它返回的是一个符号,而不是一个具体的值。当一个新的符号是第一个返回时,它的值是没有具体值来约束的,可以时任何可能的值。所以一个包含符号的表达式不能等于一个具体值。我们的语言必须是被修改,允许一个值是带有一些符号的表达式。所以会有一下表中的改变。

    正向符号执行的改变
    上图表示正向符号执行的改变
    分支将符号变量的值变为执行路径的集合,那么分支状态更新的规则如下图所示。例如,如果“if x > 2 then goto e1 else goto e2”这个语句选择真值分支,x一定包含一个比2大的值。如果选择了一个假值方向,x就包含一i个不大于2的值。所以在断言语句之后,符号的值就必须收到约束这样才能满足断言的表达式。我们用路径谓词π来表示运算语义中符号分配的这些约束。我们展示了下图中的语言结构如何对π进行更新。在每一个符号执行步骤中,π包含符号变量的约束正向符号执行语言的操作语义
    上图表示正向符号执行语言的操作语义
    第一个例子的符号执行如下表对于正向符号执行的仿真所示。在第1行,get input(·)计算为一个新的符号s,它最初表示任何可能的用户输入。s被翻倍,然后分配给x。这反映在更新后的Δ中。当正向符号执行到达一个分支时,如第2行所示,它必须选择要走的路径。路径选择策略对分析的结果有显著影响。正向符号执行语言的操作语义表显示了符号执行后的程序上下文采用这两条路径(通过使用S-TCOND和S-FCOND规则表示)。请注意,路径谓词π取决于通过程序走过的路径。
    正向符号执行的仿真
    上图表示正向符号执行的仿真
    正向符号执行的关键难点
    从概念上讲,创建正向符号执行引擎是一个非常简单的过程:获取语言的操作语义,并更改值的定义以包含符号表达式。然而,通过检查我们对这种直觉的形式定义,我们可以发现几个例子,我们的分析是失败的:
    1.符号内存当我们需要分析内存的上下文的时候该怎么用一个符号表示内存的索引值。
    2.系统调用我们的分析该如何处理外部调用,例如,系统调用。
    3.路径的选择每个条件表示程序执行空间中的一个分支。我们应该如何决定走哪个分支。

    找到以下的一些解决办法:

    • 符号内存地址
      加载和存储规则对表示内存地址的表达式求值,然后在内存上下文μ中获取或设置该地址的相应值。具体执行时,该值将是一个引用特定内存单元的整数。然而,当符号执行时,我们必须决定当内存引用是一个表达式而不是一个具体的数字时该怎么做。当加载或存储操作中引用的地址是由用户输入导出的表达式而不是具体值时,就会出现符号内存地址问题。当我们从一个符号表达式加载时,一个合理的策略是将其视为从表达式的任何可能的令人满意的赋值加载。类似地,对符号地址的存储可以覆盖对表达式的满意赋值的任何值。符号地址在实际的程序中很常见,例如,依赖于用户输入的表查找。即使沿着单个执行路径,符号内存地址也可能导致混叠问题。当两个内存操作引用相同的地址时,可能的地址别名发生。
    store(addr1, v)
    z = load(addr2)
    

    如果addr1 = addr2,则addr1和addr2是别名,加载的值为v。如果addr1 != addr2,则v不加载。在最坏的情况下,addr1和addr2的表达式有时有别名,有时没有。
    有几种处理符号引用的方法:

    • 一种方法是对从程序中删除符号地址做出不合理的假设。例如,Vine可以根据名称将所有内存地址重写为标量。这种不完整的假设需要依靠应用程序给定的范围来确定。
    • 让随后的分析步骤来处理它们。例如,许多应用程序域将生成的公式传递给SMT求解器。在这些范围中,我们可以让SMT求解器推理所有可能的别名关系。为了对符号地址进行逻辑编码,我们必须显式地命名每个内存更新。上面给定的例子可以编码为:mem1 = (mem0 with mem0[addr1] = v) ^ z = mem1[addr2];(意思是mem1是和mem0是一样的,除了在addr1这个地址上的值是v,后续的读操作在mem1上进行)
      SMT求解器( CVC Lite: A new implementation of the cooperating validity checker-2004; A decision procedure for
      bit-vectors and arrays.2007)
    • 执行别名分析。可以通过执行别名分析来判断两个引用是否指向同一个地址。然而,别名分析是静态或脱机分析。在许多应用领域,例如自动化测试用例生成、fuzzing和恶意软件分析的工作,正向符号执行的优点之一是它可以在运行时完成。在这样的场景中,添加静态分析组件可能没有吸引力。
      但是以前的大多数工作都没有专门解决符号地址的问题。KLEE及其前辈混合执行别名分析,并让SMT求解器担心别名问题。DART和CUTE只处理线性约束的公式,因此不能处理一般的符号引用。然而,当一个符号存储器访问是一个线性地址时,他们可以解决线性方程组,看看他们是否可能被别名。据我们所知,以前的恶意软件分析工作并没有解决这个问题。因此,恶意软件作者可以故意创建包含符号内存操作的恶意软件来绕过分析。
    • 路径选择
      当向前符号执行遇到一个分支时,它必须决定先遵循哪个分支。我们称之为路径选择问题。我们可以把整个程序的正向符号执行看作是一棵树,其中每个节点都表示抽象机器的一个特定实例。分析从树中的根节点开始。但是,每当分析必须fork时,比如遇到条件跳转时,它就将所有可能的fork状态添加到当前节点。我们可以进一步探索树中未终止的任何叶节点。因此,向前符号执行需要一种策略来选择下一步探索哪个状态。
      最简单的处理方式就是循环,循环可以产生无限深度的树。因此,循环的处理是路径选择策略中不可或缺的组成部分。在这个程序中探索所有的路径是不可行的。尽管我们知道从数学上讲,除了2之外,分支保护没有令人满意的答案,但正向符号执行算法却不是这样。例如,while(3n+ 4n == 5n ){n++;…},第一次循环的分支保护是3n+4n = 5n ,第二次是3n+1+4n+1 = 5n+1,以此类推。通常,正向符号执行将为循环迭代提供一个需要考虑的上限,以防止它“卡”在这种潜在的无限或长时间运行的循环中。
      1.深度优先搜索
      DFS在状态树上使用标准的深度优先搜索算法。DFS的主要缺点是,如果没有指定最大深度,它可能会陷入带有符号条件的非终止循环中。如果发生了这种情况,那么就不会探索其他分支,代码覆盖率也会很低。KLEE和EXE可以实现具有可配置的循环路径最大深度的DFS搜索,以防止无限循环
      2.导向性(concolic)测试
      导向性测试使用具体的执行来产生程序执行的跟踪。符号向前执行遵循与具体执行相同的路径。分析可以选择生成具体的输入,通过选择一个条件语句并否定与该条件语句对应的约束,强制执行到另一条路径。由于正向符号执行可能比具体执行慢很多,导向性测试的一种变体使用单个符号执行来生成许多具体的测试输入。这种搜索策略称为分代搜索。
      3.随机路径
      KLEE还实现了一种随机路径策略,其中正向符号执行引擎通过从根节点到叶节点的随机遍历状态树来选择状态。随机路径策略对浅状态赋予了更高的权重。这可以防止执行被困在带有符号条件的循环中。
      4.启发式
      附加的启发式方法可以帮助选择可能到达未发现代码的状态。启发式示例包括从当前执行点到未发现指令的距离,以及该状态在过去到达未发现代码的最近时间。
    • 符号跳转
      GOTO规则的前提要求地址表达式求值为一个具体值,类似于LOAD和STORE规则。但是,在向前符号执行期间,跳转目标可能是一个表达式,而不是具体的位置。我们称之为符号跳转问题。符号跳转的一个常见原因是跳转表,跳转表通常用于实现switch语句。正向符号执行中的大量工作并不能直接解决符号跳转问题。在某些领域,如自动化测试用例生成,将符号跳转留在实验的范围之外仅仅意味着较低的成功率。在其他领域,例如在恶意软件分析中,符号跳跃的广泛使用将对当前的自动恶意软件逆向工程构成挑战。
      处理符号跳转的三种标准方法是:
      **1. **使用具体和符号(concolic)分析运行程序,观察间接跳转目标。一旦在具体执行中获得跳转目标,我们就可以执行具体路径的符号执行。一个缺点是,探索程序的全状态空间变得更加困难,因为我们只探索已知的跳跃目标。因此,代码覆盖率会受到影响。
      **2. **使用SMT求解器。当我们搜索到一个符号跳转到e使用的路径谓词为π时,我们可以向SMT求解者请求满意的答案为π∧e。满意的答案包括对变量e的赋值,这是一个具体的跳跃目标。如果我们对更令人满意的答案感兴趣,我们可以在查询中添加返回的值与前面看到的值不同。例如,如果第一个满足的答案是n,我们求出π∧e∧¬n。尽管查询SMT求解器是一种完全有效的解决方案,但它的效率可能不如其他利用程序结构优势的选项,例如静态分析。
      **3.**使用静态分析。静态分析可以推断整个程序来定位可能的跳转目标。在实践中,源代码级间接跳转分析通常采用指针分析的形式。二进制级跳转静态分析确定跳转目标表达式中可能引用的值。例如,函数指针表通常被实现为一个包含可能跳转目标的表。
    bytes := get_input(.)
    p := load(functable + bytes)
    goto p
    

    由于functable是静态已知的,并且表的大小是固定的,静态分析可以确定目标的范围为load(functable+x),其中{x| 0≤x≤k}, k为表的大小。

    • 处理系统和库函数的调用
      在具体执行中,系统调用向程序引入输入值,我们引入的调用是作为系统级调用的输入源,例如,在C程序中,系统级调用可能对应于调用库函数,如read,在二进制程序中,系统级调用可能对应于发出中断。一些系统级调用引入了新的符号变量。然而,它们也有额外的副作用。例如,read返回新鲜的符号输入,并更新指向当前读文件位置的内部指针。对read的后续调用不应该返回相同的输入。处理系统级调用的一种方法是创建其副作用的摘要。摘要是描述具体调用各自代码时所发生的副作用的模型。摘要的优点是,它们只能抽象当前应用程序领域所需的那些细节。然而,它们通常需要手工生成。在使用concolic执行时,另一种不同的方法是在符号执行中使用从系统调用中返回的值。例如,如果在具体执行过程中sys_call()返回10,则在对应的sys_call()的正向符号执行过程中使用10。基于concolic的方法的主要优点是它简单、易于实现,并且回避了关于程序如何与其环境交互的推理问题。根据定义,任何使用具体值的分析都不会提供关于系统调用的完整分析。此外,分析可能不可靠,因为即使给定相同的输入,有些调用也不总是返回相同的结果。例如,gettimeofday为每次调用返回不同的时间。
    • 性能
      正向符号执行的直接实现将导致:A)程序分支数量的运行时间指数,b)公式的指数数量,以及c)每个分支的指数大小公式。运行时间与分支数成指数关系,因为在每个分支点都分叉出一个新的解释器。公式的指数数直接随之而来,因为在每个分支点都有一个单独的公式。
    展开全文
  • 关于自动缓冲区溢出漏洞检测技术学习(MAYHEM) 关于MAYHEM的总览 文章利用了HTTP服务orzHttpd 来展示遇到的主要问题和MAYHEM的工作流程。(利用MAYHEM找到的一个漏洞作为例子) #define BUFFSIZE 4096 typedef ...

    关于自动缓冲区溢出漏洞检测技术学习(MAYHEM)

    关于MAYHEM的总览

    文章利用了HTTP服务orzHttpd 来展示遇到的主要问题和MAYHEM的工作流程。(利用MAYHEM找到的一个漏洞作为例子)

    #define BUFFSIZE 4096
    
    typedef struct{
    	char buf[BUFSIZE];
    	int used;
    }STATIC_BUFFER_t;
    
    typedef struct conn{
    	STATIC_BUFFER_t read_buf;
    	...//omitted
    }CONN_t;
    
    static void serverlog(LOG_TYPE_t type, const char *format,....)
    {
    	...//omitted
    	if(format != NULL){
    		va_start(ap, format);
    		vsprintf(buf, format, ap);
    		va_end(ap);
    	}
    	fprintf(log, buf);//vulnerable point
    	fflush(log);
    }
    
    HTTP_STATE_t http_read_request(CONN_t *conn)
    {
    	...//omitted
    	while(conn->read_buf.used<BUFSIZE){
    		sz = static_buffer_read(conn, &conn->read_buf);
    		if(sz < 0){
    			..
    			conn->read_buf.used += sz;
    			if(memcmp(&conn->read_buf.buf[conn->read_buf.uesd] - 4, "\r\n\r\n", 4) == 0)
    			{
    				break;
    			}
    		}
    		if(conn->read_buf.used >= BUFSIZE){
    			conn->status.st = HTTP_STATUS_400;
    			return HTTP_STATE_ERROR;	
    		}
    		...
    	}
    	serverlog(ERROR_LOG,
    					"%s\n",
    					conn->read_buf.buf);
    }
    

    问题就出现在注释的位置调用serverlog 函数,可以在最后看到该函数调用了fprintf() 使用用户给的字符串格式,可变参数函数(如fprintf)使用自定义格式字符串说明符来确定如何遍历内存堆栈。这个漏洞使用fprintf 获取缓冲区的控制权,将shellcode或者其他格式写入所需的位置。
    有漏洞的程序堆栈
    由上面的例子推广开几个发现漏洞的关键点;

    1. 发现底层细节事件,发现漏洞需要底层(返回地址和栈指针)
    2. 需要找到大量的执行路径,因为代码中许多部分中的路径数量与输入的大小相关。例如:memcmp展开一个循环,在每次迭代中创建符号执行的新路径。更长的输入意味着更多的条件、更多的分支和更大的可扩展性,这样导致大多数利用都不是短字符串。
    3. 检查越多的路径越好,MAYHEM需要通过循环进行推理,读取输入,为每个可能的路径派生一个新的解释器(???interpreter),并检查错误。
    4. 更多的在本机执行(个人理解是:更多的指令执行来发现问题),符号执行因为指令的语义实在软件中模拟的所以运行的很慢,攻击者在连接到套接字之前需要百万条指令来设置基本服务器。

    总体设计图
    MAYHEM由两个并发的进程组成:一个再本机CPU上执行CEC;一个符号执行服务器SES。CEC运行在目标系统上,SES在任何平台上,等待CEC的连接。CEC接受一个二进制程序以及可能的符号源(输入规范)作为输入,并开始与SES通信。然后,SES符号执行CEC发送过来的BB和集中类型的测试用例,包括普通测试.

    1. 指定哪些输入源可能处于攻击者控制之下.
    2. CEC加载目标程序并且连接到SES初始化所有的符号输入源.初始化后,CEC在CPU上进行具体执行.在执行期间,CEC检测并且执行动态污点分析.
    3. 在CEC遇到受污染的分支约束或者跳转目标就挂起具体执行.有污染说明有可能是攻击者依赖的输入.CEC就会将所有受污染的BB送到SES,由SES进行判断哪个分支是可执行的.CEC会收到SES发来的下一个目标分支.
    4. SES和CEC是同时运行的,收到来自CEC发来的一堆收到污染的指令,SES把指令转换为一个中间语言,并且符号执行相应的IL.CEC会提供关于符号执行所需的具体值,比如指令的操作数.
      路径公式: 路径公式反映了到达特定代码行的约束条件.每一个跳转约束会增加一个新的约束在输入中.例如:例子中判断输入缓冲区大小是否超出范围的if会产生两条路径.一个是如果碰到\r\n\r\n结尾的输入所执行的;另一个是没有碰到\r\n\r\n的输入所执行的.
      **有漏洞的路径公式:**判断漏洞的检测方法:1)攻击者可以获取指令指针(??instruction pointer)2)可以执行payload
    5. 找到一个受污染的分支,SES决定是否需要用SMT解释器去分支执行。如果需要执行分支,所有新获取的分支都要送到路径选择器去优化。在选择路径时,SES会将更改的路径通知CEC,并恢复相应的执行状态。如果达到系统资源上限将会生成检查点,而不是派生新的执行器(4section)。在流程的最后将为已停止的执行器生成测试用例,而SES将通知CEC接下来应该执行哪个检查点。
    6. 在执行期间,SES在执行器和CEC形成检查点/恢复之间切换,为支持这样的功能CEC需要一个虚拟层来保证程序与计算机底层之间的交互,以及多程序执行状态之间的检查点恢复。(4section-C)
    7. 当检测到污染的跳转指令后,会建立一个可利用路径公式,利用SMT求解器来查找是否有满足的情况,如果发现了又满足要求的输入就是一个漏洞,如果受污染的分支指令上没有漏洞SES会继续探索执行路径。
      以上是对MAYHEM的最新的认识,之后会继续分析文章并配合自己的想法来找到新的思路
    展开全文
  • 本文首发于“合天智汇”公众号 作者:萌新0本文是本系列的第二篇,将对面向二进制程序的静态漏洞挖掘技术进行介绍与分析。面向二进制程序的静态漏洞的挖掘技术由于缺少源代码中的结构化信息,面临着值集分析(vaule-...
  • IDAPythonScripts: 二进制漏洞静态分析检测脚本(IDA Pro) QQ交流群:813115551 加微信-进入交流群:wwy18795980897 准备 首先下载IDA Pro软件,版本 <= 6.8,7.0以上部分脚本不支持。 安装IDAPython插件。 IDA...
  • 张小松【期刊名称】《计算机科学》【年(卷),期】2013(040)010【摘要】软件漏洞是安全问题的根源之一,fuzzing(模糊测试)是目前漏洞发现的关键技术,但是它通过随机改变输入无法有效地构造出测试用例,也无法消除测试...
  • 软件静态漏洞检测依据分析对象主要分为二进制漏洞检测和源代码漏洞检测。由于源代码含有更为丰富的语义信息而备受代码审查人员的青睐。针对现有的源代码漏洞检测研究工作,从基于代码相似性的漏洞检测、基于符号执行...
  • 针对加密软件中的密钥安全性问题,提出一种基于动态二进制插桩的密钥安全性检测方法。该方法面向CryptoAPI加密应用程序,首先通过对CryptoAPI密钥应用模式的分析,指出潜在的密钥安全性漏洞;然后以动态二进制分析...
  • 二进制漏洞挖掘技术实战

    万次阅读 2016-03-24 14:46:40
    0×00前言 ...关于二进制漏洞研究,大体可以分为漏洞分析利用和漏洞挖掘两部分。关于漏洞分析利用的部分互联网可以搜索到大量文章,而漏洞挖掘的文章却寥寥无几。因此我在这里主要来讲一下如何对
  • 今年的议题更多集中在二进制漏洞挖掘上,占比43%,而这些议题涉及(Windows、macOS、IoT、工控等等),其它议题方向包括恶意软件二进制分析工具、容器安全、漏洞奖励计划等等,可以看出当前工业界的一些研究议题...
  • 二进制文件相似度计算-(综述)涉及文件关联、函数关联、漏洞关联、漏洞发现等多方面的应用,在软件剽窃检测、代码抄袭、版本识别、补丁查找等有重要作用。
  • 目前大部分第三方代码包含大量的开源代码,并且主要是以二进制代码或是源代码的方式开源。 软件的安全性一直受到IoT、汽车、医疗等领域的高度关注,大量对企业有灾难性影响的代码漏洞,不断在一些知名的开源软件中被...
  • IDAPythonScriptsIDAPythonScripts: 二进制漏洞静态分析检测脚本(IDA Pro)准备首先下载IDA Pro软件,版本 <= 6.8,7.0以上部分脚本不支持。漏洞内容(待更新)危险函数调用此脚本对IDA反汇编文件进行静态分析,检测...
  • BinSearch是一款基于大数据与机器学习的二进制代码分析平台,具有自主知识产权。
  • IDAPythonScriptsIDAPythonScripts: 二进制漏洞静态分析检测脚本(IDA Pro)准备首先下载IDA Pro软件,版本 <= 6.8,7.0以上部分脚本不支持。漏洞内容(待更新)危险函数调用此脚本对IDA反汇编文件进行静态分析,检测...
  • 摘要:本文针对二进制SCA检测技术短板所面临的一些特殊场景、检测影响及应对措施进行详细分析和说明,希望对使用二进制SCA检测工具的测试和研发人员有所帮助。
  • 核心技术: 闭源二进制软件的开源组件复用检测 对于源代码与二进制代码间的复用检测受到复杂的复用关系影响,即检测复用时对简单的复用可能有用,如zlib.dll与zlib库,而对多层调用就失去了效果。 主要用到的方法...
  • 摘要:二进制分析技术通常被用来对应用进行安全审计、漏洞检测等,通过分析学术界近20年发表的上百篇学术论文来分析二进制代码相似度比较都有采用了哪些具体技术,二进制代码相似度比较的技术挑战是什么,后续的研究...
  • 在静态源代码检测工具方面,国内很多公司在研发产品,包括北大软件CoBOT、奇虎测腾的代码卫士、360企业代码卫士、清华大学软件学院Tsmart代码分析工具集、腾讯TscanCode开源静态扫描工具,端玛企业级静态源代码扫描...
  • 列表不定期更新,有遗漏的地方还望各位留帖补充:Plast update: 2019.04.05 从漏洞漏洞利用、Fuzz、利用缓解四...『二进制漏洞分析』学习资源整理https://bbs.pediy.com/thread-221851.htm 基础知识: Win...
  • 摘要 低功耗、单一用途的嵌入式设备(例如路由器...这种多二进制服务实现使当前的静态和动态分析技术无效或低效,因为它们无法识别各种可执行文件之间的通信并对其进行充分建模。在本文中,我们介绍了 KARONTE,这是一
  • 本文从检测程序的漏洞方面着手,比较了以前常用的静态代码分析和实时错误注入的检测方法,提出了一种对可执行文件反汇编后的代码进行缓冲区溢出漏洞检测的技术, 提高了检测软件系统漏洞的效率。
  • 二进制安全

    2021-01-16 10:58:26
    刚开始学二进制,虽然高中时候知道二进制是个啥,什么逢二进一也懂,但是完全不知道二进制跟电脑有啥关系,更别说那些专业名词了,这两天看到一篇大佬的文章,怎么说呢,写的不错,对小白非常友好,大佬的链接放下边...
  • 软件漏洞分析

    2021-01-01 20:39:30
    软件漏洞分析的定义 广义漏洞分析:指的是围绕漏洞所进行的所有工作,包括: 漏洞挖掘:使用程序分析或软件测试技术发现软件中可能存在的未知的安全漏洞 漏洞检测:又称漏洞扫描,基于漏洞特征库,通过扫描等手段...
  • 发现已经有人使用NLP来对二进制代码进行分析,主要有3种方向上使用NLP分析二进制代码,但大多数都是对二进制代码进行静态分析,以下就这三种分析方向进行介绍。 Code Similarity Detection 至今,已经有两篇文章使用...
  • 软件漏洞检测技术概述

    千次阅读 2020-05-02 23:06:55
    首席安全官Plus是一个围绕“大数据、云计算和人工智能”高技术领域,发布相关网络安全前沿技术和产业趋势的平台,努力打造“有特色、高...软件的质量是软件产品的生命线,其质量问题的根源在于软件设计的不合理以及...
  • 二进制安全学习路线

    万次阅读 多人点赞 2019-08-14 23:35:17
    本文作者:rkvir(二进制小组组长) 转自某推文,链接找不到了。...提起逆向工程也许还有人可以联想到软件破解,如果提起的是二进制安全,那么知道的人就真的是寥寥无几了。实际上二进制安全技术在20世纪...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,171
精华内容 5,668
关键字:

二进制软件漏洞检测