CacheKit 利用cache不一致性绕过内存监控

diting0x

听了Prof Kun Sun的报告,略作总结。

CacheKit核心思想:利用Trustzone的cahce不一致性,将恶意代码加载一块系统预留的I/O空间重定向的cache中,绕过安全世界和正常世界的监控。





几个发现

  • 1),安全世界可以访问正常世界的内存、CPU寄存器,反之则不行。但是,安全世界无法访问正常世界的cache内容
  • 2),内存空间:0x80000000-0xFFFFFFFF
    I/O空间: 0x0 -0x7FFFFFFF,其中0x1300000-0x1500000属于系统预留
  • 3),NS(non-secure)位,置零则表示在安全世界的cache,否则表示正常世界的cache。
  • 4), cache flush: 在安全世界中,不管cache lind的NS位是什么,会flush所有的cache line;而在正常世界中,只会fulsh正常世界的cache, NS=1.
  • 5),cache不一致性:同一块物理地址可以在安全世界和正常世界对应不同的cache line。
  • 6),有两种获取系统物理内存的方法,一是从处理器中获取,二是利用DMA从外设中获取;而DMA获取的方法直接获取物理内存而不会获取处理器中的cache内容

利用过程

1)将恶意代码加载到正常世界的cache中,但不加载到RAM中;

2)利用ARM cache locking机制保证恶意代码能持续存在cache中,而不会被换出 ;

3)控制物理地址空间保证恶意代码的隐蔽性。

如何做到上述的利用过程?


三个挑战

1) cache加载:在DRAM初始化前,允许让BLOS代码将栈存储在cache中(cache-as-ram CAR系统)。cacheKit利用CAR将恶意代码存储在cache中。

处理器cache的设计是为了对系统软件透明,所以ARM架构不支持在正常操作过程中直接访问cache lines,要让处理器读写cache中的内容,必须让处理器读写虚拟内存。
可以分两步进行,第一步是要让内存能够进行caching,具体细节可以参考论文4.2.1;
第二步是要让代码中的所有比特填充cache,但要避免将加载cache本身的程序代码也放进cache。

2)cache locking: 硬件支持将cache 锁住,ARMv7允许系统软件锁住八组cache中的七组。

3) cache 隐藏: 保证cachekit绕过安全世界和正常世界的监控;

  • 绕过正常世界监控:在正常世界中,当获取物理内存工具(如LiME)从处理器中读取物理内存时,获取的过程也会显示cache中的值。解决方法是利用未使用的系统I/O地址区域的cache,而取证者不会扫描这块区域,就算取证者打算扫描这块区域,也很难辨认哪个地址是安全可读的,哪些要跳过的,一不小心读到特定的硬件控制位就会导致系统停机与崩溃

  • 绕过安全世界监控:发现1)2)5)。安全世界无法访问正常世界中cache的内容。

cache隐藏细节:直接使用cache locking会带来两个问题;
第一个问题就是,直接在正常世界的kernel中做introspection,使用kernel模块将每个内存页面映射到内核地址空间仍然可以读取cache的内容;第二,cache lines被锁住以后,仍然可以clean操作将其内容写入到内存中。要解决这两个问题,就是利用系统预留内存0x1300000-0x1500000.在部署cachekit之前,这块区域是直接被MMU重定向到外设总线的;部署cachekit之后,利用cache-as-ram技术将其这块区域配置为内存空间,对这块区域所有的读写操作都被重定向到处理器的cache中。这块区域不会被任何RAM或者I/O设备所支持,不会有任何物理设备对这块区域响应。


来源

CacheKit: Evading Memory Introspection Using Cache Incoherence - ES&P’2016 Kun Sun