本文介绍了如何找出Intel处理器上的指令触及了哪条缓存行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了文章



在这种情况下,X为84。






C#中的伪代码显示了完整的过程:

 公共不安全字节LeakByte(IntPtr kernelAddress)
{
const in t PAGE_SIZE = 4096;

//创建探针数组
byte [] probeArray = new byte [256 * PAGE_SIZE];

//清除现金
Processor.ClearL1Cache();

尝试
{
//运动,字节[rcx]
//这将引发异常,因为我们访问非法内存
字节密码= *((byte *)kernelAddress.ToPointer());

//注意,尽管前一行在逻辑上是
//引发异常,但是
//下面的代码仍在处理器内部内部
//之前执行例外是
//实际上触发了

//尽管执行了以下几行,但在$ b $时,处理器将丢弃对变量的任何赋值
// b //然后实际抛出异常。

// shl rax,0xc
int pageOffset = secret * PAGE_SIZE;

//移动rbx,qword [rbx + rax]
//将带有数字密钥的页面移到L1缓存中。
int temp = probeArray [pageOffset];
}
catch
{
//忽略异常
}

//现在测量访问页面的时间
int bestTime = int.MaxValue;
字节bestPage = 0;

for(int i = 0; i {
int startTime = DateTime.NowInNanoSeconds;
int temp = probeArray [i * PAGE_SIZE];
int endTime = DateTime.NowInNanoSeconds;

int timeTaken = endTime-startTime;
if(timeTaken< bestTime)
{
bestTime = timeTaken;
bestPage =(byte)i;
}

}

//最快的页面是从Cache加载的,是泄露的秘密
返回bestPage;
}


I read the article about the Meltdown/Spectre exploit that allow reading privileged data from the kernel using hardware bugs in the CPU. It says:

Can someone explain how is this Flush+Reload magic is done and how can it reveal the touched cache line?

解决方案

// Further down, there is pseudocode in C# that shows the complete process.

We have a kernel address rcx which is the address of one byte (let's call the value of that byte "X") in kernel memory space that we want to leak. The currently running user process is not allowed to access this address. An exception will be thrown when doing so.

We have the probe array with the size 256 * 4096 bytes in user space which we can freely access. So, this is just some normal array which is exactly 256 pages long. The size of one page is 4096 bytes.

First, a flush operation is executed (First part of "Flush+Reload"). This tells the processor to completely clear the L1 cache. So, no memory page is cached in the L1 cache. (We don't see that in the code in the OP)

Then we execute the code mentioned in the OP.

mov al, byte [rcx]

We read the byte value X at the kernel address that we want to leak and store it in the rax register. This instruction will trigger an exception because we are not allowed to access this memory address from user level code.

However, because the test whether we are allowed to access this address takes some time, the processor will already start executing the following statements. So, we have the byte value X that we want to know stored in the rax register for these statements.

shl rax, 0xc

We multiply this secret value X with 4096 (The page size).

mov rbx, qword [rbx + rax]

Now we add the calculated value in the rax register to the start of our probe array and get an address that points into the Xth page within the memory space that makes up our probe array.

Then we access the data at that address, which means that the Xth page of the probe array is loaded into the L1 cache.

Now, the L1 cache is empty (because we have cleared it before explicitly) except for two pages that are in the cache:

  1. The page within Kernel memory that contains X (But that we can still not access)
  2. The Xth. page within our probe array

Now, the second part of "Flush+Reload" begins. One after the other, we read each page in the probe array, measuring the time that takes. So, altogether, we load 256 pages. 255 of these page loads will be rather slow (because the associated memory is not in the L1 cache yet), but one load (that of the Xth page) will be quite fast (because it was in the L1 cache before).

Now, because we find that loading the Xth page was fastest, we know that X is the value that is at the kernel address that we wanted to leak.

From the meltdown paper, this is the graphic showing the time measurements of loading the pages within the probe array:

In this case, X was 84.


Pseudocode in C# that shows the complete process:

public unsafe byte LeakByte(IntPtr kernelAddress)
{
    const int PAGE_SIZE = 4096;

    // Make probe array
    byte[] probeArray = new byte[256 * PAGE_SIZE];

    // Clear cash
    Processor.ClearL1Cache();

    try
    {
        // mov al, byte [rcx]
        // This will throw an exception because we access illegal memory
        byte secret = *((byte*)kernelAddress.ToPointer());

        // Note that although the previous line logically 
        // throws an exception, 
        // the following code is still executed internally 
        // in the processor before the exception is 
        // actually triggered

        // Although the following lines are executed, any assignments 
        // to variables are discarded by the processor at the time the 
        // exception is then actually thrown.

        // shl rax, 0xc
        int pageOffset = secret * PAGE_SIZE;

        // mov rbx, qword [rbx + rax]
        // This moves the page with number secret into the L1 cache.
        int temp = probeArray[pageOffset];
    }
    catch
    {
        // Ignore Exception
    }

    // Now meassure time for accessing pages
    int bestTime = int.MaxValue;
    byte bestPage = 0;

    for(int i=0; i<= 255, i++)
    {
        int startTime = DateTime.NowInNanoSeconds;
        int temp = probeArray[i * PAGE_SIZE];
        int endTime = DateTime.NowInNanoSeconds;

        int timeTaken = endTime - startTime;
        if(timeTaken < bestTime)
        {
            bestTime = timeTaken;
            bestPage = (byte)i;
        }

    }

    // Fastest page was loaded from Cache and is the leaked secret
    return bestPage;
}

这篇关于如何找出Intel处理器上的指令触及了哪条缓存行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 11:17