用于动态函数调用系统中的积极自我修改的系统和方法

文档序号:6596678阅读:138来源:国知局
专利名称:用于动态函数调用系统中的积极自我修改的系统和方法
技术领域
本发明通常涉及计算机安全领域。更具体地,本发明涉及用于函数调用系统的控制流混淆的方法和系统。
背景技术
混淆是通过使逆向工程、对软件代码的复制或篡改(此后称篡改)复杂化来防止或延迟软件篡改的变换。在许多示例中,延迟对软件代码的篡改是足够的,特别当该软件是对常常仅花几秒就能完成的财务交易进行保护的应用时。在版权材料的示例中,通过使篡改过程足够长以使篡改过程与一份真实软件的成本相比变得过于昂贵,混淆成功。软件篡改包括两种主要攻击类型静态攻击和动态攻击。静态攻击涉及在不运行软件的情况下对其进行静态分析,例如,使用部分求值器。动态攻击涉及当代码在存储器中执行时监视并窃取(lift)代码以捕获所窃取的部分并重新构造该代码。在动态攻击中,函数调用、调用位置、以及进入和退出点是攻击者的战略目标,用于分析程序的控制流并获取其调用图。现有的控制流混淆方法主要应用于包括分支和跳转的局部控制流。这限制了函数范围。入侵的更大威胁在于攻击者发现调用结构以使代码能被窃取或重新实施的能力。传统的调用惯例很容易理解,从而使函数调用边界称为容易攻击的点。现有的自我修改代码技术主要应用于执行数据操作的直线指令块。虽然这可能有助于隐藏操作,但其很难隐瞒应用程序的宏观控制层面。在诸如C++的高级抽象语言的更广泛使用下,应用程序与其更低等级语言的等同物相比通常具有更多函数和更深的调用树。这意味着应用程序的函数边界现在面临更大的风险。例如,Eker等人的第2008/074483A1号PCT申请公布描述了对计算机程序的混淆,但未解决代码窃取攻击、以及动态和分步攻击(例如,使用调试器),该申请的全部内容通过引用并入本文。Eker等人公开了一种方法,该方法通过改变计算地址的方式来修改函数调用系统。修改的函数调用由代数表达式在运行时间计算。该结果是具有在运行时间确定的函数地址的指针调用函数调用。该方法不具有保护调用图免受代码窃取攻击的能力。例如,函数定义主体从不被修改。其可以被轻易地静态窃取并在其它程序中作为漏洞使用。此外,在使用调试器或监视程序的动态攻击中,可通过逐步的方式遵循函数调用顺序以找出用于代码窃取和/或篡改的感兴趣的被调用函数。此外,Eker等人描述了用指针调取代静态调用位置。然而,它们依然是调用位置。任何调用位置都能够通过其唯一的指令特征识别为对攻击者有用的断点。如果攻击者准备在所有调用位置上断开,然后运行程序,它们能够通过动态手段获取调用图信息。于2007年出版的Matias Madou 的题为“Application Security through ProgramObfuscation (依靠程序混淆的应用安全)”的出版物在其第五章中描述了一种踪迹混淆(trace obfuscation)的方法,该方法通过改变数据操作使出现在指令层面的多种技术组合,该出版物的全部内容通过引用并入本文。这些技术包括插入多样化代码、代码分解、插入混淆判断。插入多样化代码被用作基于朝着驻留有指令的基本块的路径用多个等同指令中的一个改写指令。代码分解是将仅有一个指令不同的两个条件代码块合并的技术。在导致合并的代码块的条件路径中,单个指令被改写以刚好在其被执行之前提供正确的行为。第三种技术包括构造混淆判断 并尽力将这些判断插入代码以创建多样性。判断具有有时评价为假并有时评价为真的条件。判断的继承者具有等同但多样的代码。Madou将上述用于执行程序的踪迹混淆的所有三种技术组合。然而,Madou所提出的多样性技术仅限于数据指令的修改。混淆判断的插入仅涉及具有预定行为的分支的插入。此外,对于Madou的系统,函数被调用和执行的顺序、次序、时间、以及方式依然相同。因此,对由Madou的方法所保护的软件的动态攻击依然能够成功。此外,Madou的方法不保护程序免受静态攻击。孤立的函数依然被全部窃取,并且在被窃取之后继续以它们原始的方式表现。因此,期望提供一种使控制流混淆以防静态和动态攻击的方法和系统,其对程序的调用图执行全面变换。

