CN110088736A - 自调试 - Google Patents
自调试 Download PDFInfo
- Publication number
- CN110088736A CN110088736A CN201780075541.2A CN201780075541A CN110088736A CN 110088736 A CN110088736 A CN 110088736A CN 201780075541 A CN201780075541 A CN 201780075541A CN 110088736 A CN110088736 A CN 110088736A
- Authority
- CN
- China
- Prior art keywords
- debugger
- code
- software
- software process
- program
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/362—Software debugging
- G06F11/3624—Software debugging by performing operations on the source code, e.g. via a compiler
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/362—Software debugging
- G06F11/3644—Software debugging by instrumenting at runtime
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/362—Software debugging
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F21/00—Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F21/50—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems
- G06F21/52—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems during program execution, e.g. stack integrity ; Preventing unwanted data erasure; Buffer overflow
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F21/00—Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F21/50—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems
- G06F21/52—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems during program execution, e.g. stack integrity ; Preventing unwanted data erasure; Buffer overflow
- G06F21/54—Monitoring users, programs or devices to maintain the integrity of platforms, e.g. of processors, firmware or operating systems during program execution, e.g. stack integrity ; Preventing unwanted data erasure; Buffer overflow by adding security routines or objects to programs
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F2221/00—Indexing scheme relating to security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F2221/03—Indexing scheme relating to G06F21/50, monitoring users, programs or devices to maintain the integrity of platforms
- G06F2221/033—Test or assess software
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Computer Security & Cryptography (AREA)
- Computer Hardware Design (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Software Systems (AREA)
- Quality & Reliability (AREA)
- Debugging And Monitoring (AREA)
Abstract
总的来说,提供了保护软件的方法、计算机程序产品和设备。依照本公开,该方法可包括:将调试器进程附连到所述软件进程。所述软件进程执行期间,在所述调试器进程内执行与所述代码进程的功能有关的操作。结果,不侵害所述软件进程的功能情况下是不能替代或破坏所述调试器进程的。因此,可保护所述软件进程避免被通过修改的或恶意调试技术检查。
Description
产生本公开的工作受到[欧盟][欧洲原子能共同体]第七框架计划([FP7/2007-2013][FP7/2007-2011])第609734号拨款协议的资助。
技术领域
本发明涉及软件安全,尤其涉及利用调试技术来保护诸如应用程序或库的软件免受攻击。
背景技术
调试是这样一种进程:通过调试能够识别代码中的错误。用于调试的一个工具是调试器,调试器是许多操作系统允许其与要调试的代码配对的一种类型的工具。当发生异常或其他错误时,异常或其他错误的发生被报告给调试器,调试器随后能够检查代码并确定此问题的源头。
将调试器与代码配对的能力已被恶意方用于危害该代码的安全。特别地,由于调试器能够识别代码的运行,其能够成为漏洞之源。
已经开发出一些技术来视图保护代码免受这样的攻击。这些技术包括:尝试允许代码识别现用的调试器何时不正当地连接到代码。另一种方法是:将代码设计为本身能够在执行时启动调试器(此调试器可称为“自调试器”)。大多数操作系统将仅允许单个调试器与给定的进程配对,这意味着自调试器占用恶意调试器可能希望使用的空间。
附图说明
图1是在先的代码进程、以及本公开的耦合代码进程和调试器进程的主要特征的示意图;
图2是示出根据一种实施例的运行时步骤的流程图;
图3示出了根据本公开的二进制文件生成的主要方面;以及
图4示出了用于实现优选实施例的硬件架构。
具体实施方式
总的来说,提供了保护代码运行的方法。依照本公开,一种方法可包括:启动代码进程,并初始化附连到该代码进程的调试器进程。执行代码进程期间,能够在调试器进程内执行与代码进程的功能决定性地有关的操作。结果,不可能在不影响代码进程的功能的前提下替换或破坏调试器进程。因此,能够保护代码进程免受修改或恶意调试技术的检查。
在这样的背景下,“决定性地”可理解为表示调试器进程中执行的那些操作产生的输出作为代码进程其他部分的输入,并且表示考虑到代码进程的其他输入该输入对于允许代码进程生成其正确的输出是必要的。
在本公开的一些方面中,提供了一种保护软件的方法。该方法可以包括:启动软件进程,以及将调试器进程附连到该软件进程。然后,能够执行代码进程以使得至少一次调用调试器进程。调用时,可以在调试器进程中实施一个或多个函数,这些函数具有依赖于与软件进程关联的数据的输出。由于输出能够随着与软件进程关联的数据而发生变化(即,不是预定的),仅在软件进程和调试器进程都正常运行时才能实现整体功能。这样并没有给干预调试器进程以分析代码留出空间。
由于其取代了调试器正调试的进程,此方面的软件进程可视为“被调试”进程。可在启动软件进程时或之后初始化调试器进程。例如,可在(在软件进程中)加载某些功能(例如,库)时初始化调试器进程。在一些示例中,软件进程分叉以初始化调试器进程。在其他示例中,可先初始化调试器进程,然后分叉以生成软件进程。
在一些实施例中,输出包括由软件进程使用的数据输出。因此,调试器进程中的函数的输出能够直接影响软件进程之后的运行,由此,以不容易被破坏的方式将两个进程紧密结合在一起。调试器进程中的函数的输出包括软件进程的数据输入,所述数据输入对于软件进程的执行至关重要。
在一些实施例中,给定的函数的输出可表示软件进程中用于继续执行的多个返回点。这样,至少一个函数的返回点是可变的(不是固定的)。因此,控制流是能够根据调试器进程的运行而变化的,且无法容易推断或重建。
在一些实施例中,调试器进程提供存储器支持能力,以使一个或多个函数能够从软件进程的地址空间内的存储器获取数据。这样,程序有关的函数能够具有处理数据的能力,就好像其是在软件进程内执行的。
能够在到达代码进程的断点时调用调试器进程。能够在软件进程完成时将调试器进程与软件进程分离。由于软件进程是完成的,或者其他情况(诸如在中断时),软件进程可以结束。可替换地,可在软件进程内的功能完成时将调试器进程与软件进程分离,而不是等待整个进程完成。
在一些实施例中,软件进程实现可执行文件(例如,应用)。在其他实施例中,代码进程实现库。
在本公开的另一方面中,提供了一种生成受保护代码的方法。能够识别要迁移到调试器的目标代码内的代码段。然后,能够生成二进制代码,其中,二进制代码在运行时使得调试器进程附连到软件进程,在调试器进程内执行识别出的代码段。软件进程和调试器进程可从单个进程分叉开。例如,软件进程可以初始化调试器进程。
生成步骤可包括将与通用调试器功能对应的预定义的代码包含在二进制代码中。生成步骤可以是并入调试器的一些预定义方面的链接步骤,这样的预定义方面可称为“微型调试器”。这样,凭借识别出的代码段的包容性,整个调试器包括一些通用方面以及专用于源代码的一些方面。
该方法可包括从源代码提取识别要迁移到调试器的代码段的一个或多个注释。随后,编译源代码以生成目标代码。然后,识别的代码段与二进制代码中的调试器结合,能够从目标代码生成二进制代码。通过这样的方式,二进制代码的生成可为包括重写的要素以将识别的段移动到另一位置的链接步骤。随后使用二进制代码时,生成包括初始源代码的方面的调试器,这与源代码的功能有关。
在一些实施例中,二进制代码包括对应于源代码但不包括识别的代码段的第一二进制代码文件,以及对应于调试器的第二二进制代码。可替换地,单个二进制代码文件可包含源代码和调试器。
本公开的另外方面涉及计算机可执行程序产品,包括执行上述各方面的方法的计算机可执行指令。本公开的各方面还可涉及配置用于执行上述各方面的方法的设备。
现在参照附图,以说明的方式描述一些具体实施例,在附图中,相同的参考标号指代相同的特征。
在本公开中,二进制重写技术能够将整个功能块从初始软件中迁移到自调试器。这提供了一些优点。首先,自调试器的输入输出操作不再是预定的:每次自调试器干预时,其执行非预定的不同的功能,但可替代地,其能够随着受保护的程序中的功能的变化尽可能的变化。这使得该保护在对抗自动分析、解混淆、以及解构时更有弹性。其次,即使攻击者能够认出等同初始程序的控制流和数据流,攻击者撤销该保护并且重构该初始程序变得更难。相结合地,这两个优势使得攻击者分离调试器同时保持功能程序被追踪或现场调试更困难。
总体自调试器设计
图1说明了根据本公开的自调试机制的基本概念。此实施例面向Linux(及其衍生物,例如安卓),原理还可应用于其他环境,例如,Windows以及OS X。
在图1的左边,描绘了初始无防护的应用,包括小的控制流图片段。示出的汇编码是(伪)ARMv7代码。此无防护的应用转成由以下两部分构成的受保护的应用:主要对应于初始应用的被调试程序,如图中间部分所示,以及调试器,图右边所示。除了一些添加到被调试程序和调试器中的新的组件外,与初始应用的主要不同在于控制流图片段已从应用迁移到调试器中。此特定实施例支持不包含例如函数调用的过程间控制流的单入多出代码段。
这样的段的迁移不只是简单的复制:诸如LDR指令的存储器引用应当被转换,因为在受保护的应用中,在调试器地址空间中执行的经迁移的代码能够优选地访问仍留在被调试程序地址空间中的数据。将在之后的部分更详细的描述所有有关的组件和转换。
迁移的段优选地这对于应用的运行至关重要。也就是说,迁移到调试器进程执行的那些操作所产生的输出用作代码进程其余部分的输入,且考虑到代码进程的其他输入,该输入对于允许代码进程生成其正确的输出是至关重要的。在实践中,这样的要求很容易被漏掉。例如,通常的程序员可能考虑在调试器环境中执行代码进程变量的初始化。但是通常,在调试器进程中执行代码进程变量的初始化是不够的,因为在实践中,在进程中是经常发生的是,(例如,局部变量进入到函数时的)变量初始化作为好的编程实践的结果且为了满足源程序语言定义要求而实施,而实际上不是进程的正确运行和生成正确输出所需要的。这可能是因为变量仅仅不用在代码进程中的执行路径中,或者是因为初始值在能够影响代码进程执行或输出之前就被重写了。
运行时,此受保护的应用的运行如下。首先,在步骤s21启动被调试程序,就如它就是初始应用。新注入的初始化程序随后分叉出调试器的新进程,其中,调试器的初始化程序立即附连到被调试程序。因此,在步骤s22,调试器进程启动并附连到被调试程序。
之后在程序执行期间,到达迁移的代码段的入口点,应用中一个可能的控制流遵循图1中的箭头。在步骤s23,在应用/被调试程序中,包括指令的异常被执行并引发异常(图1中标为1)。在步骤s24,通知调试器此异常,调试器在其调试器循环中处理该异常(图1中标为2)。其中,此循环中的代码负责从被调试程序获取进程状态,查找对应的迁移的代码段,以及在步骤s25,将控制转移到该段的入口点(图1中标为3)。如上所述,在该段中,不能按原样实施存储器访问。因此,在步骤s26,存储器访问由在被调试程序的地址空间内访问存储器的存储器支持函数5的调用4来取代。在步骤s27,迁移的代码段中实际达到出口点6时,控制转移到调试器循环7中对应的点,在步骤s28,利用调试器中计算的数据更新被调试程序的状态,并且在步骤s29,控制转移回被调试程序。对于具有多个出口的代码段,例如图中的示例,控制能够转移回被调试程序中的多个继续点。就这点而言,本公开的调试器的行为方式比现有的自调试器更复杂,实现了在被调试程序和调试器之间转移的前向和后向控制流之间的一对一映射。
事实上,应用退出时,嵌入式终止化程序将实施必要的分离操作。
值得注意的是,此机制不仅能够用于保护可执行文件(即,具有主要函数和入口点的二进制文件),还用于保护共享库。类似于可执行文件,库能够包含由OS加载器加载或卸载时执行的初始化程序以及终止化程序。此时,也能够实施所有必要的分叉、附连以及分离。
尽管以下描述主要涉及保护应用,隐含地,该教导同等地适用于应用和库。特别与库有关的一方面是对于调试器的适当的初始化和终止化的需求。由于对于库来说,在单次执行程序中加载以及卸载多次并不少见,因此这是必要的。例如,对于媒体播放器和浏览器的插件,会频繁发生重复加载和卸载。此外,启动主程序时,主程序仅由一个线程构成,而库加载和卸载时主程序能够由多个线程构成。
工具支持
图3描绘了一个可能的概念工具流。
源代码注释
为了确定要向调试器迁移的代码段,存在多种选项。图中描绘的一种选项是:在步骤s31,利用标记要向调试器进程迁移的代码区域的起点和结束的编译指示、备注或任意其他形式的注释来给源代码作注释,这也是在我们的实现方式中使用的选项。简单的grep足以提取注释及其行号,且足以在步骤s32将该信息存储在注释文件中。
替代的选项是列出要保护的程序或源代码文件,或收集痕迹或简档,以半自动地选择感兴趣的段。
就这一点而言,值得注意的是,要迁移到调试器的段不一定是非常热门的段。为了实现被调试程序和调试器之间较强的附连,相对频繁的引发异常就足够,但这不需要是在最热门的代码路径上。下面将详细描述选择段的另外考虑。由于每个引发的异常会引入大量开销(上下文切换,许多ptrace调用,等),最小化其数量而不危害保护等级是非常重要的。
标准编译器和工具
为了部署所公开的自调试方法,在步骤s33能够使用任何“标准”编译器。该技术不对编译器生成的代码强加任何限制。在试验评估中,使用了GCC和LLVM,其中,没有适应或调试代码生成的要求。
但是,一个要求在于编译器和二进制实用程序(汇编器和链接器)为链接时重写器提供足够精确的符号和重新定位信息。这是使得能够进行可靠的、保守链接时的代码分析以及转换从而实现整个自调试机制所要求的,其中整个自调试机制包括所选择的代码段的迁移和转换。对于常用工具,提供足够精确的信息是容易实现的。例如默认已这样做了很久的ARM专有编译器,并且对于GNU二进制实用程序(binutil)、GCC和LLVM,非常简单的补丁足以防止那些工具执行过度激进的符号松弛和重新定位简化,且足以迫使其插入映射符号以标记代码中的数据。之前已记载了这些要求,已表明它们足以如全都是手写的汇编代码的CISC(×86)和RISC(ARMv7)版本的Linux核和C库那样复杂且非传统,实施代码的可靠的保守连接时重写。
能够利用标准编译器来预编译调试器的较大的通用部分——微型调试器,且随后,将其简单地连接到要保护的应用中。由于诸如每个迁移的段的调试循环的序和结语这样的其他部分是为特定的段定制的,由链接时重写器生成该其他部分。
为了允许链接时重写器识别源代码中注释的段,向编译器传递从源代码文件中提取行号信息并且使编译器利用调试信息生成对象文件就足够。该调试信息随后将二进制代码中的全部地址映射到源行号,重写器能够根据注释链接至行号。
二进制文件、库、以及进程
链接时重写器具有在步骤s35生成受保护的应用的两种选项。第一种选项是生成两个二进制文件,一个用于应用/被调试程序,一个用于调试器。从安全的角度讲,这可能是优选的,因为应用语义及其实现方式随后分布于多个二进制文件,很可能使得攻击者更难以破坏保护,即将被调试程序修补成初始应用。此选项不会引入额外的运行时开销。但是,由于调试器的启动,随后也需要加载第二个二进制。
下面的其他示例中所用的可替换的选项是:将所有被调试程序代码和所有调试器代码嵌入到一个二进制文件。在这样的情况中,简单的分叉足以启动调试器。这是否减轻了对自调试提供的保护的攻击,以及将对自调试提供的保护的攻击减轻到什么程度是开放的研究问题。
实现方式
初始化以及终止化
能够对受保护的二进制文件增加额外的初始化例程。加载二进制文件后尽快调用此例程(因为其分配了较高优先级),此后,执行二进制文件的.init部分列出的所有其他例程。
此初始化例程调用fork(),因此,创建父子两个进程。一旦完成初始化例程,父进程将通常通过调用下一个初始化例程来继续执行。
存在分配调试器和被调试程序角色的两种选项:分叉后,子进程附连到父进程,或者父进程附连到子进程。在前一种情况下,子进程变成调试器,父进程变成被调试程序,在后一种情况下,角色显然相反。
前一选项是优选的。父进程(即,被调试程序)仍然是主要的应用进程,其保持同样的进程ID(PID)。例如,由于初始PID在加载和分叉受保护的库之前建立,这有助于依赖于初始PID的进程间通信通道和所有外部应用的持续执行或使用。
但是,此方案有其自己的问题。如已经提到的,能够在程序执行期间的任意时刻(使用dlopen()以及dlclose())加载及卸载共享库。因此,存在这样的可能的问题:可能在最初加载及分叉的调试器还未完成其初始化时再次卸载和加载受保护的共享库。这会导致两个调试器进程同时存在,两个调试进程都试图附连到被调试程序(一个失败)。为了避免这样的情况,我们阻止调用dlopen()的线程的执行。因此在这一时刻到来之前,该线程不能使用其利用dlopen()得到的句柄调用函数dlclose(),并且它也不能将句柄传到另一个线程。被调试程序初始化例程的无限循环防止加载线程在调试器允许其继续之前退出初始化。
初始化例程还在被调试程序中安装终止化程序。此终止化程序没有太多的作用。在程序出口(或卸载共享库时),其仅仅通过发出SIGUSRI信号来通知微型调试器该事实,使得微型调试器与所有被调试程序线程分离,以及关闭调试器进程。
多线程支持
附着调试器并非无关紧要,尤其在受保护的共享库的情况下。加载库时,应用可能由几个线程构成。仅其中的一个线程会在调用dlopen期间执行被调试程序初始化例程。这是好的,因为仅将执行一个分叉,但它也有其自身的缺点:仅一个线程会进入前面章节提到的无限循环。被调试程序进程中的其他线程会继续运行,且可能在被调试程序初始化例程或调试器初始化例程执行期间的任意点创建新的线程。为了确保适当的保护,调试器应附于被调试程序进程的每个线程,作为其初始化的部分。同时,为了确保调试器不会漏掉在被调试程序中创建的任何线程,我们使用/proc/[pid]/task目录,该目录包含进程中每个线程的条目。调试器进程通过迭代此目录中所有条目,并通过保持迭代直至没有发现新的条目,来附于所有线程。通过PTRACE_ATTACH请求的方式发生附连到线程时,线程也停止(且OS通知调试器此事件),意味着其从那时起不再产生新的线程。因此,对于产生有限数量线程的任意程序,确保附于所有线程的迭代程序终止。一旦所有线程都被附连之后,被调试程序中的无限循环结束,且允许其停止的线程继续。当程序执行期间随后创建附加线程时,OS将调试器自动附于所创建的附加线程,且调试器获得信号,使得能够实施所有必要的登记(bookkeep)。
控制流
将控制流转换成迁移的代码段以及将代码段转换成控制流由几部分构成。我们讨论通知调试器的异常发生,告知调试器要执行哪个片段的ID的转移,以及增加到每个代码段的定制的序和结语。
引发异常
调试器的实际通知能够通过引起要引发的异常的任何指令产生。在我们的实现方式中,为了简单起见,我们使用软件断点(即,ARMv7上的BKPT指令)。当然也可以使用其他不太显眼的异常,例如非法或未定义的指令所引起的那些。当这样的指令能够通过直接控制流(直接分支或导向(fall-through)路径)获得时,当然也容易静态检测这样的指令。但是,间接控制流转移被用于跳转到代码段中的数据时,且数据位对应于非法或未定义的指令时,静态检测更困难。同样地,仅在其运算对象是“无效的”时输出异常的合法指令能够用于掩藏指令的目的。这样的指令包括除以零,无效存储器访问(即,分段错误),或延迟无效指针(导致总线错误)。
转移ID
由于引发异常的被调试程序中的线程实质上要求调试器执行一些代码段,我们将其称为请求线程。
被OS告知请求之后,调试器需要确定执行哪个段。为了使得调试器能够确定执行哪个段,被调试程序可以以多种方式传递段的ID。一个选项是简单地使用异常诱导指令的地址作为ID。另一选项是通过将ID放置在紧接引发异常之前的固定寄存器中或固定的存储器位置中来传递ID。在我们的实现方式中,我们使用后一选项。由于被调试程序中的多个线程能够同时请求不同的段,存储器位置不能是全局位置。相反地,存储器位置需要是线程局部的。由于每个线程具有其自己的栈,我们选择经由请求线程的栈的顶部来传递段ID。
基于用于引发异常的指令类型,还可以预想到其他方法。例如,(除0的)除数操作数指令也可用于传递ID。
序言和结语
微型调试器中的调试器循环负责在执行段之前获取被调试程序的程序状态,并且在执行后将其转移回去。标准ptrace功能用于此。
对于每个迁移的代码段,调试循环也包含要在代码段之前或之后分别执行的定制的序言和结语。序言将必要的值从结构体加载到寄存器中,结语将必要的值写回到结构体中。序言是从其仅加载实际在段中使用的寄存器(称为现场调入寄存器)这一方面来定制的。结语仅存储现场调入(即,将在被调试程序中耗尽)的值以及在代码段中重写的值。
存储器访问
对于迁移的代码段中的每次加载或存储操作,需要访问被调试程序的存储器。存在实现这样的访问的多种选项。第一选项是简单地使用ptrace功能:调试器能够执行PTRACE_PEEKDATA和PTRACE_POKEDATA请求,以读写被调试程序位置空间。在这样的情况下,每个字被读或写,都需要ptrace系统调用,这导致大量开销。一些最近的Linux版本支持更广泛的访问,但这样的访问不是每个地方都可用,例如安卓上就不可用。
第二选项是在调试器中打开被调试程序的/proc/[pid]/mem文件,然后简单地在此文件中读或写。这更容易实现,且能够利用单个系统调用来读或写更宽范围的数据,因此通常这样的方法更快。但是,不是每个版本的Linux/安卓核都支持写到另一个进程的/prooc/[pid]/mem,因此在我们的原型中仍用第一选项实现写请求。
第三选项建立在第二选项上:如果二进制重写能够确定在迁移的代码段中将要访问哪个存储器页,调试循环实际上能够使用选项2将那些页复制到调试器地址空间中。随后,调试器中的段简单地执行常规加载和存储操作以访问复制的页,并且在已执行了段之后,更新的页被复制返回到被调试程序。例如,如果代码段包含访问栈上的缓冲器的循环,此选项能够更快。我们进行了将第三选项与前两个选项作比较的实验,且实验揭示了此技术对于仅8次存储器访问是值得的。但是,在我们的原型中我们没有实现对其的可靠支持。确定代码段将访问哪页的保守的连接时分析目前仍是未来的工作。
第四潜在选项是通过例如提供定制的堆存储器管理库(malloc、free、…)来改编被调试程序,使得所有分配的存储器(或至少该堆)被分配作为被调试程序和调试器进程之间的共享存储器。随后,调试器中的代码段可直接访问数据。当然,段仍然需要被重写,以包括两个地址空间之间的地址的转换,但可能地,此选项的开销能够比其他选项的开销更低。实现此选项以及评估此选项目前仍是未来的工作。
安全方面,就其将影响攻击者对程序的初始语义进行反向工程以及将自调试版本重构成初始程序的等效替代的困难性这方面,不同的选项可能也具有不同的影响。
自调试与其他保护结合
为了提供针对MATE攻击的更强有力的软件保护,可使用其他保护技术。例如,除了自调试,可使用混淆以防止静态分析,结合防篡改技术以防止全部种类的攻击。
例如,实现自调试方法的二进制重写器还可应用多个其他的保护,例如下面中的一个或多个:
控制流混淆:众所周知的不透明谓词、控制流平整、以及分支函数的混淆;
代码排布随机化:代码排布期间,所有函数的代码混合,且随机化排布;
代码迁移:一种如下的技术:从静态二进制文件移除代码段,且仅在运行时将代码段下载到应用作为所谓的移动代码;
代码保护:技术的线上及线下实现方式,其中,对进程地址空间中的代码进行哈希计算,以检查代码是否已被改变。
控制流完整性:一种轻量化技术,在该技术中检查返回地址以防止从外部代码调用内部函数。
指令集虚拟化:一种这样的技术:通过该技术,本地代码转换成由嵌入的虚拟机解释而不是在本地执行的字节代码。
将自调试技术与所有那些保护结合在实践中不会造成任何问题。在连接时重写器中,确定良好的顺序来执行针对所有保护的所有转换,并防止多个技术在那些技术实际上未构成时应用于相同的代码段并不困难。例如,移动代码重新定位到随机位置。正确处理所有保护要求一些登记,但并不复杂。
对于运行时行为,技术也进行构成。多种技术要求初始化程序以及终止程序,但在调试进程中,我们不想执行其他保护的初始化,因为该调试器进程应仅为调试器,而不是代码迁移或任何其他技术的另一客户端。为了防止执行其他初始化,给予自调试器初始化程序最高优先级。当加载二进制文件或库时,首先执行自调试器初始化程序,调试器初始化例程实际上实现真正的初始化程序以及调试循环。因此,例程从不结束(也即,只要未调用终止程序,例程就不结束),且因此,控制不会转移到二进制文件中可能会存在的其他初始化程序。
评估
评估平台
自调试器的一个实现方式目标是ARMv7平台。具体地,此实现方式目标在于且广泛评估Linux 3.15及(限制权限的)安卓4.3+4.4上的实现。进一步确认了在最新版本的Linux(4.7)和安卓(7.0)上该技术仍然起作用,且事实确实如此。
测试硬件包括几个开发板。对于Linux,使用具有单核德州仪器OMAP4处理器的特征的Panda板,还使用了具有双核三星Exynos处理器的特征的Arndale板,以及具有单核Freescale i.MX6q处理器的特征的边界设备Nitrogen6X/SABRE Lite板。后面的板也用于安卓版本。
在工具链中,使用了GCC 4.8、LLVM 3.4以及GNU实用程序2.23。利用以下标记来编译代码:-Os-march=armv7-a–marm-mfloat-abi=softfp-mfpu=neon-msoft-float。
用例
已表明自调试机制在多个用例中发挥作用。例如,在数字权利管理场景中,遇到了以下实际问题。
对于安卓媒体框架以及安卓DRM框架,此用例包括用C和C++写的两个插件。这些库对于访问加密电影以及进行解密是必要的。Java编程的视频应用用作访问视频的GUI。此应用与媒体服务器和安卓的DRM框架通信,通知供应商的框架其所需要的插件。根据需要,这些框架随后加载插件。具体地,这些服务器是媒体服务器以及安卓上运行的drm服务器进程。
试验及研发期间,注意到一些特征使此用例成为此技术的最佳压力测试。首先,媒体服务器是多线程的,且总是创建及终止新的进程。其次,频繁加载及卸载插件库。有时,甚至在库的初始化结束之前启动卸载。第三,进程一崩溃就启动新的实例。有时这使得Java视频播放器能够继续不受干扰的运作,有时不能。这使得调试我们技术的实现方式比它已经用于简单的应用更复杂。第四,在频繁的进程间通信中需要媒体服务器和drm服务器。然而,基于上述原理实现了成功的实现方式。
本技术可用于众多其他的用例场景。例如,用在移动银行或要求安全性的任意其他场景。
图4说明了计算设备400的一个实现方式的框图,可在该计算设备中执行使得计算设备实施本文所讨论的任何一个或多个方法的指令集合。在可替代的实现方式中,计算设备可连接(例如,联网)至局域网(LAN)、内联网、外部网络、或互联网中的其他机器。该计算设备可以在客户端-服务器网络环境中的服务器或客户端机器的容量(capacity)中进行操作,或作为端对端(或分布式)网络环境中的对等机器运行。计算设备可为个人电脑(PC)、平板计算机、机顶盒(STB)、个人数字助理(PDA)、蜂窝电话、网络设备、服务器、网络路由器、交换机或网桥、或能够执行规定机器运作的指令集合(或序列)的任意机器。此外,虽然仅说明了单个计算设备,术语“计算设备”还应包括独立或联合执行一个或多个指令集以执行本文讨论的一个或多个方法的任何机器(例如,计算机)的集合。
示例的计算设备400包括经由总线430相互通信的处理设备402、主存储器404(例如,只读存储器(ROM))、闪存、诸如同步DRAM(SDRAM)或Rambus DRAM(RDRAM)等的动态随机存取存储器DRAM、静态存储器406(例如,闪存、静态随机存取存储器(SRAM)等)以及次级存储器(例如,数据存储设备418)。
处理设备402表示一个或多个通用存储器,例如,微处理器、中央处理器等。更特别地,处理设备402可为复杂指令集计算(CISC)微处理器、精简指令集计算(RISC)微处理器、超长指令字(VLIW)微处理器、实现其他指令集的处理器、或实现指令集的组合的处理器。处理设备402还可为一个或多个专用处理设备,例如,专用集成电路(ASIC)、现场可编程门阵列(FPGA)、数字信号处理器(DSP)、网络处理器等。处理设备402被配置为执行实施本文讨论的操作和步骤的处理逻辑(指令422)。
计算设备400还可包括网络接口设备408。计算设备400还包括视频显示单元410(例如,液晶显示器(LCD)或阴极射线管(CRT))、字母数字输入设备412(例如,键盘或触摸屏)、光标控制设备414(例如,鼠标或触摸屏)以及音频设备416(例如,扬声器)。
数据存储设备418可包括一个或多个机器可读存储介质(或更特别地,一个或多个非易失性计算机可读存储介质)428,其上存储实现本文描述的一个或多个方法或功能的一个或多个指令集422。计算机系统400执行指令422期间,指令422还可完全或至少部分位于主存储器404内,和/或处理设备402内,主存储器404和处理设备402还构成计算机可读存储介质。
可通过计算机程序实现上述各种方法。计算机程序可包括计算机代码,该计算机代码设置用于指示计算机实施上述各种方法中的一个或多个方法的功能。实施这样的方法的计算机程序和/或代码可以在一个或多个计算机可读介质上,或者更一般地,在计算机程序产品上,提供给诸如计算机的装置。计算机可读介质可为易失性或非易失性的。一个或多个计算机可读介质可为例如电、磁、光、电磁、红外、或半导体系统、或用于数据传输的传播介质,数据传输例如通过互联网下载代码。可替换地,一个或多个计算机可读介质能够采用一个或多个物理计算机可读介质的形式,例如,半导体或固态存储器、磁带、可移除计算机磁盘、随机存取存储器(RAM)、只读存储器(ROM)、刚性磁盘、以及光盘,例如CD-ROM、CD-R/W或DVD。
在一种实现方式中,本文描述的模块、组件和其他特征(例如,关于图4的控制单元410)可实现为分立组件,或集成于诸如ASICS、FPGA、DSP或类似设备的硬件组件的功能中,作为个性化服务器的部分。
“硬件组件”是有形的(例如,非易失性的)物理组件(例如,一个或多个处理器的集合),能够实施某些操作且可以以某些物理方式配置或设置。硬件组件可包括永久配置用于实施某些操作的专用电路或逻辑。硬件组件可为或包括专用处理器,例如,现场可编程门阵列(FPGA)或ASIC。硬件组件还可包括通过软件暂时配置用于实施某些操作的可编程逻辑或电路。
因此,短语“硬件组件”应理解为包含可物理构建、永久配置(例如,硬连线)或暂时配置(例如,编程)从而以某些方式运行或用于实施本文描述的某些操作的有形实体。
此外,各模块和组件能够实现为固件或硬件设备中的功能电路。此外,各模块或组件能够实现为硬件设备和软件组件的任意结合,或仅实现为软件(例如,存储于或以其他方式嵌入机器可读介质或传输介质中的代码)。
除非特别说明,根据以下讨论显而易见的,可以认识到,在整个描述中,使用诸如“接收”、“确定”、“比较”、“使能”、“维持”、“识别”、“替换”等的术语的讨论指的是计算机系统或类似的电子计算设备的动作和程序,其操纵并将表示为计算机系统的寄存器和存储器中的物理(电子)量的数据转换成类似地表示为计算机系统存储器或寄存器或其他这样的信息存储、传输或显示设备中的物理量的其他数据。
应理解到,上面的描述目的在于说明,而不是限制。对于本领域的技术人员,通过阅读及理解上面的描述,许多其他的实现方式是显而易见的。尽管已参照具体示例的实现方式描述了本公开,应意识到,本公开不限于所描述的实现方式,而是可以实践为具有所附权利要求的精神和范围内的修改和变化。因此,说明书和附图视为说明,而不是限制。因此,应当参照所附权利要求以及这些权利要求所要求的等同形式的全部范围来确定本公开的范围。
Claims (15)
1.一种保护软件的方法,包括:
启动软件进程;
将调试器进程附连到所述软件进程;
执行所述软件进程,使得至少调用一次所述调试器进程;
响应于所述调试器进程的调用,在所述调试器进程内执行一个或多个函数,所述一个或多个函数具有依赖于与所述软件进程关联的数据的输出。
2.根据权利要求1所述的方法,其中,所述输出包括所述软件进程使用的数据输出。
3.根据权利要求1或2所述的方法,其中,给定函数的所述输出可指示用于继续执行的所述软件进程内的多个返回点。
4.根据前述权利要求中的任一项所述的方法,其中,所述调试器进程提供存储器支持能力,以使所述一个或多个函数能够在所述软件进程的地址空间内从存储器获取数据。
5.根据前述权利要求中的任一项所述的方法,其中,当到达所述软件进程内的断点时调用所述调试器进程。
6.根据前述权利要求中的任一项所述的方法,进一步包括:所述软件进程完成时,将所述调试进程与所述软件进程分离。
7.根据前述权利要求中的任一项所述的方法,其中,所述软件进程实现诸如应用的可执行文件。
8.根据权利要求1至6中的任一项所述的方法,其中,所述软件进程实现库。
9.一种计算机可执行程序产品,包括用于执行前述权利要求中任一项所述的方法的计算机可执行代码。
10.一种设备,其被配置用于执行权利要求1至8中任一项所述的方法。
11.一种生成受保护代码的方法,包括:
识别要迁移到调试器的目标代码内的代码段;
生成二进制代码,所述二进制代码在运行时使得调试器进程附连到软件进程,识别出的代码段在所述调试器进程内执行。
12.根据权利要求11所述的方法,其中,生成步骤包括在所述二进制代码中并入对应于通用调试器功能的预定义代码。
13.根据权利要求11或12所述的方法,其中,所述二进制代码包括对应于源代码但不包括识别出的代码段的第一二进制代码文件,以及对应于调试器的第二二进制代码文件。
14.一种计算机可执行程序产品,包括用于执行根据权利要求11至13中任一项所述的方法的计算机可执行代码。
15.一种设备,其被配置为执行根据权利要求11至13中任一项所述的方法。
Applications Claiming Priority (3)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
EP16202259.4A EP3330859A1 (en) | 2016-12-05 | 2016-12-05 | Self-debugging |
EP16202259.4 | 2016-12-05 | ||
PCT/EP2017/081587 WO2018104344A1 (en) | 2016-12-05 | 2017-12-05 | Self-debugging |
Publications (2)
Publication Number | Publication Date |
---|---|
CN110088736A true CN110088736A (zh) | 2019-08-02 |
CN110088736B CN110088736B (zh) | 2023-05-23 |
Family
ID=57482335
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201780075541.2A Active CN110088736B (zh) | 2016-12-05 | 2017-12-05 | 自调试方法和系统 |
Country Status (9)
Country | Link |
---|---|
US (1) | US11580007B2 (zh) |
EP (2) | EP3330859A1 (zh) |
JP (1) | JP7042270B2 (zh) |
KR (1) | KR102684371B1 (zh) |
CN (1) | CN110088736B (zh) |
BR (1) | BR112019011434A2 (zh) |
ES (1) | ES2901532T3 (zh) |
PT (1) | PT3549020T (zh) |
WO (1) | WO2018104344A1 (zh) |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN111935622A (zh) * | 2020-08-03 | 2020-11-13 | 深圳创维-Rgb电子有限公司 | 带数字功放电子设备的调试方法、装置、设备及存储介质 |
Families Citing this family (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
EP3595190A4 (en) * | 2017-03-14 | 2020-07-15 | Guangdong Oppo Mobile Telecommunications Corp., Ltd. | UPLINK SIGNAL TRANSMISSION METHOD AND ASSOCIATED DEVICE |
EP4097614A1 (en) * | 2020-01-28 | 2022-12-07 | C2A-SEC, Ltd. | Control flow integrity system and method |
CN111737661A (zh) * | 2020-05-22 | 2020-10-02 | 北京百度网讯科技有限公司 | 异常堆栈处理方法、系统、电子设备及存储介质 |
KR102271273B1 (ko) * | 2020-11-26 | 2021-06-29 | 숭실대학교산학협력단 | 네이티브 코드 분석방지 우회를 위한 프로세스 래핑 방법, 이를 수행하기 위한 기록 매체 및 장치 |
US11886589B2 (en) | 2020-11-26 | 2024-01-30 | Foundation Of Soongsil University-Industry Cooperation | Process wrapping method for evading anti-analysis of native codes, recording medium and device for performing the method |
US11681786B2 (en) * | 2020-12-07 | 2023-06-20 | Arm Limited | System, devices and/or processes for secure computation |
CN117370214B (zh) * | 2023-12-01 | 2024-04-19 | 珠海格力电器股份有限公司 | 一种控制器的程序调试方法、装置和存储介质 |
Citations (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US7647589B1 (en) * | 2005-02-07 | 2010-01-12 | Parallels Software International, Inc. | Methods and systems for safe execution of guest code in virtual machine context |
CN103077112A (zh) * | 2012-10-16 | 2013-05-01 | 中兴通讯股份有限公司 | 一种软件调试的方法和系统 |
US20140289707A1 (en) * | 2013-03-21 | 2014-09-25 | International Business Machines Corporation | Dynamic code switching in debugging process |
CN105229654A (zh) * | 2013-03-27 | 2016-01-06 | 爱迪德技术有限公司 | 保护软件应用 |
CN105683924A (zh) * | 2013-06-06 | 2016-06-15 | 微软技术许可有限责任公司 | 通过从在本机模式中执行转变为在经解释的模式中执行来调试本机代码 |
Family Cites Families (9)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US7162664B2 (en) * | 2003-06-20 | 2007-01-09 | Microsoft Corporation | Debugging breakpoints on pluggable components |
JP4048382B1 (ja) * | 2006-09-01 | 2008-02-20 | 富士ゼロックス株式会社 | 情報処理システムおよびプログラム |
WO2008144524A1 (en) | 2007-05-18 | 2008-11-27 | Verimatrix, Inc. | System and method for defining programmable processing steps applied when protecting the data |
US8166459B2 (en) * | 2008-02-27 | 2012-04-24 | Sap Ag | Apparatus and method of generating self-debugging computer software |
JP5549810B2 (ja) * | 2010-06-25 | 2014-07-16 | 日本電気株式会社 | プログラム難読化装置、プログラム制御装置、プログラム難読化方法及びプログラム |
FR3003967B1 (fr) * | 2013-03-29 | 2015-05-01 | Alstom Transport Sa | Procede d'execution d'un logiciel securitaire et d'un logiciel non securitaire entrelaces |
KR101434860B1 (ko) * | 2013-08-16 | 2014-09-02 | (주)잉카엔트웍스 | 해시를 이용한 동적코드의 무결성 검증 방법 |
US9262300B1 (en) * | 2014-06-24 | 2016-02-16 | Google Inc. | Debugging computer programming code in a cloud debugger environment |
US9892019B2 (en) * | 2015-10-16 | 2018-02-13 | Successfactors Inc. | Use case driven stepping component automation framework |
-
2016
- 2016-12-05 EP EP16202259.4A patent/EP3330859A1/en not_active Withdrawn
-
2017
- 2017-12-05 WO PCT/EP2017/081587 patent/WO2018104344A1/en active Application Filing
- 2017-12-05 KR KR1020197017015A patent/KR102684371B1/ko active IP Right Grant
- 2017-12-05 US US16/466,044 patent/US11580007B2/en active Active
- 2017-12-05 CN CN201780075541.2A patent/CN110088736B/zh active Active
- 2017-12-05 EP EP17808502.3A patent/EP3549020B1/en active Active
- 2017-12-05 ES ES17808502T patent/ES2901532T3/es active Active
- 2017-12-05 BR BR112019011434A patent/BR112019011434A2/pt unknown
- 2017-12-05 JP JP2019527551A patent/JP7042270B2/ja active Active
- 2017-12-05 PT PT178085023T patent/PT3549020T/pt unknown
Patent Citations (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US7647589B1 (en) * | 2005-02-07 | 2010-01-12 | Parallels Software International, Inc. | Methods and systems for safe execution of guest code in virtual machine context |
CN103077112A (zh) * | 2012-10-16 | 2013-05-01 | 中兴通讯股份有限公司 | 一种软件调试的方法和系统 |
US20140289707A1 (en) * | 2013-03-21 | 2014-09-25 | International Business Machines Corporation | Dynamic code switching in debugging process |
CN105229654A (zh) * | 2013-03-27 | 2016-01-06 | 爱迪德技术有限公司 | 保护软件应用 |
CN105683924A (zh) * | 2013-06-06 | 2016-06-15 | 微软技术许可有限责任公司 | 通过从在本机模式中执行转变为在经解释的模式中执行来调试本机代码 |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN111935622A (zh) * | 2020-08-03 | 2020-11-13 | 深圳创维-Rgb电子有限公司 | 带数字功放电子设备的调试方法、装置、设备及存储介质 |
CN111935622B (zh) * | 2020-08-03 | 2022-02-11 | 深圳创维-Rgb电子有限公司 | 带数字功放电子设备的调试方法、装置、设备及存储介质 |
Also Published As
Publication number | Publication date |
---|---|
JP2019537150A (ja) | 2019-12-19 |
BR112019011434A2 (pt) | 2019-10-22 |
US11580007B2 (en) | 2023-02-14 |
WO2018104344A1 (en) | 2018-06-14 |
KR20190090810A (ko) | 2019-08-02 |
EP3330859A1 (en) | 2018-06-06 |
JP7042270B2 (ja) | 2022-03-25 |
PT3549020T (pt) | 2021-12-02 |
EP3549020A1 (en) | 2019-10-09 |
ES2901532T3 (es) | 2022-03-22 |
EP3549020B1 (en) | 2021-10-13 |
CN110088736B (zh) | 2023-05-23 |
KR102684371B1 (ko) | 2024-07-11 |
US20190286551A1 (en) | 2019-09-19 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN110088736A (zh) | 自调试 | |
Kroes et al. | Delta pointers: Buffer overflow checks without the checks | |
Gal et al. | Trace-based just-in-time type specialization for dynamic languages | |
US8615735B2 (en) | System and method for blurring instructions and data via binary obfuscation | |
CN103019799A (zh) | 具有指令签名支持的分布式编译处理 | |
Abrath et al. | Tightly-coupled self-debugging software protection | |
Fourtounis et al. | Static analysis of java dynamic proxies | |
US20230267067A1 (en) | Software protection from attacks using self-debugging techniques | |
De Keulenaer et al. | Link-time smart card code hardening | |
Kang | Function call interception techniques | |
Yedidia | Lightweight Fault Isolation: Practical, Efficient, and Secure Software Sandboxing | |
Stucki et al. | Bridging islands of specialized code using macros and reified types | |
Soares et al. | Side-channel elimination via partial control-flow linearization | |
Dinesh | Retrowrite: Statically instrumenting cots binaries for fuzzing and sanitization | |
Baumann et al. | Cudagrind: Memory-usage checking for cuda | |
Harper‐Cyr et al. | Fast and flexible tracepoints in x86 | |
Rosà et al. | Adaptable runtime monitoring for the java virtual machine | |
Puder et al. | Cross-compiling Java to JavaScript via tool-chaining | |
Saeed et al. | Tag‐Protector: An Effective and Dynamic Detection of Illegal Memory Accesses through Compile Time Code Instrumentation | |
Yin et al. | PAST: accurate instrumentation on fully optimized program | |
Rizzo et al. | Hardening and Testing Privileged Code through Binary Rewriting | |
Drescher et al. | Fast Template-Based Code Generation for MLIR | |
Dang et al. | Verse: An EDSL for cryptographic primitives | |
Adler et al. | Speculative optimizations for interpreting environments | |
Suzuki | Translating java bytecode to BoogiePL |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |