Reverse Engineering Page Table Caches in Your Processor
C Makefile Python C++
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

README.md

Introduction

This directory contains the source code for both anc and revanc. anc is an implementation of the ASLR^Cache (AnC) attack which is an EVICT+TIME side-channel attack on the MMU. AnC relies on the fact that page table lookups by the MMU are stored in the last level cache (LLC) in order to speed up the next required translation. By flushing parts of the LLC and timing the page table lookup, AnC can identify which parts of the LLC store page tables. On top of flushing the LLC, AnC also needs to flush the TLB as well as page table caches. Since the information on the size of the TLB and the LCC is available, the AnC attack can be used to reverse engineer the properties of the page table caches that are of interest to attackers, like their internal architecure and size. revanc is an implemention that retrofits AnC to acquire this information.

With anc, we have demonstrated that numerous x86-64, ARMv7-A and ARMv8-A microarchitectures are affected by the AnC attack. Furthermore, with revanc we have been able to detect the existence of page table caches and the amount of entries that they contain on these microarchitectures. As the code is written with portability in mind, it should be easy to add support for other potentially affected platforms that share a similar MMU design.

We invite you to visit our project page for more information.

Usage

To build the code, simply type:

make

After the code has been built, the anc and revanc programs should be available in the obj directory.

The results generated by the anc program by plotted as MMU-grams using the Python 3 script provided. As this script depends on numpy and matplotlib, these dependencies should be installed first:

sudo apt-get install python3-numpy python3-matplotlib

Then after running the anc program, the script can be run as follows:

scripts/plot.py

The script will then generate a file named mmugram.pdf.

Examples

On x86-64, the cpuid instruction is used to automatically detect the sizes of the caches and the TLBs. As such, it is often sufficient ro anc without any arguments:

./obj/anc

However, since the TLB sizes are also used as a guideline to evict the page table or translation caches, it is sometimes necessary to specify the sizes of these caches. While Intel Ivy Bridge and older microarchitectures do implement a translation cache for PDPTEs, there either is no TLB to cache 1G huge pages, or cpuid does not report its existence. As such we have to specify that this cache consists of four entries manually:

./obj/anc --pl3-entries=4

Similarly, several AMD microarchitectures implement a page table cache with 24 entries:

./obj/anc --pl2-entries=24

With the revanc program, these page table and translation caches can be reverse engineered. However, to optimise the results it is currently advised to specify the virtual address:

./obj/revanc --target=0x222e2599000 --runs=10

For ARMv7-A and ARMv8-A, the sizes of the caches and TLBs cannot be determined automatically yet. As such, it is important to specify these manually. Further, while the ARMv7-A and ARMv8-A platforms do offer Performance Monitoring Units with a register similar to the Timestamp Counter on x86-64, this is not used as it is not accessible from user mode by default. On these platforms a thread that increments a volatile global variable simulating a cycle counter is used instead. Hence it is important to take more timing samples (e.g. 100 rather than the default of 10). For instance, for the Nvidia Tegra K1 the following can be used:

./obj/revanc --target=0x10040000 --evict-target=0x80000000 --runs=10 --cache-size=4M --pl1-entries1=544 --rounds=100

Some ARMv7-A platforms have Large Physical Address Extensions enabled. If this is the case, then the arm-lpae page format has to be specified as well:

./obj/revanc --target=0x10040000 --evict-target=0x80000000 --runs=10 --cache-size=4M --pl1-entries1=544 --page-format=arm-lpae --rounds=100

On ARMv8-A another target address is recommended. For instance, for the Allwinner A64, the following can be used:

./obj/revanc --target=0x116565000 --runs=10 --cache-size=2M --pl1-entries=522 --rounds=100

Frequently Asked Questions (FAQ)

Q. What processor architectures are currently supported/affected?

The anc and revanc can currently be built for and run on the x86-64, ARMv7-A and ARMv8-A architectures and show that these architectures are affected.

Q. What operating systems are currently supported?

The code can currently be built for BSD, Linux, Mac OS X and Microsoft Windows (using MSYS 2).

Q. Does this attack work on hardened systems with ASLR enabled?

Yes, the native implementation of the attack has been reported to work on an Intel Xeon E3-1505M v5 running HardenedBSD/amd64 (thanks to Shawn Webb).

Q. Does this attack work in virtualised environments?

Yes, we have run this attack within KVM guests running Linux on an Intel Atom C2750 and an Intel Xeon E5-2658 v2. In fact, because the hypervisor makes use of the MMU as well, the page table and/or translation cache(c) used by the MMU may end up being (partially) evicted already, amplifyingthe AnC attack. However, because the MMU is used by the hypervisor as well, the revanc program cannot reliably determine the sizes of these caches.

For other questions, please refer to the project page first.