发明内容
本发明的目的是提供一种涉及程序的全面变换以防止程序受到静态和动态攻击的保护方法。根据本发明的实施方式,该方法包括复杂的预分析步骤以理解原始程序的函数调用结构、整个函数调用图、以及函数调用布局这三个程序特征,以对程序进行变换。在一个实施方式中,程序的变换可包括在构建时间对函数相关的指令的动态插入、替换、以及修改进行编排,使得变换程序的静态分析(静态攻击)不指示合适的函数调用布局,从而当程序在存储器中执行时不指示程序的行为。在构建时间计划的动态改变在运行时间执行,从而当变换程序在存储器中运行时,对变换程序的执行进行监视的动态攻击无法成功地确定合适的函数调用图或函数调用布局。在一个方面,本发明提供一种通过改变软件程序的控制流结构将程序从原始形态变换为更加安全的形态以防止程序受到静态和动态攻击的方法。该方法包括分析程序的原始函数调用结构和函数调用布局;将原始函数调用布局变换为新函数调用布局;将原始函数调用结构变换为能够进行动态自我修改的新函数调用结构;产生具有变换的控制流结构但在语义上等同于原始程序的变换程序;以及在程序执行时将原始函数调用图变换为新的函数调用图。在本文中,术语“语义上等同”应被解释为“产生相同的结果或输出”。在一个实施方式中,动态自我修改改变函数被调用的时间和方式。分析和变换原始程序并产生变换程序的步骤可在构建时间执行,将原始调用图变换为新图的步骤在运行时间执行。改变原始布局和结构或程序可涉及改变函数边界以掩饰函数调用布局。在一个实施方式中,改变函数边界可包括打破函数边界并将至少两个函数连接成一个函数。在另一个实施方式中,改变函数边界包括插入新的函数边界以将函数分成至少两个函数。该方法还可包括对程 序进行破坏,包括至少一个损坏性破坏紧跟着至少一个修复性破坏,以进一步掩饰函数调用结构并维持与原始程序的函数等效性。在一个实施方式中,对原始程序的分析包括在程序中确定战略点以修改程序和/或执行复杂的预分析步骤以理解程序的函数调用结构、函数调用布局、以及整个函数调用图。修改点可放置在与相应执行点物理地且短暂地远离的点处。在一个实施方式中,为单个执行点提供多个修改点。在另一个方面,本发明提供了一种通过改变软件程序的控制流结构将程序从原始形态变换为更加安全的形态以防止程序受到静态和动态攻击的方法。该方法包括构建时间阶段和运行时间阶段。构建时间阶段包括下列步骤分析程序的原始的函数调用结构和函数调用布局;将程序的原始函数调用布局变换为新的函数调用布局;将函数调用结构变换为能够进行动态修改的新函数调用结构;以及产生具有变换的控制流结构但在语义上等同于原始程序的变换程序。运行时间阶段包括在程序执行时将程序的原始函数调用图变换为新的函数调用图,其中在运行时间执行的动态修改是对在构建时间执行的改变的补充,以产生在语义上等同于原始程序的变换程序。在又一个实施方式中,本发明提供了一种计算机可读储存器,其上记录有用于通过改变软件程序的控制流结构将程序从原始形态变换为更加安全的形态以防止程序受到静态和动态攻击的语句(statement)和指令,所述语句和指令在由处理器执行时使处理器执行以下步骤分析程序的原始函数调用结构和函数调用布局;将原始函数调用布局变换为新函数调用布局;将原始函数调用结构变换为能够进行动态自我修改的新函数调用结构;产生具有变换的控制流结构但在语义上等同于原始程序的变换程序;以及在程序执行时将原始函数调用图变换为新函数调用图。对本领域技术人员来说,当结合附图阅读了以下对本发明的具体实施方式
的描述,本发明的其它方面和特征将变得显而易见。


