您的位置:网站首页 > Java软件 > 正文

ASLR on the Line:利用Cache Side Channel来反随

类别:Java软件 日期:2019-6-7 16:45:11 人气: 来源:

  ASLR是防御与内存有关安全漏洞的一个非常有用的措施,由于其overhead比较低,因此被广泛部署在现在的计算机系统中。如图1所示,ASLR是在程序运行时选择将数据和代码放到一个随机的,在64位机器上,其有效的虚拟地址位数一般为48位(256TB),地址的熵比较大,可以有效的防止破解ASLR。

  由于ASLR的部署,对程序的code reuse(ret-to-libc, rop等)就变的比较困难。所以一般在进行code reuse之前,会通过一定的手段(内存泄露,buffer over read)来泄露数据段或代码段的地址,从而有效的实施。但是如果没有buffer over read等漏洞,则很难泄露相关段的地址,从而很难破解ASLR防御。此文[1]利用cache的side channel来实现ASLR的derandomization,此利用了硬件特性来对ASLR进行破解,因此不需要程序有buffer over read等漏洞。

  图2是Intel处理器的内存组织结构,当执行单元(取指令)或者Load/Store单元(访问内存)时,其访问到的地址是虚拟地址,需要将虚拟地址转换成物理地址,在计算机系统中,将虚拟地址转换为物理地址的单元为MMU,其首先检查TLB(Translation Lookaside Buffer)表中是否存在需要查找的Virt Addr, 如果TLB中不存在Virt Addr到其对应的物理地址的映射,则需要进行PT Walk,具体的PT Walk会在下面具体介绍,此时只需要知道其需要查找Page Table表,而Page Table表的内容则可作为数据可能会存储在cache中。当Page Table Walk之后,就找到了Virt Addr对应的物理地址Phys Addr。首先查找cache,看cache中是否存在phys addr地址对应的内容,如果cache中不存在,则从DRAM内存中取得数据。

  需要注意的是在现在的Intel处理器中(Skylake i7-6700K),cache是分为三层的,每一层都比其下一层小,但是访问速度较快,相当于每一层都是下一层cache的缓存。区中,在第一层L1中,东哥格格又具体将数据Data和代码Code进行分开,分为L1 code和L1 data;在第二层L2和第三层L3中code和data是放在一起的。需要注意的是,L2中的内容不包含L1中的内容,即如果一个地址的数据或代码存放在L1中,其肯定不会存放在L2中,而L3中的内容即包含L1中的内容又包含L2中的内容,即如果一个地址的数据或代码在L1或者L2中,其一定存放在L3中,相反,如果一个地址的内容不在L3中,其一定也不在L1和L2中。通过此特性,可以使某个内容不在cache L3中,来确保其不在cache中,从而实现cache的side channel。

  在计算机系统中,程序所能看到的只能是虚拟地址,而真实存在的数据或者代码是存放在物理地址的,所以当程序访问某一虚拟地址va时,需要特定的硬件单元(MMU)来进行虚拟地址到物理地址pa的转换。该转换在计算机系统中是通过查找page table来完成的,该过程叫做Page Table Walk。

  图3是我从深入理解计算机系统[2]中截取的Intel i7的page table转换图,由图3可知,其虚拟地址是48位,由于每个页表是4KB(2^12B),所以低12位表示页内偏移。由于是在64位机器中,每一个PTE(page table entry)的大小是64位,即8B(2^3B),所以可用9位(2^12/2^3=2^9)表示页表中的偏移,因此可将虚拟地址划分为4级页表。首先通过CR3寄存器取出一级页表的址,再通过VPN1找到二级页表的址,如此往复,直到找到物理页的址pba, 是的pba+vpo即为要转换到的物理地址pa。

  当从虚拟地址va转换成物理地址pa之后,就可以通过物理地址pa来访问真实的数据。由于CPU处理速度远远大于DRAM的访问速度,如果直接访问DRAM,则可能造成CPU处理能力的浪费,所以在现在的计算机系统中,在CPU和DRAM之间又添加缓存,用来存储CPU最近时间内访问的数据或指令。

  图4是当今计算机系统中的cache结构,由图中可知,其将物理地址分成了3部分:块内偏移,组号和标签。每一个cache组可能由多个cache行组成,每个cache行所存储的数据大小是B=2^b字节,则块内偏移就是低b位;cache中存在S=2^s个cache组,则组号为中间s位,剩余的部分就是标签位。当要查找cache数据时,首先通过中间s为找到cache组号,在通过标签位找到其对应的cache行,再通过低b位找到对应数据。

  由前面一节介绍的基础知识我们可以知道,当MMU进行虚拟地址va到物理地址pa的转换时,首先查找TLB表,如果TLB表miss,则进行page table walk。在进行page table walk时,就是进行4级页表的访问操作。具体的例子如图5所示。

  而在当今的计算机系统中,一般都能b+s12。在Intel Skylake处理器中,其对应的b=6,s=10。

  该模型是假设者可以在被者的浏览器中执行Java代码(通过引导被者访问恶意的网站或者伪装的网站)。

  如果想要使cache side channel实施成功,则需要比较精确的Java计时器。通过Java计时器可以告诉者其访问的数据是存放在cache中还是存放在DRAM中,因为访问cache的速度远远快于访问DRAM的速度。在以往的中,一般通过Java的performance.now()函数来比较精确的获得访问DRAM和cache的时间差。而现在的浏览器一般都对side channel有了一定的防御措施,即将performance.now()函数的精度将为5us。

  由图7可知,当performance.now()精度很高时,可以在访问数据前记一下时t0,访问数据后记一下时t1,将其T=t1-t0就记为访问数据的时间,如果T与CT比较接近,则证明其访问的是cache,否则,其访问的是内存。而如果将performance.now()的精度降为5us之后,就如图7.2所示,无法分辨其访问的数据是在cache中,还是在内存中。

  在当今浏览器中,采用了SharedArrayBuffer函数来申请一个共享的Buffer,使多个线程能够共享该Buffer的数据。

  这种方法进行的timing与performance.now()的精度没有任何关系,因为它只依赖于CPU的运算速度。

  前面也提到过,如果想要进行Page Table Walks,则首先TLB缺失,即要操作的目标虚拟地址va不在TLB表中。所以需要先设计一个TLB eviction set,TLB中不存在目标虚拟地址va。由于TLB分为i-TLB和d-TLB,即数据和代码不是在一个TLB中,所以在此文[1]中,有两种方式来设计TLB eviction set。首先如果目标虚拟地址va在heap上,则通过ArrayBuffer类型来作为TLB-eviction set,由于ArrayBuffer是页对其的,因此可以有效的预测ArrayBuffer的索引与页内偏移的关系,能够比较有效的设计TLB eviction set。而如果目标虚拟地址va在代码段,则需要生成JITed代码区域。

  对于一个页表来说,其大小是4KB,每个页表项为8B(64位),假设cache line存储的数据大小是64B,则每一个cache line可以存储8个页表项,因此一个页表一共占了64个cache lines。所以可以将整个的LLC(第三层cache)按每页进行划分,一共可以划分为64种不同的颜色。

  2): 对于目标页表项来说,如果它位于页表的第t个cache行(64个中的一个),则通过读取eviction set中那些内存中相应的offset(64个中的一个)来页表项。offset是从1到64进行遍历的。

  3): 在此访问目标虚拟内存va,它的访问速度。如果它的访问速度比较慢,则说明t=offset,即offset对应的cache行与t对应的cache行一致。此时,就可得到一个页表项。使得offset从1遍历到64,则可得到4个页表项对应的cache offset。

  此时已经得到了4个页表项对应的cache offset,即得到了四个页表项的物理地址的中间s位,然而现在面临着两个问题:

  无法准确的知道每个页表项分别对应的cache offset,即无法建立四个页表项与得到的cache offset的一一映射关系。

  为了更清楚的解释这一方法,我们可以看一下图9这个例子。在图9中,设其此时的虚拟地址为v,我如果想要在Page Table Walks时访问Level 1的第501个页表项,则需要访问的虚拟地址为v+4KB;如果想要访问Level 2的第401个页表项,则需要访问的虚拟地址为2MB;如果想要访问Level 3的第301个页表项,则需要访问的虚拟地址为v+1GB;如果想要访问Level 4的第200个页表项,则需要访问的虚拟地址为v+512GB。

  由于对于PTL3和PTL4来说,相邻的页表项需要加的偏移较大(1GB和512GB),所以针对不同的浏览器内存分配策略有不同的方式进行处理。

  在Firefox中,[1]发现可以使Java分配TBs级别的虚拟内存,只要对应的需要内存页不被访问(not touched),就不会分配具体的物理内存页,因此,针对Firefox来说,可以采用反随机化PTL1和PTL2的方法来反随机化PTL3和PTL4。

  在Chrome浏览器中,当内存分配器使用mmap分配内存之后会将该内存初始化,因此分配多少虚拟内存就对应着相同的物理内存大小。因此不可能分配TBs级别的虚拟内存。[1]采取的措施是使Java申请2GB的虚拟内存,一般2GB的虚拟内存对应3个Level 3的页表项(除一些特殊的情况对应2个页表项),因此在这3个页表项进行测试。如果v对应的Level 3的页表项在cache中的偏移是7或8,则能够检测出来,否则,检测不出来。

  图10显示的分别是在Chrome和Firefox下的成功率和假阴性和假阳性的比例。其中假阴性是指当在进行sliding PT entries时没有检测到cache line发生了变化,假阳性是报告出一个错误的地址(与真实的地址v不一致)。

  由图11可知,其可以在较短的时间内解出大部分的虚拟地址位数。即使没有解出所有的位数,也降低了破解的熵值,极大地提高了破解成功的可能性。

  另该项目的具体实现作者[1]已经发布在github revanc上,但是其发布的是针对C程序ASLR的反随机化。

  检测:由于实行该需要进行大量的虚拟内存分配和cache的清空操作,在一定程度上影响了浏览器的性能,因此可以通过性能检测器来检查此类漏洞。但是此类检测被证明[1]存在假阴性和假阳性。

   文章来源于博贝棋牌850游戏

关键词:java随机4位数
0
0
0
0
0
0
0
0
下一篇:没有资料

相关阅读

网友评论 ()条 查看

姓名: 验证码: 看不清楚,换一个

推荐文章更多

热门图文更多

最新文章更多

关于联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助

郑重声明:本站资源来源网络 如果侵犯了你的利益请联系站长删除

CopyRight 2010-2012 技术支持 FXT All Rights Reserved