对动态代码实施影子堆栈违规。线程在处理器处被执行,其包括生成用于由线程执行的动态代码的部分、标识动态代码的部分被加载到存储器中的存储器地址范围以及启动动态代码的部分执行。至少基于线程的执行来处理异常,该异常由从与线程对应的调用堆栈弹出的第一返回地址和从与线程对应的影子堆栈弹出的第二返回地址之间的不匹配所触发。处理异常包括(i)确定从影子堆栈弹出的第二返回地址是否在标识的地址范围内,以及(ii)基于已经确定第二返回地址在地址范围内,启动影子堆栈强制动作。启动影子堆栈强制动作。启动影子堆栈强制动作。
【技术实现步骤摘要】
【国外来华专利技术】用于动态代码的影子堆栈强制范围
技术介绍
[0001]在大多数现代计算架构中,操作系统针对每个线程分配部分系统存储器到调用堆栈(有时称为机器堆栈或执行堆栈)。此调用堆栈用于促进应用代码内的过程(procedure)调用(例如,函数、例程等)。通常,在线程执行期间每次调用过程时,都会将新的堆栈帧添加或“推送”到该线程的调用堆栈。此堆栈帧通常由过程的“序言(prologue)”创建,该过程可以保存返回调用上下文所需的状态信息(例如,过程退出后将被执行的下一指令的返回地址、保存的寄存器值等),为了向过程传递任何参数而分配存储器,为过程的局部变量分配存储器等。堆栈帧中包含的特定数据以及该数据的布局取决于处理器架构、操作系统等。当过程退出时,它的堆栈帧从线程的调用堆栈中被去除或“弹出”。此堆栈帧通常由过程的“结尾(epilogue)”去除,这可以恢复调用上下文所需的保存信息(例如,通过将保存的返回地址放置在程序计数器或指令计数器中,来恢复保存的寄存器值等)并释放由堆栈帧占用的任何调用堆栈存储器。
[0002]近来,一些操作系统和/或处理器已经包含了针对影子堆栈的支持。影子堆栈是一种保护过程的存储的返回地址免受恶意或无意修改的机制,诸如当调用堆栈“缓冲器溢出”导致过程在完成时返回到其正确返回地址以外的地址时(例如,在恶意代码内,而不是调用上下文)。例如,恶意行为者可能能够通过利用过程的边界检查中的缺陷,超出分配给过程的堆栈帧中的参数和/或局部变量的存储器量进行写入、以及写入过程堆栈帧中的用于存储过程的返回地址的堆栈存储器,来完成堆栈缓冲器溢出攻击。因此,恶意行为者可以使用堆栈缓冲器溢出,将过程存储的存储器地址替换为新的存储器地址(例如,在恶意行为者自己的代码内,或在从过程返回时不打算被执行的代码内)。用于线程的影子堆栈是另外的单独堆栈,它对于线程的正常调用堆栈“充当影子(shadow)”。当为应用的线程启用影子堆栈强制(enforcement)时,该应用的每个过程序言的执行导致返回地址被存储在线程的调用堆栈和线程的影子堆栈两者中。另一方面,该应用的每个过程结尾的执行导致从线程的调用堆栈和线程的影子堆栈两者中加载返回地址,然后进行比较。如果在调用堆栈与影子堆栈之间的返回地址的两个记录不同,则检测到影子堆栈违规并终止线程(或线程所属的进程)。
技术实现思路
[0003]目前,对整个线程(或进程)实施(enforce)影子堆栈违规,而不管实际触发违规的特定代码。但是,从应用二进制执行的线程频繁地执行不属于应用二进制本身的代码。例如,应用频繁地调用不属于应用部分的模块内的过程。例如,模块可以采用共享库的形式,诸如WINDOWS下的动态链接库(DLL)或LINUX下的共享对象。这些库可以是操作系统的部分,也可以由第三方提供。因此,使用现有的影子堆栈违规处理技术,如果为应用启用了影子堆栈强制,并且如果为该应用执行的线程在执行由该应用代码调用的模块期间遇到影子堆栈冲突,则整个线程(潜在地包括线程所属的整个进程)被终止。
[0004]此处描述的至少一些实施例以模块粒度而不是以整个线程(或进程)的粒度实施
影子堆栈违规。例如,当在线程的堆栈上检测到影子堆栈违规时,不是简单地终止线程(或其所属的进程),实施例包括新的附加检查以确定在执行被调用模块期间是否发生了影子堆栈违规,如果是这样,确定是否为该模块启用了影子堆栈强制。如果在执行模块期间发生影子堆栈违规,并且如果为该模块启用影子堆栈强制,则实施例继续终止线程(或线程所属的进程)。然而,如果没有为该模块启用影子堆栈强制,则一些实施例选择允许线程继续执行,而不是像典型情况那样终止线程。因此,这里的实施例决定是否以模块粒度而不是线程(或进程)粒度终止线程(或它所属的进程)。
[0005]可以理解,以模块粒度而不是典型的线程/进程粒度执行影子堆栈违规可以增加计算机系统的整体安全性,并且提高应用利用影子堆栈技术的技术能力。例如,在许多情况下,应用作者希望将应用配置为通过应用自己的代码实施执行影子堆栈违规,但允许通过在应用调用的模块内执行的代码执行影子堆栈违规。在一个示例中,应用可以调用有效篡改返回地址的模块(例如,经由面向返回的编程(ROP))。例如,应用可以在防病毒应用将代码注入应用的环境中执行,这会导致应用调用这样的模块。在另一示例中,应用可以调用非恶意触发(例如,由于错误)影子堆栈违规的模块。相对于由于与这些模块的交互而需要完全禁用此应用上的影子堆栈强制,本文的实施例在允许被调用模块代码的影子堆栈违规的同时(即,不终止应用)对应用的代码实施影子堆栈违规。通过这种方式,即使应用调用有意篡改返回地址或尚不兼容影子堆栈的外部模块,也可以为应用启用影子堆栈强制。因此,这里的实施例使得能够对应用使用影子堆栈强制——即使在由于应用所依赖的模块或由于应用执行的环境而以前不可能或不切实际的情况下。
[0006]此外,这里描述的至少一些实施例使得执行应用能够指定一个或多个存储器范围,该存储器范围存储由应用动态生成的代码,并且在动态生成的代码的执行期间应当针对该存储器范围实施影子堆栈违规。例如,这些实施例有助于在执行由管理运行时管理的即时编译代码的管理运行时(包括虚拟机运行时)的上下文中促进影子堆栈违规强制。例如,即使管理运行时的作者可以保证实现管理运行时的代码本身不会导致影子堆栈违规(从而使管理运行时有资格获得影子堆栈保护),但作者可能无法关于如下做出保证:管理运行时即时编译和在其进程/线程上下文中执行的管理代码。因此,在许多情况下,在全局启用影子堆栈强制的情况下编译管理运行时可能是不切实际的。但是,通常希望通过管理运行时管理/执行的代码来实施影子堆栈违规。使用这里的实施例,管理运行时能够指定:管理运行时向哪个存储器(多个)区域存储了动态代码(即管理代码的即时编译版本),这导致在执行此动态代码期间实施影子堆栈违规。因此,在实施例中,标识应当被实施影子堆栈违规的动态生成的可执行代码的至少部分,并且标识该动态代码已经被加载到存储器中的一个或多个地址范围(例如,虚拟地址)。当在执行此动态代码期间发生影子堆栈异常时,异常处理器确定导致异常的返回地址(例如,从影子堆栈获得)是否在识别的地址范围内。当确定返回地址在识别的地址范围内时,处理违规(例如,终止线程/进程、审核违规、根据规则忽略违规等)。
[0007]一些实施例涉及以模块粒度实施影子堆栈违规的方法、系统和计算机程序产品。线程的执行在处理器处启动。这包括启动调用外部模块的第二可执行代码的应用二进制的第一可执行代码的执行。应用二进制启用了影子堆栈强制。至少基于处理器处的线程的执行,处理异常。该异常是由从与线程对应的调用堆栈中弹出的第一返回地址和从与线程对
应的影子堆栈中弹出的第二返回地址之间的不匹配而触发的。处理异常包括确定异常是由执行外部模块的第二可执行代码中的指令引起的,以及确定外部模块是否启用了影子堆栈强制。基于已确定外部模块是否启用了影子堆栈强制,处理异常包括执行以下之一:(i)至少基于启用影子堆栈强制的外部模块,终止线程的执行,或(ii)至少基于未启用本文档来自技高网...
【技术保护点】
【技术特征摘要】
【国外来华专利技术】1.一种计算机系统,包括:处理器;以及计算机可读介质,其上存储有计算机可执行指令,所述计算机可执行指令由所述处理器可执行,以使所述计算机系统在动态代码的执行期间实施影子堆栈违规,所述计算机可执行指令包括由所述处理器可执行以使所述计算机系统至少执行以下的指令:在所述处理器处启动线程的执行,所述线程的执行包括:(i)生成用于由所述线程执行的动态代码的部分,(ii)标识所述动态代码的部分被加载到存储器中的存储器地址的范围,以及(iii)启动所述动态代码的部分的执行;至少基于所述线程在所述处理器处的执行来处理异常,所述异常是由从与所述线程对应的调用堆栈弹出的第一返回地址和从与所述线程对应的影子堆栈弹出的第二返回地址之间的不匹配触发,包括:确定从所述影子堆栈弹出的所述第二返回地址是否在所述动态代码的部分被加载的所标识的所述地址的范围内;以及基于已经确定所述第二返回地址在所述地址的范围内,启动影子堆栈强制动作。2.根据权利要求1所述的计算机系统,其中启动所述影子堆栈强制动作包括以下至少一项:(1)终止所述线程的所述执行,或者(2)记载与所述异常相关联的数据。3.根据权利要求1所述的计算机系统,其中生成用于由所述线程执行的所述动态代码的部分包括:即时编译源代码或中间语言代码中的至少一个。4.根据权利要求1所述的计算机系统,其中所述线程使用JavaScript即时编译器来生成所述动态代码的部分。5.根据权利要求1所述的计算机系统,其中所...
【专利技术属性】
技术研发人员:J,
申请(专利权)人:微软技术许可有限责任公司,
类型:发明
国别省市:
还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。