现在将参照附图仅通过实施例描述本发明的实施方式,在附图中图I示出原始形态的程序的传统函数布局、调用图、以及函数调用顺序;图2示出根据本发明的实施方式的图I所示程序的变换版本;图3a示出图2的变换程序的运行时间过程和动态修改;图3b示出根据本发明的实施方式的如何针对已经执行的指令对程序进行破坏的示例;图4是图I所示的原始程序的调用顺序相对于图2、3a和3b所示的变换程序的动态调用顺序的流程图;图5a至5c示出根据本发明的实施方式的当对除主入口函数之外不具有其它函数的程序实施动态调用系统时的运行时间过程;图6示出根据本发明的实施方式的使程序变换的步骤的流程图7示出用于构建用于在传统系统上执行的应用程序的一组传统工具;图8示出根据本发明的实施方式的动态函数调用系统中所使用的构建工具的示例;图9不出根据本发明的实施方式的用于使原始程序变换为面对静态和动态攻击安全的被保护程序的系统的示例性实施方式;以及图IOa至IOc示出用于动态函数调用系统的可选操作设置。
具体实施例方式本发明的实施方式提供用于软件混淆的 系统和方法,软件混淆用于将程序从第一形态变换为抵御静态和动态攻击的更加安全的形态。在一个实施方式中,该方法利用复杂的预分析步骤来理解程序的函数调用结构、函数调用布局、以及整个函数调用图,以在程序中确定用于改变程序的战略点。该方法通过将原始函数调用布局变换为新的布局来抵御静态攻击。在一个实施方式中,改变布局可包括改变函数边界。该方法通过将原始函数调用结构变换为新的结构以使变换的程序在存储器中执行时能够自我修改来抵御静态攻击。在一个实施方式中,改变函数调用结构可包括修改函数被调用的时间和方式、和/或选择导致相同结果的随机执行路径。变换的程序在语义上等同于原始程序但更好地抵御静态和动态攻击。在下面的描述中,术语函数调用图、函数调用结构、函数调用布局、以及控制流结构应被解释为如下含义-函数调用图是函数辨识的关系、以及当程序在存储器中运行时函数被调用以供执行的方式、次序、时间、和持续时间。函数调用图通常被黑客监视以进行动态攻击。-函数调用结构是确定程序在执行期间的行为的结构。函数调用结构包括组成函数结构的程序代码、边界、输入/输出惯例(convention)、以及调用惯例以及函数被调用和执行的方式和时间。-函数调用布局是当程序被储存且未运行时函数调用结构的外表特征(从静态点的角度观察),即函数数量、次序、边界等。攻击者调查函数调用布局以进行静态攻击,诸如代码窃取和篡改。-控制流结构是允许对贯穿程序的控制进行改变的一组操作。在局部层面,控制流结构包括分支和跳转。在程序层面,控制流结构包括函数调用结构、函数效用布局、跳转、以及分支、返回、线程处理和异常处理。根据本发明的一个实施方式,程序的变换包括两个阶段-构建时间程序在执行之前被静态分析和改变的时间。该阶段包括分析程序以确定战略点、以及通过插入诱饵、创建新函数,插入函数调用、改变函数边界等来变换程序并改变函数调用结构。-运行时间变换的程序在存储器中运行的时间。新的函数调用结构自我修改并改变函数调用图。当程序执行时,通过修改函数被调用的时间和方式来修改整个函数调用图。根据本发明的一个实施方式,该方法包括复杂的预分析步骤以理解原始程序的函数调用结构、整个函数调用图、以及函数调用布局这三个程序特征。在一个实施方式中,与如上面讨论的 Matias Madou 的 “Application Security through Program Obfuscation(依靠程序混淆的应用安全)”中的仅改变分支层面上的数据指令相反,该方法考虑整个程序层面上的控制流。当程序是原始且未被混淆或隐藏时,预分析步骤可为相应的函数调用图和函数边界检测合适的函数调用 结构。因此,当程序处于其原始形态时,这三个程序特征彼此匹配。根据本发明的一个实施方式,程序的变换包括在构建时间对与函数相关的指令的动态插入、替换以及修改进行编排。因此,程序在构建时间变换之后,变换的程序中的三个程序特征中的任何一个都不与其他特征匹配。变换的程序具有新的函数调用结构和新的函数调用布局。换言之,程序的合适的函数调用结构不再能够通过执行静态或动态攻击而被确定。具体地,变换的程序的静态分析(静态攻击)不指示合适的函数调用布局,从而当程序在存储器中执行时不指示该程序的行为。随后,静态攻击无法指示变换程序的合适的函数调用结构。另一方面,监视变换的程序在存储器中的执行的动态攻击无法从被监视的函数调用图成功确定变换程序的合适的函数调用结构或函数调用布局,因为变换的程序当其在存储器中运行时进行自我修改。这些修改可包括以不同次序、不同时间执行函数、以及选择导致相同结果的随机的执行路径。因此,变换的程序在面对静态和动态攻击时更加安全,并且合适的函数调用结构得到了更好地保护。在优选实施方式中,变换的控制流结构包括新的函数调用布局、和新的函数调用结构。在另一个优选实施方式中,变换的函数调用结构可包括下列中的一个或多个跳转和分支、异常处理、以及返回。当变换程序在存储器中运行时,在程序层面,监视程序执行的攻击者不但无法检测到合适的函数调用图,也无法确定原始程序的合适的函数调用布局或结构。因此,攻击者将被限制为仅在非常局部的层面上(即,在代码的当前执行点处)监视程序的执行。然而,在程序层面上,攻击者即使通过收集与程序代码的所有执行点有关的信息也无法重新构造程序,这是因为,变换程序的控制流和函数调用图不同于原始程序的控制流和函数调用图。当变换程序在存储器中运行时,原始应用的函数调用、返回语句(statement)、函数入口点、以及函数布局边界动态地改变来隐藏程序编写者想要的原始函数调用系统以免受到静态和/或动态攻击。因此,降低了通过静态分析或动态分析对程序进行篡改的容易性。函数调用布局可通过打破或改变函数之间的边界而变换为新的函数调用布局。因此,攻击者不但无法在运行时间使用动态攻击来确定函数的入口和出口,也无法在程序被储存时使用静态攻击来确定变换程序的函数调用结构或函数调用布局,这是因为,程序的函数调用布局被掩饰了。对函数体的这些修改降低了攻击者对完整的未破坏的函数体进行窃取的风险。还可以对函数体内的调用位置进行修改,包括移除或插入。可创建新函数并使用新的调用位置对其进行调用。调用位置不是静态明显的。它们可以在运行时间动态地插入。此外,调用位置被插入程序的时刻与该调用被执行的时间无关。例如,在运行时间,程序可在执行任何调用之前在程序内插入或移除多于100个的不同调用位置。在一个实施方式中,能够改变调用位置被插入和移除的时间和方式以及函数被调用的时间。比如,能够延迟对函数的调用、通过其它代码替换调用位置、在别的函数之前调用函数、掩饰哪些调用已经被执行或将要被执行的证据、改变它们的执行次序、或这些技术的任意组合。传统函数调用返回ABI (应用二进制接口)变换为新ABI,新ABI可当应用在存储器中运行时(运行时间过程)被修改。此外,在构建时间(当安全组件和反篡改技术被应用于待保护应用时)构造函数复本,从而在运行时间可能存在多个代码路径。在构建时间,程序被设置以使函数调用惯例的边界可被动态修改。这些函数边界包括调用位置、返回点、入口指令、函数的开始和结束、等等。在本发明的一个实施方式中,在确保与原始函数的语义等同的情况下,非决定论(non-determinism)被用来随机选择调用图上的执行路径。非决定论是对导致 有效结果的多个路径中的一个进行随机选择的算法。在一个实施方式中,变换的程序被设定为具有不同的函数调用图,无论其是否被执行。因此,对变换程序在存储器中的执行进行监视的攻击者在不同的执行时间将获得不同结果。然而,在任何时间所获得的结果都不会将攻击者引导至原始程序的正确的函数调用结构或布局。随着变换程序的执行的进行,指令被动态地修改,使得调用位置和函数边界在执行之前和之后被改变。在本发明的一个实施方式中,指令被修改(插入、删除或改变)的程序点出现在被修改的指令执行之前或之后的合适的点处。对于出现在被修改的指令执行之前的修改点,无所谓修改发生的多早或多晚,只要修改发生在指令执行之前就行。在本发明的另一个实施方式中,修改点通过至少一个指令与相应的指令分离,以防止攻击者识别指令如何被修改以及确定该修改和被修改指令的执行之间的关系。因此,优选的是将修改点放置于在物理上远离相应执行点的点处,例如,使它们之间具有其它执行点、或其它代码。在一个实施方式中,可通过将修改点放置于分析器/编译器知道将在相应执行点之前执行的函数中来完成修改点与相应执行点的分离。该分析被称为支配者分析。修改点不需要与执行点一一对应。它们可以是多对一或一对多。比如,在到达某一执行点之前,具有待遵循的多个修改点是可能的。该方法通过针对基于静态的侵入(例如,反汇编、反编译器)隐藏函数布局和调用顺序、针对基于动态的侵入(例如,调试器、仿真器)隐藏函数布局和调用顺序、以及使代码窃取和篡改攻击变得更加困难来抵御未授权使用的攻击。该结果是具有新的控制流结构的变换程序,新的控制流结构包括新的函数调用布局和新的函数调用结构。虽然变换的程序在语义上等同于原始程序,然而同时,变换的程序在面对篡改、代码窃取、以及静态和动态攻击时具有更大的抵御能力。图I是程序或应用在其原始、未调整形态下的传统函数布局、调用图、以及函数调用顺序的示例。各函数以简单、传统的顺序被调用、执行、和返回。如图I所示,原始调用顺序如下系统调用主函数(Main),主函数通过调用函数I (Function_l)开始执行,函数I调用函数2 (Function_2),函数2返回函数I,随后函数I调用函数4 (Function_4),函数4返回函数1,随后函数I返回主函数,并且主函数返回系统。图2示出根据本发明的示例性实施方式的图I所示的程序的变换版本。所示程序是在构建时间之后变换的“预加载的”程序。图2中所举例说明的变换程序看来具有某种函数调用顺序,但因为代码在运行时间被动态修改,故实际上将执行替代的函数调用顺序。在构建时间,许多代码操作准备步骤生效,包括通过在运行时间简化代码修改的新ABI替换传统函数调用惯例;修改函数边界以掩饰布局;通过诱饵调用、诱饵指令等修改调用位置点;用调用位置替换直线指令;插入重复的函数;以及插入附加的函数。如图2所示,创建并插入新的调用函数5,并且移除先前的调用函数2(图I所示)。已经通过用函数3 (Function_3)的调用位置替换调用函数4、通过将原始的函数I分为被修改的函数I和新的函数3、以及通过将函数4的调用位置插入函数3中来改变函数I的边界。上述措施在构建时间完成并用于将攻击者的注意力从真实函数调用布局和调用结构转移开。图3a示出图2的变换程序的运行时 间过程和动态修改的示例。当变换程序执行时,修改点改变函数调用特征。修改点修复(fix-up)代码部分以确保程序的正确执行,并破坏代码部分以相对于攻击者隐藏信息。通过使这些补充的改变在构建时间与运行时间之间生效,可以获得在语义上与原始程序相同但具有转移攻击者注意力的不同函数调用特征的变换程序。在图3的示例中,主函数开始执行,随后是函数1,函数I进而调用函数5(Function_5)。函数5未出现于原始程序中,而是当在构建时间对程序进行分析时通过编译器插入。函数5通过插入在构建时间从图I所示的原始程序移除(如图2所示)的函数2的调用位置来对函数I进行修复。当控制返回函数I时,其调用函数2,函数2通过将下一个调用位置从对函数3的调用修改为对函数4的调用以对函数I进行修复。当函数4被调用时,其通过将返回(Return)替换为空操作(NOP)并通过将调用函数4替换为NOP来消除函数I和函数3之间的边界,从而使函数I再次成为一个大函数,如图I中所示的原始程序。控制返回函数I并返回主函数。类似的方法将允许破坏动态地出现,以编排出在面对静态和动态攻击时更加安全的控制系统。对程序的破坏是对程序进行的使程序损坏(corrupt)并使其不正确地运行的修改。图2和3a中所举例说明的动态改变与破坏之间的差别在于,通过动态改变,变换程序在执行期间的任意时间都是静态地完全正确的,但以非预期的方式执行。相比之下,如图3b所示包括损坏性破坏的被保护程序在损坏性破坏之后将不正确地运行(例如,不是按照程序的作者所打算的那样运行),直至在执行期间的稍后时间出现修复性修改以对损坏性破坏进行修复。 修复性修改会将变换程序从相应的损坏性破坏修正,以确保与原始程序的语义等同。类似于图2和3a所举例说明的修改,破坏也在构建时间被计划并在运行时间被执行。在本发明的一个实施方式中,对于单个损坏性破坏,能够具有多于一个的修复性修改。破坏和它们相应的修复性修改用于多个目的,包括但不限于I.隐藏已经被执行的指令。2.准备用于后续执行的指令的状态。3.准备用于进一步破坏和/或修改的程序。图3b示出如何破坏已经被执行的指令的程序的示例。假设当分析系统已经计划时程序已经执行了部分代码,则可出现用于使该程序的真实调用结构混淆的破坏。参照图3b,考虑点300,在点300处,函数I已经开始执行,函数2已经完成执行并且函数4已经开始执行。函数4进行两个破坏
I.函数4中的指令(或指令组)移除对已出现函数(例如调用函数2)的调用。2.函数4还插入对原始程序中未出现的函数6 (Function 6)的调用。第一破坏移除函数4被调用的证据,并且第二破坏插入对函数6的调用,其导致进
一步破坏。当对函数6的调用到达时,函数6进行四个修复性修改
I.函数6插入对原始程序中未出现的函数5的调用(记得函数5在第一步骤中被用于自我修改)。这是用于后续调用的程序状态的准备。2.函数6将对函数4的调用修改为对函数3的调用。3.函数6移除对自身的调用,因为该调用已经被执行。4.函数6通过在函数I中插入返回语句来插入函数3的边界并插入对函数4的调用,从而有效地创建函数I的布局的结束和函数3的布局的开始。在所有破坏和它们的相应修复性修改已经出现之后,变换程序中的执行结果与如图2所示的在构建时间预计划的修改相协调。换言之,在所有破坏和修复性修改出现之后,保持与原始程序的语义等同。图3b仅示出如何能够对程序的调用结构进行破坏和修复性修改以使其与在构建时间进行的预修改相协调的一个示例。实施动态改变和/或破坏的代码被插入变换程序。该代码或者可采用函数的形式,或者可根据情况作为代码片段插入到程序中。该代码本身使用白盒密码术、数据变换、完整性验证或类似技术进行保护。在本发明中,可使用共同拥有的第7,397,916号美国专利和第11/020,313号和第61/175,945号美国专利申请来保护本发明的程序中的代码,这三个专利文献的全部内容通过弓I用并入本文。图4是示出图I所示的函数的原始调用顺序与图2和3a所示的变换程序的动态调用顺序相比较的流程图。如图4所示,在主函数调用函数I之后,当变换程序在存储器中执行时,变换程序的行为动态地改变。比如,在动态调用顺序中,在函数I之后函数2之前调用函数5,而在原始调用顺序中,函数5不存在。如上所述,函数5在构建时间被插入。此外,函数2通过用调用函数3替换调用函数4来修改函数I。函数3是如图I和2所示的原始函数I的分部。为了使函数I具有其在图I中的原始大小,函数4在运行时间移除函数I与函数3之间的边界,从而修复了在构建时间生效的改变。在图4的图解中所示的示例性实施方式中,函数在不同时间以不同方式被修改、调用,函数边界被改变,并且新的函数被引入和移除。对被保护程序的执行进行监视的攻击者将获得-欺骗性函数和欺骗性函数调用布局,因为函数边界被改变(例如通过改变函数的入口和出口),某些函数可被复制,并且某些不包含在原始程序中的函数可由系统创建;-欺骗性的各函数执行时间,因为函数可被延迟或提前调用;-欺骗性的执行次序,因为与原始程序相比,某些函数可能在其它函数之前被执行;-欺骗性的函数调用图,因为函数可被打破和/或联合,并且可例如使用非决定论选择随机的执行路径,这与原始程序保持功能等同但在存储器中执行时却看上去不同。图5a示出在对除如图5a所示的主函数入口函数之外不具有其它函数的程序实施动态调用系统时的运行时间过程。程序被分析以确定战略点以将程序变换为在运行时动态改变的程序。当主函数运行时,通过如图5a所指示,在主函数内制造函数A (Function_A)的边界以及入口、出口和调用位置来改 变主函数的边界。在函数A执行之后,函数A的边界、调用位置、以及入口和出口随后被移除,如图5b所示。一旦已经在执行后移除函数A的边界、调用位置和入口和出口,则主函数将看上去有如其从未变换过,如图5c所示。然而,从攻击者的立场来看,篡改并没有成功,因为向攻击者提供了欺骗性的调用图信息。另一个极端情况是,设定程序以使其静态地具有过多数量的函数。在运行时间,当提供在语义上等同于原始程序的变换程序时,函数边界被组合成更大的函数。图6是示出根据本发明的实施方式的对程序进行变换的步骤的流程图。如图6所示,在步骤600中,对待保护的原始程序进行分析以理解函数调用结构和函数调用布局。在步骤602中,将原始的函数调用布局变换为新的布局,使得变换的程序如果在储存于存储器中时被攻击者静态地分析,则看上去会有所不同。在步骤604中,将函数调用结构变换为新的函数调用结构,新的函数调用结构能够在变换的程序执行时进行动态自我修改。在步骤606中,由于在步骤604和606中预计划的改变,而当程序在存储器中执行期间将原始函数调用图变换为新的图。程序被变换以使函数边界诸如调用位置、返回点、进入指令、函数的开始和结束等可被动态地修改以产生更大或更小的函数。函数边界内的调用位置也可以被修改,包括移除或插入。函数边界在执行之前或之后被改变以抵御静态和动态的攻击。函数复本、诱饵、以及附加指令被插入以使静态和动态的攻击更加困难。在步骤608中,生成在语义上等同于原始程序的变换程序。当进行静态地分析时,被保护程序不同于原始程序,并且当在存储器中执行时被保护程序能够自我修改以抵御动态的攻击和代码窃取。在一个实施方式中,在对程序变换之前分析原始程序以确定每个函数的重要性等级,从而重视对安全性目标或性能目标而言重要的函数。对于安全性目标,函数可通过用户被识别为重要,因为其可能包含安全资产或计算安全系统的关键部分(如同信任密钥的根)。这可以通过语言扩展或通过外部装置(如命令行接口)来完成以指示该函数从安全性方面来说是重要的。如果情况是这样,则变换系统可强调对这个具体函数进行混淆的努力。对于性能目标,编译器通过静态分析(profiling)或实际分析装置可识别频繁执行的函数。在某些性能考量为重要的实施方式中,对于频繁执行的函数,将为那个函数选择已知的快速执行的变换。图7不出用于构建用于在本机(native)系统上执行的应用程序的一组传统工具。用于这种情况下的主要工具是编译器和链接器,传统上,它们是两个单独的工具,但是在某些情况下,它们可合并成一个工具。在其它情况下,它们还可以分离为多于两个工具。编译器的主要功能是执行应用程序文件的句法和语义分析、执行优化、以及为链接器生成代码。链接器将程序和数据段重新安置到布局中,该布局在组合时形成执行所需的二进制文件或二进制文件组。执行可以是本机的或在虚拟机上虚拟化的。图8示出根据本发明的一个实施方式的用于动态函数调用系统的构建工具的示例。相对于图7所示的传统工具,图8示出两个新工具编译器层面分析工具和链接层面分析工具。编译器层面分析工具与传统的编译器层面处理相关,并且或者能够在本机编译器之前或之后独立运行,或者作为传统编译器的替代。其还能够在本机链接器之前或之后独立运行,或者作为本机链接器的替代。如图8所示,编译器层面分析工具在本机编译器之前运行。类似地,链接层面分析器可与链接层面处理相关。其也可以在本机链接器之前或之后独立运行,或者作为本机链接器的替代。在编译器层面上,应用程序的完整函数调用图可被分析并且表达成“可能调用”和“必须调用”的表达。随后可对这些调用表达进行全局地分析以用于分配指令的插入、移除、以及修改。在编译器层面对原始程序进行战略地修改以用于动态修改。
函数边界可被分析并且信息可被准备以用于链接层面上的消耗。在链接层面,根据从编译器层面传递来的布局信息放置程序段,包括哪些函数需要与彼此相邻以及按照什么次序。这允许函数边界的动态修改。此外,任何附加的静态库和/或目标代码被链接至程序以进行诸如指令修改的辅助操作。在链接层面,动态修改系统所需的组件被设置为可执行的二进制或二进制组。图9示出系统900的示例性实施方式,系统900用于通过改变程序的函数调用布局将程序从原始形态变换为在面对静态和动态攻击时更加安全的形态,并用于将程序的函数调用结构变换为新的结构,新的结构能够当程序运行时动态地自我修改,以向对存储器中的变换程序的执行进行监视的攻击者提供欺骗性函数调用图。在图9所示的实施方式中,系统900包括至少两个计算机902和904。计算机902包括CPU 906、存储器908、图8所示的一组构建工具910、以及输入输出模块(1/0)912。计算机904包括CPU 914、存储器916、以及I/O 918。计算机902接收待变换的原始程序并进行构建时间过程以改变该程序的函数调用布局和函数调用结构。随后将变换的程序转移至计算机904以供储存和/或执行。可通过通信链路或者通过计算机可读储存器(诸如CD、DVD、USB驱动器或任何其它装置)将变换的程序转移至计算机904。变换的程序虽然在语义上等同于原始程序,但在面对静态和动态攻击时更加安全。当变换的程序被储存在计算机904中时,其抵御静态攻击,因为函数调用布局不反映原始函数的真实布局。因此,试图对变换程序的函数调用布局进行分析的攻击者将获得欺骗性布局,因为编译器/链接器改变了被保护程序中函数的函数边界、调用位置和执行次序。当变换的程序被计算机904执行时,函数调用结构在变换的程序执行时进行自我修改,从而通过改变函数被调用的方式和时间来改变原始的函数调用图。在一个实施方式中,执行函数边界修改的代码不需要与程序处于相同的执行线程中。可选地,其可以位于并发线程或中或者可位于在程序代码与操作系统(即,OS)之间运行的虚拟机层。因此,修改代码独立于程序,并且能够与程序函数性交织地或不相交地运行。可替换地,可以采用交织的与不相交的方法的组合。图IOa至IOc示出根据本发明的示例性实施方式的用于动态函数调用系统的可替换操作设置。图IOa示出放置于应用程序与操作系统(S卩,OS)之间的应用虚拟机。虚拟机管理指令的执行。当指令准备好被执行时,虚拟机可中断指令并将其直接发送至OS以本机地执行。在该实施方式中,虚拟机对正在运行的应用程序进行指令修改。与当指令修改位于应用本身中时的情况一样,对于该设置也需要类似的构建时间分析工具。
图IOb示出在应用程序旁边运行的并发进程或线程。该分离的线程或进程半独立于应用程序运行。在这种情况下,分离的进程或线程通过多个同步或异步执行方案中的任何一个与应用程序并发地执行。可从并发的进程或线程对应用程序进行指令修改。类似地,与在指令修改位于应用本身中时的情况一样,对于该设置也需要类似的构建时间分析工具。图IOc示出图IOa和IOb的设置的组合。运行两个并发线程或进程。附加地,虚拟机运行于应用层面和OS层面之间。各并发应用线程或进程可修改其它应用线程或进程中的指令。可替换地,应用线程或进 程可修改虚拟机中的指令。类似地,虚拟机可修改应用进程/线程中的任一个的指令。此外,该设置不排除应用进程/线程中的任一个与独立情况相同对自身进行修改。虚拟机也可以对自身进行修改。在之前的描述中,出于说明的目的,陈述了许多细节以使本发明的实施方式得到彻底的理解。然而,对本领域技术人员显而易见的是,这些具体细节不是实施本发明所必需的。在其它示例中,以框图的形式示出已知的电气结构和电路并不是为了使本发明模糊。例如,关于文中所描述的本发明的实施方式是否被实施为软件程序、硬件电路、固件、或它们的组合,不提供具体细节。本发明的实施方式可表现为储存在机器可读介质(又称为计算机可读介质、处理器可读介质、或使计算机可读程序代码具体化的计算机可用介质)中的软件产品。机器可读介质可以是任何合适的有形介质、包括磁、光、或电储存介质,包括磁带、只读磁盘存储器(CD-ROM)、存储装置(易失或非易失的)、或类似储存机构。机器可读介质可包含在执行时使处理器实行根据本发明的实施方式的方法中的步骤的多组指令、代码序列、配置信息、或其它数据。本领域技术人员应理解,实施所述发明所必需的其它指令和操作也可储存在机器可读介质上。来自机器可读介质的运行的软件可与电路衔接以进行所需的工作。本发明的上述实施方式仅是示例性的。在不背离本发明的范围的情况下,本领域技术人员可对本发明进行变更、修改和变形,本发明的范围由所附权利要求单独限定。
权利要求
1.一种通过改变软件程序的控制流结构将所述程序从原始形态变换为更加安全的形态以防止所述程序受到静态和动态攻击的方法,包括 a)分析所述程序的原始函数调用结构和原始函数调用布局; b)将所述原始函数调用布局变换为新函数调用布局; c)将所述原始函数调用结构变换为能够进行动态自我修改的新函数调用结构; d)产生变换程序,所述变换程序具有变换的控制流结构但在语义上等同于原始程序,所述变换程序被配置为在执行时将原始函数调用图变换为新函数调用图。
2.如权利要求I所述的方法,其中所述动态自我修改改变函数被调用的时间和方式。
3.如权利要求I所述的方法,其中步骤a)至c)是在构建时间执行的预修改,并且将原始函数调用图变换为新函数调用图的步骤在运行时间执行以执行在步骤a)至c)中计划的动态改变。
4.如权利要求I所述的方法,其中步骤a)还包括为所述程序中的每个函数确定重要性等级,以在对所述程序进行变换时重视重要的函数。
5.如权利要求I所述的方法,其中步骤b)至c)包括改变函数边界以掩饰所述函数调用布局。
6.如权利要求5所述的方法,其中改变函数边界包括打破函数边界并将至少两个函数连接成一个函数。
7.如权利要求5所述的方法,其中改变函数边界包括插入新函数边界以将函数分成至少两个函数。
8.如权利要求I所述的方法,其中步骤b)和c)还包括插入函数复本以在所述变换程序的执行期间使多个代码路径成为可能。
9.如权利要求8所述的方法,还包括使用非决定论以在所述函数调用图上随机地选择执行路径。
10.如权利要求I所述的方法,还包括改变所述调用图中的函数的执行次序。
11.如权利要求I所述的方法,还包括创建新函数并插入新函数调用。
12.如权利要求I所述的方法,还包括在战略点处插入诱饵。
13.如权利要求I所述的方法,还包括修改指令以改变它们的行为。
14.如权利要求I所述的方法,还包括移除指令并用空操作(NOP)指令替换它们。
15.如权利要求I所述的方法,还包括对所述程序进行破坏,所述破坏包括至少一个损坏性破坏紧跟着至少一个修复性破坏,以进一步掩饰所述函数调用结构并维持与所述原始程序的函数等效性。
16.如权利要求15所述的方法,还包括移除函数被调用的证据。
17.如权利要求15所述的方法,其中每个损坏性破坏具有多于一个修复性破坏。
18.如权利要求I所述的方法,还包括将所述变换程序设定为每当所述变换程序被执行时都具有不同的函数调用图。
19.如权利要求I所述的方法,其中步骤a)包括在所述程序中确定战略点以对所述程序进行修改。
20.如权利要求19所述的方法,其中步骤a)包括执行复杂的预分析步骤以理解所述程序的函数调用结构、函数调用布局、以及整个函数调用图。
21.如权利要求19所述的方法,其中步骤b)和c)还包括在所述程序中在与相应执行点物理地且短暂地远离的点处放置修改点。
22.如权利要求21所述的方法,还包括为执行点提供多个修改点。
23.如权利要求I所述的方法,其中所述变换的控制流结构包括所述新函数调用布局和所述新函数调用结构。
24.如权利要求23所述的方法,其中所述变换的控制流结构还包括下列中的一个或多个跳转、分支、返回、以及异常处理。
25.一种通过改变软件程序的控制流结构将所述程序从原始形态变换为更加安全的形态以防止所述程序受到静态和动态攻击的方法,所述方法包括构建时间阶段和运行时间阶段,所述构建时间阶段包括下列步骤 a)分析所述程序的原始函数调用结构和原始函数调用布局; b)将所述程序的原始函数调用布局变换为新函数调用布局; c)将所述原始函数调用结构变换为能够执行动态修改的新函数调用结构;以及 d)产生变换程序,所述变换程序具有变换的控制流结构但在语义上等同于所述原始程序; 所述运行时间阶段包括 e)在所述程序执行时将所述程序的原始函数调用图变换为新函数调用图; 其中在运行时间执行的所述动态修改是对在构建时间执行的改变的补充,以产生在语义上等同于所述原始程序的变换程序。
26.一种计算机可读储存器,所述存储器上记录有用于通过改变软件程序的控制流结构将所述程序从原始形态变换为更加安全的形态以防止所述程序受到静态和动态攻击的语句和指令,所述语句和指令在由处理器执行时使所述处理器执行以下步骤 a)分析所述程序的原始函数调用结构和原始函数调用布局; b)将所述原始函数调用布局变换为新函数调用布局; c)将所述原始函数调用结构变换为能够进行动态自我修改的新函数调用结构; d)产生变换程序,所述变换程序具有变换的控制流结构但在语义上等同于所述原始程序,所述变换程序被配置为在执行时将原始函数调用图变换为新函数调用图。
全文摘要
本发明的实施方式提供一种用于软件混淆的系统和方法,软件混淆用于将程序从第一形态变换为抵御静态和动态攻击的更加安全的形态。在一个实施方式中,该方法利用复杂的预分析步骤来理解程序的函数调用结构、函数调用布局、以及整个函数调用图,以在程序中确定战略点以改变程序。所述方法通过将原始函数调用布局变换为新布局来抵御静态攻击。在一个实施方式中,改变布局可包括改变函数边界。该方法还通过将原始函数调用结构变换为新结构来抵御静态攻击,其中新结构能够当变换程序在存储器中执行时进行自我修改。在一个实施方式中,改变函数调用结构可包括修改函数被调用的时间和方式、和/或选择导致相同结果的随机执行路径。变换的程序虽在语义上等同于原始程序但更好地抵御静态和动态攻击。
文档编号G06F21/00GK102713839SQ200980162789
公开日2012年10月3日 申请日期2009年10月8日 优先权日2009年10月8日
发明者克利福德·立厄姆 申请人:埃德图加拿大公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1