CN114266036A - 一种基于Intel CET机制的保护通用内存完整性的方法 - Google Patents
一种基于Intel CET机制的保护通用内存完整性的方法 Download PDFInfo
- Publication number
- CN114266036A CN114266036A CN202111430587.6A CN202111430587A CN114266036A CN 114266036 A CN114266036 A CN 114266036A CN 202111430587 A CN202111430587 A CN 202111430587A CN 114266036 A CN114266036 A CN 114266036A
- Authority
- CN
- China
- Prior art keywords
- sensitive
- written
- pointer
- code
- content
- 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.)
- Pending
Links
Images
Classifications
-
- 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
- G06F21/00—Security arrangements for protecting computers, components thereof, programs or data against unauthorised activity
- G06F21/60—Protecting data
- G06F21/64—Protecting data integrity, e.g. using checksums, certificates or signatures
Landscapes
- Engineering & Computer Science (AREA)
- Computer Security & Cryptography (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- Computer Hardware Design (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Health & Medical Sciences (AREA)
- Bioethics (AREA)
- General Health & Medical Sciences (AREA)
- Storage Device Security (AREA)
Abstract
本发明实施例提供了一种基于Intel CET机制的保护通用内存完整性的方法,该方法基于Intel CET机制来实现对通用内存完整性保护,为了与Intel CET机制兼容,且不与Intel CET机制自身维护的影子栈页相冲突,本发明设置了专用影子栈页,其独立于Intel CET机制自身维护的影子栈页,并在对写入该专用影子栈页的需要降低写入开销的待写入内容进行与之适配的降开销处理,从而降低使用WRSS指令的次数,以在使用更低开销的情况下保护敏感数据和/或敏感代码的完整性,减少处理器在保护通用内存完整性方面的性能开销,进而可以提升处理器对其他任务的处理效率。
Description
技术领域
本发明涉及计算机信息安全领域,具体来说涉及软件安全领域,更具 体地说,涉及一种基于Intel CET机制的保护通用内存完整性的方法。
背景技术
随着信息化的快速发展和计算机的大规模普及,计算机在军事、教育、 金融、科研等社会的各个方面都有广泛的应用。与此同时,计算机的安全 问题层出不穷,对国家安全、经济等造成了严重影响。例如,2001年7月 爆发的红色代码(Code Red)病毒大规模攻击了许多服务器,遭到攻击的 服务器会按照病毒的指令向政府网站发送大量数据,最终导致网站瘫痪, 给全球带来26亿美元的损失。2020年1月1日至今,微软安全应对中心 (MicrosoftSecurity Response Center,简称MSRC)共报告了37964个漏 洞(Bug),其中,有5264个严重性等级为高危的漏洞。MSRC的另一份报 告中指出,披露漏洞的CVE(CommonVulnerabilities&Exposure)字典内 每年新增的漏洞中,有70%是关于内存安全问题的漏洞。
内存安全问题中,破坏敏感内存(包括敏感数据和敏感代码)的完整 性给系统安全带来很大的威胁。
诸多抵御内存破坏攻击的防御机制能够正常工作的前提是保证其敏 感数据的完整性,如代码指针完整性机制(Code Pointer Integrity,简 称CPI机制)的安全区域和安全栈,影子栈防御机制的影子栈(shadow stack),保证C++中对象类型完整性的防御机制CFIXX的元数据等。抵御 代码注入攻击的可写与可执行互斥机制(Write XOR Execute,W^X机制) 阻止内存页同时具有写权限和执行权限。然而,广泛应用于即时编译器(Just-In-Time,简称JIT编译器)和动态二进制翻译中的动态代码生成 技术会动态生成和修改代码,并存储在代码缓存(Code Cache)中。由于 敏感代码位于代码缓存中,所以需要保护代码缓存的完整性。
进程内隔离机制是保障系统安全的重要手段,它保证了攻击者即使攻 破了用户进程,也无法执行敏感代码、访问敏感数据。基于进程内隔离的 方法是目前学术界研究的主流方向,进程内隔离的方法可以分为三种,包 括基于地址的隔离方法、基于域的隔离方法以及基于特权访问的隔离方法, 介绍如下:
1、基于地址的隔离方法。基于地址的隔离方法需要插桩每条访存指令, 约束这些指令可以访问的地址范围,确保无法访问到安全区域。纯软件的 地址隔离方法如软件错误隔离(Software Fault Isolation,简称SFI) 的技术方案中,将代码和数据分为不同的区域,每个区域的代码只能访问 相应的数据。由于SFI是用纯软件方法实现的,因此会给访存密集型的程 序带来巨大的性能开销。为了加速地址隔离方法,英特尔(Intel)推出了 内存保护扩展硬件(Memory Protection Extensions,简称MPX)以加速 边界检查,MPX允许程序员创建一组边界,用来标识地址区间的上界和下 界。通过插桩所有访存指令,并利用MPX硬件检查访存地址是否落在安全 区域内。由于基于地址隔离的方法在每条访存指令执行前都要检查其是否 访问关键数据,因此保护访存密集的程序会引入巨大的性能开销,其性能瓶颈也在于此。
2、基于域的隔离方法。基于域隔离方法的基本思想是访问安全区域前 打开安全区域的访问权限,访问完成后立即关闭访问权限,这样即使攻击 者知道了安全区域所在位置,也无法访问关键数据。而信息隐藏技术所保 护的关键数据一般都会被防御机制频繁访问,比如:代码指针完整性技术、 控制流完整性技术、影子栈技术等,这些防御机制会在函数返回、函数调 用、控制流间接跳转时访问安全区域。以SPEC CPU2006基准测试集为例,其函数调用和函数返回指令的执行频率平均约为5800万次每秒,间接跳 转指令的执行频率平均约为4300万次每秒。因此域隔离方法的性能瓶颈 是其需要频繁地切换访问权限。纯软件的域隔离方法如利用Mprotect系 统调用在访问安全区域前后修改其访问权限。由于执行一次系统调用需要 进行用户态和内核态的切换,大约需要2万个时钟周期,因此访存权限切 换频繁时会引入非常大的性能开销。
为了加速基于域隔离的方法,提高切换访问权限的速度,一些研究者 提出利用硬件辅助内存虚拟化中的扩展页表技术(Extended Page Table, 简称EPT技术)隔离安全区域。该方法设置两个扩展页表(简称EPT),一 个记录了安全区域的地址映射关系(称为安全EPT),另一个记录了非安全 区域的地址映射关系(称为非安全EPT)。然后利用英特尔提供的vmfunc 指令(约140个时钟周期)在这两个EPT之间快速切换,以达到隔离的目 的。此外,还可以利用英特尔内存保护秘钥硬件(Intel Memory Protection Keys,简称MPK)隔离安全区域。MPK可以将用户内存空间划分为16个区 域,用页表项中的4位标识该页所属区域,并新增PKRU寄存器控制各个 区域的读写权限,达到隔离的目的。
3、基于特权访问的隔离方法。还有一些研究通过在处理器中增加新的 硬件来保护安全区域。例如,一些研究者在页表项中新增1位用于标识该 页是否为敏感数据页,并扩展X86指令集,提供了专用的访存指令smov访 存敏感数据页(简称IMIX机制)。类似地,MicroStache机制也采用了类 似IMIX机制的设计思路,只不过在缓存上也做了进一步的隔离用来阻断 潜在的基于缓存的侧信道攻击。IMIX机制和MicroStache机制只需要将安 全区域所在页面设置为受保护页面,然后通过专有访存指令访问该区域, 即可实现对安全区域的保护。
综上所述,就现有工作来看,内存隔离的方法仍然存在着性能开销大 的问题,成为了阻碍其大规模部署的障碍。新增硬件的方法存在的主要问 题是没有真正的硬件支持,因此并不能立即部署到系统中保护安全区域的 完整性和机密性。
由于现有的软件实现方法性能开销较大,为了保护敏感内存,英特尔 推出了控制流强制(Control-flow Enforcement Technology)技术(简称 CET机制),包含在最新的处理器中新增的硬件影子栈机制CET.SHSTK(简 称SHSTK机制)和新增的硬件实现的针对前向边的粗粒度CFI(control flow Integrity,控制流完整性)的防御机制(简称IBT机制)。其中,SHSTK 机制是阻止ROP攻击的一种很重要且行之有效的防御机制,可以保证栈上 的返回地址不被攻击者篡改。在程序执行Call指令将返回地址压入主栈 的同时,SHSTK机制同时会将返回地址压入SSP寄存器指向的硬件影子栈 (所在页是影子栈页);程序执行Ret指令时,SHSTK机制会比较主栈和硬 件影子栈上的返回地址是否一致,不一致则抛出#GP异常。普通读指令可 以读影子栈页,普通写指令不能写影子栈页,否则会触发异常,只有WRSS指令可以写影子栈页。
但是,WRSS指令的写入开销较大,使得现有技术的隔离开销过大,而 且,由于CET机制涉及多方面的任务,直接对CET机制进行调整难以实现。
发明内容
因此,本发明的目的在于克服上述现有技术的缺陷,提供一种基于 Intel CET机制的保护通用内存完整性的方法。
本发明的目的是通过以下技术方案实现的:
根据本发明的第一方面,提供一种基于Intel CET机制的保护通用内 存完整性的方法,包括:在程序执行时,将需要保护的敏感数据和/或敏感 代码所在页设置为专用影子栈页,专用影子栈页与CET机制自身维护的影 子栈页彼此独立;在对专用影子栈页执行写操作前,对需要降低写入开销 的待写入内容进行与之适配的降开销处理;将经降开销处理的待写入内容 通过CET机制的WRSS指令写入专用影子栈页;利用所述专用影子栈页对 敏感数据和/或敏感代码的完整性进行保护。
在本发明的一些实施例中,所述对需要降低写入开销的待写入内容进 行与之适配的降开销处理的步骤包括:在待写入内容的数据量超过预定的 阈值时,对待写入内容进行无损压缩处理,其中通过利用地址空间内未被 寻址过程使用的多个比特位以降低待写入内容实际占用的内存大小。
在本发明的一些实施例中,所述需要降低写入开销的待写入内容包括 敏感指针的元数据,所述敏感指针的元数据包括敏感指针的值、其指向对 象的上界和下界;对待写入内容进行无损压缩处理的步骤包括:根据敏感 指针的元数据计算第一差值和第二差值,所述第一差值为敏感指针的值减 去其指向对象的下界得到的差值,所述第二差值为敏感指针指向对象的上 界减去敏感指针的值得到的差值;利用地址空间内未被寻址过程使用的多 个比特位以及被寻址过程使用的多个比特位保存敏感指针的值、第一差值 和第二差值。
在本发明的一些实施例中,所述将经降开销处理的待写入内容通过 CET机制的WRSS指令写入专用影子栈页的步骤包括:根据敏感指针的不同 类别,根据与该类别对应的数据写入规则将敏感指针的值、第一差值和第 二差值写入专用影子栈页中指定的比特位,并将地址空间内未被寻址过程 使用的相应比特位作为扩展类别指示位,用以记录敏感指针的类别。
在本发明的一些实施例中,所述利用所述专用影子栈页对敏感数据和 /或敏感代码的完整性进行保护的步骤还包括:在对保存在普通内存的相 应指针进行解引用前,根据对该指针备份存储在专用影子栈页中的敏感指 针的元数据判断此次解引用是否安全。
在本发明的一些实施例中,所述方法还包括:将不需要降低写入开销 的待写入内容通过CET机制的WRSS指令直接写入专用影子栈页。
在本发明的一些实施例中,所述不需要降低写入开销的待写入内容包 括用于记录虚表指针的元数据表;所述利用所述专用影子栈页对敏感数据 和/或敏感代码的完整性进行保护的步骤还包括:根据保存在普通内存的 相应虚表指针对目标函数执行间接调用前,将所述虚表指针和专用影子栈 页中元数据表内记录的虚表指针进行比较,判断此次间接调用是否安全。
在本发明的一些实施例中,所述在对专用影子栈页执行写操作前,对 需要降低写入开销的待写入内容进行与之适配的降开销处理的步骤包括: 在待写入内容的数据量小于预定的阈值时,占用预留的寄存器临时保存该 待写入内容并等待数据量小于预定的阈值的其他待写入内容存入,直到所 述预留的寄存器内的待写入内容的数据总量大于等于预定的阈值时才通 过WRSS指令执行写入。
在本发明的一些实施例中,所述待写入内容包括JIT编译器生成的机 器码,所述机器码是敏感代码;其中,所述在对专用影子栈页执行写操作 前,对需要降低写入开销的待写入内容进行与之适配的降开销处理的步骤 包括:将相应的机器码按照生成的顺序存储在预留的寄存器中,直到待写 入内容的数据总量达到预定的阈值才通过WRSS指令执行写入。
根据本发明的第二方面,提供一种基于Intel CET机制保护程序安全 性的方法,所述方法包括:获取程序源代码;利用编译器对程序源代码进 行编译,以在所述程序执行时按照第一方面所述的方法对敏感数据和/或 敏感代码的完整性进行保护。
在本发明的一些实施例中,所述利用编译器对程序源代码进行编译的 步骤包括:根据程序源代码中需要保护的敏感数据和/或敏感代码的信息, 插入相应的保护逻辑代码,以使编译好的程序在被执行时通过相应的保护 逻辑代码按照第一方面所述的方法对敏感数据和/或敏感代码的完整性进 行保护。
根据本发明的第三方面提供一种电子设备,包括:一个或多个处理器; 以及存储器,其中存储器用于存储可执行指令;所述一个或多个处理器被 配置为经由执行所述可执行指令以实现的第一方面和/或第二方面所述的 方法。
附图说明
以下参照附图对本发明实施例作进一步说明,其中:
图1为根据本发明实施例的影子栈页/专用影子栈页通过WRSS指令执 行写操作而不能被普通的写指令执行写操作的示意图;
图2为根据本发明实施例的敏感指针的元数据的原始数据结构经降开 销处理/经无损压缩处理后的数据结构;
图3为根据本发明实施例的4种不同类型的敏感指针的元数据经降开 销处理/经无损压缩处理后的数据结构;
图4为现有技术中JIT编译器对js文件进行解释执行和转变为机器 码的执行过程;
图5为根据本发明实施例的利用Intel CET技术保护敏感代码所在的 代码缓存区中将NX位置0的示意图;
图6为根据本发明实施例的修改Chakra引擎的JIT编译器以利用本 发明的保护机制执行对敏感代码的保护过程;
图7为根据本发明实施例的占用预留的寄存器临时保存该待写入内容 并等待数据量小于预定的阈值的其他待写入内容存入的示意图。
具体实施方式
为了使本发明的目的,技术方案及优点更加清楚明白,以下结合附图 通过具体实施例对本发明进一步详细说明。应当理解,此处所描述的具体 实施例仅用以解释本发明,并不用于限定本发明。
如在背景技术部分提到的,WRSS指令的写入开销较大,使得现有技术 的隔离开销过大,而且,由于Intel CET机制涉及多方面的任务,直接对 Intel CET机制进行调整难以实现。因此,本发明基于Intel CET机制来 实现对通用内存完整性保护,为了与Intel CET机制兼容,且不与Intel CET机制自身维护的影子栈页相冲突,本发明设置了专用影子栈页,其独 立于Intel CET机制自身维护的影子栈页,并在对写入该专用影子栈页的 需要降低写入开销的待写入内容进行与之适配的降开销处理,从而降低使 用WRSS指令的次数,以在使用更低开销的情况下保护敏感数据和/或敏感 代码的完整性,减少处理器在保护通用内存完整性方面的性能开销,进而 可以提升处理器对其他任务的处理效率。
在对本发明的实施例进行具体介绍之前,先对其中使用到的部分术语 作如下解释:
WRSS指令,是Intel CET技术中能修改影子栈页内容的指令。Intel CET技术可以在内存空间中为相应线程(需要被保护的线程)维护一个影 子栈,参见图1所示的内存空间,影子栈的基地址保存在SSP(Shadow Stack Pointer)寄存器中。影子栈是由影子栈页组成的。普通的写指令没有影子 栈页的写权限,WRSS指令具有影子栈页的写权限。和普通访存指令相比, WRSS指令单次写入内存的时间开销很大,具体来说,一次mov指令的执行 只需不到1个时钟周期,而一次WRSS指令大约需要12个时钟周期。WRSS 指令包括WRSSQ指令(一次写入8字节的内容)和WRSSD指令(一次写入 4字节的内容)。其中,WRSSQ指令将源寄存器中的8字节内容写入目的影 子栈页中,且目的地址必须是8字节对齐的;WRSSD指令将源寄存器中的 4字节内容写入目的影子栈页中,且目的地址必须是4字节对齐的。WRSSD 指令写入4字节的开销和WRSSQ指令写入8字节的开销相当。相比之下, WRSSQ指令更高效。因此,以下具体的实施例中使用WRSSQ指令作为示例。 但应当理解,在一些情况下,本领域技术人员也可采用WRSSD指令,进行 相应调整,从而实现本发明。
指针解引用,是指引用该指针指向的对象的值。例如,引用某个地址 存储的变量的值。
根据本发明的一个实施例,为了兼容和避免冲突,本发明在Intel CET 机制(一些地方也简称CET机制)维护的影子栈页之外设置保护敏感数据 和/或敏感代码的专用影子栈页(“专用”一词是为了区别于Intel CET机 制自身维护的影子栈页,专用影子栈页也属于影子栈页);WRSS指令既能 对Intel CET机制维护的影子栈页进行操作,也能对专用影子栈页进行操 作;为了降低写入开销,会区分不同的待写入内容并进行相应的写入处理:
如果是不需要降低写入开销的待写入内容,则直接通过WRSS指令将 待写入内容写入专用影子栈页;
如果是需要降低写入开销的待写入内容,并且待写入内容的数据量超 过预定的阈值,则对待写入内容进行无损压缩处理后,通过WRSS指令写 入专用影子栈页;
如果是需要降低写入开销的待写入内容,并且待写入内容的数据量小 于预定的阈值,则将待写入内容的数据量累积到预定的阈值时,通过WRSS 指令写入专用影子栈页。
根据本发明的一个实施例,如果实施者新编写程序,实施者可以在编 程时根据本发明的方案编写对程序中特定的敏感数据和/或敏感代码的保 护逻辑,以通过专用影子栈页来实现低开销的保护机制。
根据本发明的一个实施例,如果实施者已经编写好程序,但是编写好 的程序中并不是通过影子栈页来保护敏感数据和/或敏感代码,编程者可 以通过编译器在对程序进行优化时按照预设的调整逻辑将程序中原有的 保护机制的保护逻辑改为以本发明的保护逻辑来实现,从而节省时间和精 力。为了直观,以下实施例主要从通过编译器调整程序中原有的保护机制 的保护逻辑角度进行说明,但应当理解,以下实施例仅为示意性的,本领 域还有很多其他的实现方式,不一一枚举。
对于保护通用内存完整性,主要包含保护敏感数据和保护敏感代码两 个方面,以下分别从这两个方面对本发明的技术方案进行说明:
一、保护敏感数据
保护敏感数据的实施例中以LLVM编译器为例,示意通过LLVM编译器 来调整程序中原有的保护机制,转变为本发明的保护机制的过程。 LLVM(Low Level VirtualMachine)编译器(框架)是一套模块化、可重用 的编译器以及工具链技术的集合。LLVM编译器的大部分逻辑都在处理编译 优化和代码生成,这些功能由一个或者多个中间优化过程(即:Pass,一 些文献将“一个Pass”称为“一趟”)构成。为了调整原有的保护机制, 可以将LLVM编译器作为底层框架,通过在LLVM编译器的中端添加CETIS (即CET-based memoryIsolation Technology,为本发明的保护机制的 简写)Pass,实现对敏感数据的保护,可以阻止攻击者破坏敏感数据的完 整性。下面以CFIXX防御机制和CPI机制为例,展示本发明的CETIS机制 如何与这些防御机制结合,低开销地实现内存完整性保护。
(1)以保护CFIXX防御机制中的敏感数据为例,对不需要降低写入 开销的待写入内容的情形进行说明
C++是从C语言发展而来的一种编程语言。C++可以进行C语言的过程 化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计, 还可以进行以继承和多态为特点的面向对象的程序设计。其中,通过虚表 实现的动态分配是C++中多态的核心,这使得子类可以重写继承自父类的 虚函数。在C++中,每一个多态类都有一个或多个虚表,虚表中包括该类 所有虚函数的函数指针。虚表通过类对象的第一个域虚表指针索引,虚表 指针在类对象的构造函数中初始化。动态分配利用虚表指针标识对象的底 层类型(UnderlyingType)。在每一个虚函数调用点,程序首先通过对象 所属类的虚表指针在虚表中找到目标虚函数指针,然后通过间接调用执行 目标函数。虚表位于只读的内存区域(Rodata段),而虚表指针存储在可 读可写的内存区域,因此如果攻击者利用程序漏洞篡改了虚表指针,则可 以发动控制流劫持攻击,如伪造面向对象编程(Counterfeit Object OrientedProgramming,简称COOP)攻击等。
为了抵御上述攻击,需要保证C++程序的对象类型完整性(Object TypeIntegrity,简称OTI),换言之,即保证虚表指针的完整性。CFIXX 防御机制保证了对象的虚表指针在运行时不被攻击者篡改,具体做法是, 通过修改LLVM编译器,使得程序在运行时将虚表指针的备份保存在元数 据表中,并通过地址隔离的方法保证元数据表的完整性。
根据本发明的一个实施例,本发明在CFIXX防御机制的基础上,在LLVM 编译器中添加一个中间优化过程(Pass,一些文献也称为“一趟”),该中 间优化过程根据原有的CFIXX防御机制中的保护逻辑生成利用专用影子栈 页进行保护的逻辑,其中,通过修改C++程序中用于备份虚表指针的元数 据表的分配和保存部分,将该元数据表的保存位置设置为专用影子栈页, 并修改为利用WRSSQ指令将虚表指针写入专用影子栈页处的元数据表中, 弃用原有的CFIXX防御机制中的保护逻辑(比如,通过删除原CFIXX防御 机制的实现代码)。而原有的CFIXX防御机制每次将8字节的虚表指针写 入元数据表,因此,可以直接将此处的待写入内容(虚表指针)设为不需 要降低写入开销的待写入内容,用CET机制的WRSSQ指令直接写入专用影 子栈页。程序执行时,根据保存在普通内存的相应虚表指针对目标函数执 行间接调用前,比较普通内存中的所述虚表指针与专用影子栈页中元数据 表内记录的虚表指针的一致性,如果一致,则此次间接调用是安全的,则 继续执行,如果不一致,则此次间接调用是不安全的,则抛出异常并停止 执行。调整后,可以利用本发明的防御机制实现原有的CFIXX防御机制的 保护功能,但调整后程序执行时实现本发明的防御机制的开销更小。
(2)代码指针完整性机制(简称CPI机制)也是保证敏感数据的完整 性的一种机制,接下来说明本发明是如何保护代码指针完整性(简称CPI) 的,同时,也是对需要降低写入开销的待写入内容,并且待写入内容的数 据量超过预定的阈值的情形的说明。
CPI机制旨在保护敏感指针的完整性,阻止攻击者篡改敏感指针,从 而阻止发动控制流劫持攻击。在CPI中,敏感指针的定义是递归的,即包 括所有代码指针(比如:函数指针、返回地址等)以及可以用来访问敏感 指针的指针。CPI中的敏感数据分为两部分,一部分是安全栈(Safe Stack), 其用于存放返回地址的值和通过静态分析能够证明是安全的对象,不安全 的对象存储在不安全栈(Unsafe Stack)中,在CPI的实现中,将程序主 栈设置成了安全栈;另一部分是安全指针存储区(Safe Pointer Store), 用于存储除返回地址之外的敏感指针的元数据,参见图2a,包括敏感指 针的值value,以及其指向对象的上界upper和下界lower。指针解引用 前,根据安全指针存储区中的敏感指针的元数据判断此次解引用是否安全 (即,对于代码指针来说判断其是否被篡改,对于数据指针来说判断其访问目标是否越界)。
根据本发明的一个实施例,本发明通过修改LLVM编译器,利用CET机 制替代安全栈保护程序中的返回地址不被篡改;同时,将安全指针存储区 所在的页设置为专用影子栈页,即将敏感指针的元数据存储在专用影子栈 页。以X86_64处理器为例,每个敏感指针的元数据(value,upper,lower) 为24字节,直接用WRSSQ指令需要分3次写入专用影子栈页,会增加隔 离的性能开销。而在现有技术中,8字节的地址空间中的48-63比特位是 未被寻址过程使用的,为此,本发明借助这些未被寻址过程使用的比特位, 采用一种无损压缩元数据的方式,将每次写入敏感内存的数据量降到最低。 根据本发明的一个实施例,参见图2b,将24字节压缩到16字节,压缩 后的数据结构(或者称Compress_val结构)见图2c。其中,由于目前的 X86_64处理器中可以索引248字节地址空间,用户空间的指针的低48位是 有效的,高16位全为0,因此Compress_val结构中的低48位(0-47位) 用来存储敏感指针的值(Value),其余位主要用于存储第一差值Offset1 (48-54位)和第二差值Offset2(55-61位)。其中,第一差值offset1 的值等于敏感指针的值Value减去敏感指针指向对象的下界Lower,第二 差值Offset2的值等于敏感指针指向对象的上界upper减去敏感指针的值Value。在本发明中,大于等于128字节的对象被称为“大对象”,小于128 字节的对象被称为“小对象”。Compress_val结构的62到63为Extend位 (即扩展类别指示位),用来标识该元数据对应敏感指针的类别:当 Extend=1时,表示该敏感指针为代码指针;当Extend=2时,表示该敏感 指针是指向小对象的数据指针(Offset1和Offset2均可以用7位编码); 当Extend=3时,表示该敏感指针是指向大对象的数据指针;当Extend=0 时,表示该敏感指针已经被释放。
根据本发明的一个实施例,不同类别的指针可以有不同的元数据压缩 策略,参见图3a-图3d,给出了对4种不同类别的指针的元数据的压缩 策略下对地址空间的示意性的利用方案,灰色区域为实际使用的区域。其 中,从图3a中可以看到,代码指针只需要存储指针的值(只需8字节), 只需利用低8字节地址中的部分比特位即可,压缩后只需使用WRSSQ指令 执行一次写操作。图3b中,指向小对象的数据指针存储指针的值Value 和两个Offset,由于是指向小对象的数据指针,第一差值Offset1或第二 差值Offset2的最大值也仅占用7个比特位,由于Extend位仅占用2个 比特位,低8字节中的48-61位刚好可以存储两个Offset。因此,指向小 对象的数据指针仅需使用8字节,压缩后只需使用WRSSQ指令执行一次写 操作。图3c中,指向大对象的数据指针由于48到61位无法存储两个 Offset,因此需要额外的8字节用于写入Offset,因此,使用16字节中 的高8字节用于存储两个Offset(例如64-95位存储Offset1,96位-127 位存储Offset2),原来的24字节则可以压缩到16字节,压缩后使用WRSSQ 指令执行两次写操作。当指针释放时,只需将低8字节中的Extend位置0。可见,在上述压缩元数据的策略下,只有指向大对象的数据指针需要写 入16字节,其余情况下均只需要写入8字节即可,最大限度地降低了更 新安全区域的性能开销。指针解引用时,本发明根据Extend值,按照相对 应的压缩策略将指针的元数据解压出来,再利用CPI原有的检查逻辑检查 指针是否合法。即在对保存在普通内存的相应指针进行解引用前,根据对 该指针备份存储在专用影子栈页中的敏感指针的元数据判断此次解引用 是否安全,若否,则抛出异常并停止执行,若是,则对指针进行解引用。
二、保护敏感代码
除了保护敏感数据,本发明还可以保护敏感代码的完整性。以下借助 保护敏感代码的完整性的实施例来对需要降低写入开销的待写入内容,并 且待写入内容的数据量小于预定的阈值的情形进行说明。
JavaScript引擎的性能对整个浏览器的影响至关重要,JIT(Just-In- Time)编译优化是为了提高JavaScript引擎的性能。如图4所示,JS引 擎中的解析器会首先将输入的js文件解析为字节码,并通过解释器解释 执行。当在循环语句中反复执行同一段脚本代码时,如果解释器反复执行 相关的字节码,效率会很低。JIT编译器可以将源代码直接生成机器指令, 在下一次执行时直接执行机器指令。只有当目标函数或者循环语句被频繁 调用时才会启用JIT编译,JIT编译后生成了相应的机器指令,作为本地 代码(Native code)存储在内存空间,这部分存储本地代码的内存空间称 之为代码缓存区(Code Cache),下一次调用到这个语句或是函数时就会直 接执行机器码(机器指令)。一旦JIT生成完成,程序就可以直接调用JIT 生成的机器码。
字节码是在受限的虚拟机环境中解释执行的,而代码缓存区内的机器 码是由本地的处理器直接执行的,因此JIT编译器限制了发射的代码缓存 的能力,例如,JIT编译器不会发射潜在的危险指令如系统调用指令等。 由于JIT编译器需要将生成的机器码写入内存,因此最直接的方法是将机 器码所在页设置为可读可写可执行的页面,如JavaScriptCore引擎在 Intel处理器下的实现。但这样做打破了W^X策略,使得代码缓存区很容 易成为攻击者的目标,因此一些引擎采用基于mprotect()系统调用的域隔 离方法保护代码缓存区不被攻击者篡改,即发射时先将代码缓存区设置为 可读可写,发射完毕后再将代码缓存区的权限设置为可读可执行,如 JavaScriptCore引擎在ARM处理器下的实现以及Chakra等。为了降低频 繁调用mprotect()系统的性能开销,JavaScript引擎会将JIT编译器产 生的机器码先存储到缓冲器(Buffer)中,生成完毕后使用内存拷贝函数 memcpy()一次性将缓冲器中的机器码拷贝到代码缓存区中。
对于一些敏感代码,本发明可以设置专用影子栈页进行保护,不在普 通内存存储该敏感代码,只需要将存储敏感代码的页设置为可执行的专用 影子栈页,进而达到保护的目的。根据本发明的一个实施例,本发明利用 Intel CET技术保护敏感代码所在的代码缓存区,将存储敏感代码的专用 影子栈页对应的页表项中NX位置0,使得敏感代码所在页是具有可执行权 限的影子栈页。Intel CET技术中的影子栈页面是只读的脏页,其页表项 的属性如图5所示:脏位D置1,读写位R/W置0。由于页表项中NX位 (用于指示该页是否为不可执行的页,0为可执行的页,1为不可执行的 页)和读写位以及脏位是分离的,所以可以将代码缓存区所在页面对应的 页表项中NX位置0,使得代码缓存区所在页是具有可执行权限的影子栈 页。
根据本发明的一个实施例,以Chakra引擎为例,本发明可以部署在 Chakra引擎上。Chakra引擎是一个由微软为Microsoft Edge浏览器开发 的JavaScript引擎。Chakra引擎在一个独立的CPU核心上即时编译脚本, 与浏览器并行。Chakra引擎在生成代码缓存区前后会通过mprotect()系 统调用开关代码缓存区的写权限,使其不会同时具备可写和可执行权限。 由于缓冲器(Buffer)缓存了JIT编译器产生的机器码,且所在页面是可 读可写的,攻击者还可以通过篡改Chakra引擎中的缓冲器达到间接篡改 代码缓存区的效果。为了抵御针对缓冲器的攻击,Chakra引擎对缓冲器加 强了保护,如图4所示,Chakra引擎的JIT编译器在将每条IR编译成机 器码存入缓冲器时,对机器码逐字节计算校验码(Checksum),在执行 memcpy()操作后,对代码缓存区中的机器码逐字节重新计算校验码,并将 计算的校验码与之前的校验码进行比对,通过后才会使用代码缓存区中的 机器码,否则报错。
根据本发明的一个实施例,参见图6,本发明修改了Chakra引擎的 JIT编译器,将保存敏感代码的代码缓存区所在页设置为可执行的专用影 子栈页。同时抛弃了Chakra引擎原有的缓冲器及校验流程,利用WRSSQ指 令将编译好的机器码直接写入代码缓存区。然而,JIT编译器每次生成的 代码片段长度不一且通常较短,由于WRSSQ指令每次必须向8字节对齐的 目的地址写入8字节,所以将连续生成的小字节数据写代码缓存区时需要 执行多次WRSSQ指令。例如,JIT编译器连续生成了4字节/2字节/2字节 代码,顺序写入代码缓存区中需要进行如下操作(假设4字节代码的目的 地址是0x1000,该地址是8字节对齐的):
①从地址为0x1004的内存中读取4个字节,与待写入的4字节代码 进行拼接,然后利用WRSSQ指令将这8字节内容写入地址为0x1000的代 码缓存区中;
②从0x1000和0x1006中分别读取4字节和2字节,并和待写入的2 字节进行拼接,然后利用WRSSQ指令将这8字节内容写入地址为0x1000 的代码缓存区中;
③从0x1000中读取6字节,并和待写入的2字节进行拼接,然后利 用WRSSQ指令将这8字节内容写入地址为0x1000的代码缓存区中。
以上写操作需要执行3次WRSSQ指令,为了进一步提升性能,本发明 提出了寄存器即缓冲器(Register-as-buffer)技术。根据本发明的一个 示例,如图7所示,本发明利用寄存器作为缓冲器,将较短的代码片段暂 存到XMM寄存器当中(该寄存器被可以被CETIS设置为保留,仅用于存储 代码片段),当寄存器内容达到8字节时才使用WRSSQ指令将代码片段写 入代码缓存区中;其中,使用第一索引标记index1指向尚未提交到代码 缓存区中的代码,使用第二索引标记index2标记当前可以写入的位置, 从而实现代码片段的有序提交。在该示例中,利用这种寄存器即缓冲器技 术,可以将WRSSQ指令的执行次数由3次变为1次,大大减少了WRSSQ指 令的执行次数,提高了CETIS的性能。为了保证XMM寄存器和内存的一致 性,读取代码缓存区的内容前需要执行刷新操作,将XMM寄存器中的内容 同步至内存中。此外,除了使用XMM寄存器作为缓冲寄存器,其他通用寄 存器也可以用做缓冲寄存器,如%R14,%R15等。该实施例的技术方案至少 能够实现以下有益技术效果:由于本发明不需要计算校验码、核对校验码 以及进行memcpy操作,提升了保护代码缓存区完整性的效率。
根据本发明的一个实施例,提供一种基于Intel CET机制保护程序安 全性的方法,包括:获取程序源代码;利用编译器对程序源代码进行编译, 以在所述程序执行时按照基于Intel CET机制的保护通用内存完整性的方 法对敏感数据和/或敏感代码的完整性进行保护。优选的,所述利用编译器 对程序源代码进行编译的步骤包括:根据程序源代码中需要保护的敏感数 据和/或敏感代码的信息,插入相应的保护逻辑代码,以使编译好的程序在 被执行时通过相应的保护逻辑代码按照基于Intel CET机制的保护通用内 存完整性的方法对敏感数据和/或敏感代码的完整性进行保护。优选的,需 要保护的敏感数据和/或敏感代码的信息可以是指定的敏感数据和/或敏 感代码的指针或者指针范围,由编译器根据敏感数据和/或敏感代码的指 针或者指针范围在程序中插入相应的保护逻辑代码。或者,程序源代码中 可以有按照原有的保护机制对应的保护逻辑代码,在这种情况下,原有的 保护机制对应的逻辑代码则记录了需要保护的敏感数据和/或敏感代码的 信息。优选的,基于Intel CET机制保护程序安全性的方法包括:根据程 序源代码中保护敏感数据和/或敏感代码的原有的保护机制(如CPI、CFIXX 等)对应的逻辑代码,插入相应的保护逻辑代码并且删除原有的保护机制 对应的逻辑代码,以使编译好的程序在被执行时通过相应的保护逻辑代码 按照基于Intel CET机制的保护通用内存完整性的方法对敏感数据和/或敏感代码的完整性进行保护。
需要说明的是,虽然上文按照特定顺序描述了各个步骤,但是并不意 味着必须按照上述特定顺序来执行各个步骤,实际上,这些步骤中的一些 可以并发执行,甚至改变顺序,只要能够实现所需要的功能即可。
本发明可以是系统、方法和/或计算机程序产品。计算机程序产品可以 包括计算机可读存储介质,其上载有用于使处理器实现本发明的各个方面 的计算机可读程序指令。
计算机可读存储介质可以是保持和存储由指令执行设备使用的指令 的有形设备。计算机可读存储介质例如可以包括但不限于电存储设备、磁 存储设备、光存储设备、电磁存储设备、半导体存储设备或者上述的任意 合适的组合。计算机可读存储介质的更具体的例子(非穷举的列表)包括: 便携式计算机盘、硬盘、随机存取存储器(RAM)、只读存储器(ROM)、可 擦式可编程只读存储器(EPROM或闪存)、静态随机存取存储器(SRAM)、 便携式压缩盘只读存储器(CD-ROM)、数字多功能盘(DVD)、记忆棒、软盘、 机械编码设备、例如其上存储有指令的打孔卡或凹槽内凸起结构、以及上 述的任意合适的组合。
以上已经描述了本发明的各实施例,上述说明是示例性的,并非穷尽 性的,并且也不限于所披露的各实施例。在不偏离所说明的各实施例的范 围和精神的情况下,对于本技术领域的普通技术人员来说许多修改和变更 都是显而易见的。本文中所用术语的选择,旨在最好地解释各实施例的原 理、实际应用或对市场中的技术改进,或者使本技术领域的其它普通技术 人员能理解本文披露的各实施例。
Claims (12)
1.一种基于Intel CET机制的保护通用内存完整性的方法,其特征在于,包括:
在程序执行时,将需要保护的敏感数据和/或敏感代码所在页设置为专用影子栈页,专用影子栈页与CET机制自身维护的影子栈页彼此独立;
在对专用影子栈页执行写操作前,对需要降低写入开销的待写入内容进行与之适配的降开销处理;
将经降开销处理的待写入内容通过CET机制的WRSS指令写入专用影子栈页;
利用所述专用影子栈页对敏感数据和/或敏感代码的完整性进行保护。
2.根据权利要求1所述的方法,其特征在于,所述对需要降低写入开销的待写入内容进行与之适配的降开销处理的步骤包括:
在待写入内容的数据量超过预定的阈值时,对待写入内容进行无损压缩处理,其中通过利用地址空间内未被寻址过程使用的多个比特位以降低待写入内容实际占用的内存大小。
3.根据权利要求2所述的方法,其特征在于,所述需要降低写入开销的待写入内容包括敏感指针的元数据,所述敏感指针的元数据包括敏感指针的值、其指向对象的上界和下界;
对待写入内容进行无损压缩处理的步骤包括:
根据敏感指针的元数据计算第一差值和第二差值,所述第一差值为敏感指针的值减去其指向对象的下界得到的差值,所述第二差值为敏感指针指向对象的上界减去敏感指针的值得到的差值;
利用地址空间内未被寻址过程使用的多个比特位以及被寻址过程使用的多个比特位保存敏感指针的值、第一差值和第二差值。
4.根据权利要求3所述的方法,其特征在于,所述将经降开销处理的待写入内容通过CET机制的WRSS指令写入专用影子栈页的步骤包括:
根据敏感指针的不同类别,根据与该类别对应的数据写入规则将敏感指针的值、第一差值和第二差值写入专用影子栈页中指定的比特位,并将地址空间内未被寻址过程使用的相应比特位作为扩展类别指示位,用以记录敏感指针的类别。
5.根据权利要求4所述的方法,其特征在于,所述利用所述专用影子栈页对敏感数据和/或敏感代码的完整性进行保护的步骤还包括:
在对保存在普通内存的相应指针进行解引用前,根据对该指针备份存储在专用影子栈页中的敏感指针的元数据判断此次解引用是否安全。
6.根据权利要求1-5之一所述的方法,其特征在于,所述方法还包括:
将不需要降低写入开销的待写入内容通过CET机制的WRSS指令直接写入专用影子栈页。
7.根据权利要求6所述的方法,其特征在于,所述不需要降低写入开销的待写入内容包括用于记录虚表指针的元数据表;
所述利用所述专用影子栈页对敏感数据和/或敏感代码的完整性进行保护的步骤还包括:
根据保存在普通内存的相应虚表指针对目标函数执行间接调用前,将所述虚表指针和专用影子栈页中元数据表内记录的虚表指针进行比较,判断此次间接调用是否安全。
8.根据权利要求1所述的方法,其特征在于,所述在对专用影子栈页执行写操作前,对需要降低写入开销的待写入内容进行与之适配的降开销处理的步骤包括:
在待写入内容的数据量小于预定的阈值时,占用预留的寄存器临时保存该待写入内容并等待数据量小于预定的阈值的其他待写入内容存入,直到所述预留的寄存器内的待写入内容的数据总量大于等于预定的阈值时才通过WRSS指令执行写入。
9.根据权利要求8所述的方法,其特征在于,所述待写入内容包括JIT编译器生成的机器码,所述机器码是敏感代码;
其中,所述在对专用影子栈页执行写操作前,对需要降低写入开销的待写入内容进行与之适配的降开销处理的步骤包括:
将相应的机器码按照生成的顺序存储在预留的寄存器中,直到待写入内容的数据总量达到预定的阈值才通过WRSS指令执行写入。
10.一种基于Intel CET机制保护程序安全性的方法,其特征在于,所述方法包括:
获取程序源代码;
利用编译器对程序源代码进行编译,以在所述程序执行时按照权利要求1-9之一所述的方法对敏感数据和/或敏感代码的完整性进行保护。
11.根据权利要求10所述的基于Intel CET机制保护程序安全性的方法,其特征在于,所述利用编译器对程序源代码进行编译的步骤包括:
根据程序源代码中需要保护的敏感数据和/或敏感代码的信息,插入相应的保护逻辑代码,以使编译好的程序在被执行时通过相应的保护逻辑代码按照权利要求1-9之一所述的方法对敏感数据和/或敏感代码的完整性进行保护。
12.一种电子设备,其特征在于,包括:
一个或多个处理器;以及
存储器,其中存储器用于存储可执行指令;
所述一个或多个处理器被配置为经由执行所述可执行指令以实现权利要求1至11中任一项所述的方法。
Priority Applications (2)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202111430587.6A CN114266036A (zh) | 2021-11-29 | 2021-11-29 | 一种基于Intel CET机制的保护通用内存完整性的方法 |
PCT/CN2022/126374 WO2023093385A1 (zh) | 2021-11-29 | 2022-10-20 | 一种基于cet机制的保护通用内存完整性的方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202111430587.6A CN114266036A (zh) | 2021-11-29 | 2021-11-29 | 一种基于Intel CET机制的保护通用内存完整性的方法 |
Publications (1)
Publication Number | Publication Date |
---|---|
CN114266036A true CN114266036A (zh) | 2022-04-01 |
Family
ID=80825752
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202111430587.6A Pending CN114266036A (zh) | 2021-11-29 | 2021-11-29 | 一种基于Intel CET机制的保护通用内存完整性的方法 |
Country Status (2)
Country | Link |
---|---|
CN (1) | CN114266036A (zh) |
WO (1) | WO2023093385A1 (zh) |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
WO2023093385A1 (zh) * | 2021-11-29 | 2023-06-01 | 中国科学院计算技术研究所 | 一种基于cet机制的保护通用内存完整性的方法 |
Family Cites Families (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US20160381050A1 (en) * | 2015-06-26 | 2016-12-29 | Intel Corporation | Processors, methods, systems, and instructions to protect shadow stacks |
CN109359487B (zh) * | 2018-10-09 | 2022-02-18 | 湖北文理学院 | 一种基于硬件隔离的可扩展安全影子存储及标签管理方法 |
CN112256357B (zh) * | 2020-10-19 | 2023-03-24 | 海光信息技术股份有限公司 | 数据保护系统、方法和计算机可读介质 |
CN112579988B (zh) * | 2020-12-10 | 2022-12-06 | 海光信息技术股份有限公司 | 影子栈数据完整性保护方法、装置和计算机设备 |
CN114266036A (zh) * | 2021-11-29 | 2022-04-01 | 中国科学院计算技术研究所 | 一种基于Intel CET机制的保护通用内存完整性的方法 |
-
2021
- 2021-11-29 CN CN202111430587.6A patent/CN114266036A/zh active Pending
-
2022
- 2022-10-20 WO PCT/CN2022/126374 patent/WO2023093385A1/zh unknown
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
WO2023093385A1 (zh) * | 2021-11-29 | 2023-06-01 | 中国科学院计算技术研究所 | 一种基于cet机制的保护通用内存完整性的方法 |
Also Published As
Publication number | Publication date |
---|---|
WO2023093385A1 (zh) | 2023-06-01 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
Duck et al. | Stack Bounds Protection with Low Fat Pointers. | |
CN108090346B (zh) | 一种基于数据流监控的代码复用攻击防御方法及系统 | |
CN109918903B (zh) | 一种基于llvm编译器的程序非控制数据攻击防护方法 | |
Suh et al. | Secure program execution via dynamic information flow tracking | |
KR102617102B1 (ko) | 서명 바운디드 포인터를 생성하기 위한 장치 및 방법 | |
US9483419B2 (en) | Apparatus and method for handling page protection faults in a computing system | |
Volckaert et al. | Cloning your gadgets: Complete ROP attack immunity with multi-variant execution | |
Suh et al. | CSAIL | |
KR102649092B1 (ko) | 바운디드 포인터의 사용을 제어하기 위한 장치 및 방법 | |
Crandall et al. | Minos: Architectural support for protecting control data | |
US7506096B1 (en) | Memory segment emulation model for virtual machine | |
JP2021512400A (ja) | メモリ・アクセスにおける保護タグ・チェックの制御 | |
JP2023038361A (ja) | 命令セット内の変更を制御する装置及び方法 | |
CN114902178A (zh) | 域转换禁用配置参数 | |
CN115510430A (zh) | 一种函数指针及其数据依赖的识别与保护方法、装置 | |
Xie et al. | CETIS: Retrofitting Intel CET for generic and efficient intra-process memory isolation | |
WO2023093385A1 (zh) | 一种基于cet机制的保护通用内存完整性的方法 | |
US20230236925A1 (en) | Tag checking apparatus and method | |
Wu et al. | Dancing with wolves: An intra-process isolation technique with privileged hardware | |
Mustafa et al. | Seeds of SEED: New security challenges for persistent memory | |
JP7349437B2 (ja) | メモリ・アクセスにおける保護タグ・チェックの制御 | |
Hiser et al. | Meds: The memory error detection system | |
Lei et al. | Put your memory in order: Efficient domain-based memory isolation for wasm applications | |
De et al. | HeapSafe: securing unprotected heaps in RISC-V | |
Zhang et al. | Stateful forward-edge CFI enforcement with Intel MPX |
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 |