2

I heard about the Meltdown vulnerability and read the paper, which was kind of difficult since I am not a native speaker, but I decided to make a small proof of concept C++ program which is shown below, I would like to know the reasons for the code not working. I have tested it on an AMD FX 8350 Eight Core and an Intel I3 processor

/*In this code I wanted to make a PoC for the Meltdown flaw (https://meltdownattack.com/)*/
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <chrono>

int secretvar = 15;     //This is our "unreadable" var which we "cannot" read but we will have the value exposed via cache attack
int x = rand() % 100;   //Used later, important that it's random

int main()
{   
    int arr[1000];                  //We setup our array
    for (int i = 0; i < 100; ++i) { //Fill it with random values
        arr[i] = rand() % 10 + 1;
    };

    if (x == 4) {                       //Here I want to trigger the Out-of-Order execution so that the CPU executes the code below the if case
        int c = arr[secretvar];         //before it really checks if x is actually 4. And with this, the CPU would put the cached variable "c" into
                                        //its cache.
    };
    
/*At this point we don't know the value of secretvar but we know that the CPU has cached some index with the
exact value of secretvar. Therefore we can now iterate over the array and how long it takes the CPU to access the
different array indexes. The CPU will be faster at accessing one specific element because it is taken from cache 
and not from the memory. This index is the value of secretvar.*/

    double lowest_val = 500;
    int    lowest_index = 0;

    for (int i = 0; i < 100; i++) {
        auto start = std::chrono::high_resolution_clock::now(); //start timer
        arr[i];                                                 //access array
        auto finish = std::chrono::high_resolution_clock::now();//end timer
        std::chrono::duration<double> elapsed = finish - start;//calculate needed time
        double e = elapsed.count();
        if (e < lowest_val) {
            lowest_val = e;
            lowest_index = i;
        }
        std::cout << i << " : " << e << " s\n"; //show it to the screen
    }
    std::cout <<  lowest_index << "Was accessed fastest "<< " with a time of  "<< lowest_val << "ms" << std::endl;
    system("pause");
    return 0;
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • 1
    What is the current behavior/expected behavior? – user202729 Jan 07 '18 at 14:39
  • 1
    It seems that the whole array `arr` fits in the cache, so... – user202729 Jan 07 '18 at 14:40
  • @user202729 ok thank you, is there a way to prevent the whole arrray to be cached? –  Jan 07 '18 at 14:44
  • 1
    Besides adjusting array size you need to make sure that actual machine code does correspond to your code. For example `if (x == 4) ` check and branch most likely will be thrown away by the compiler if at least minimum optimization level is turned on. – user7860670 Jan 07 '18 at 14:49
  • @VTT Ok, I will run this without any optimization but doesnt the randomness of x prevent the compiler from deleting the if branch? –  Jan 07 '18 at 14:56
  • 3
    It may as well rearrange the branch. Compilers nowadays are **smart**. Look at the assembly is the only way to be sure. – user202729 Jan 07 '18 at 14:57
  • 1
    Without optimizations it may emit additional code that will mess up the experiment. For example padding filling or stack checks. – user7860670 Jan 07 '18 at 14:57
  • Even with `-O0` some compiler still optimize division to multiplication... – user202729 Jan 07 '18 at 14:58
  • So i turned optimization off and testet it again on both processors but it did not work.Unfortunately, I dont have the debugger and assembly knowledge to look into the code that deep –  Jan 07 '18 at 15:21
  • This sort of test(ing) is usually done with hand-crafted assembler together with an expert knowledge of the instruction set and architecture. – Richard Critten Jan 07 '18 at 16:01
  • @ByteR have a look at my Specter-Based Meltdown PoC implemented in C: https://github.com/berestovskyy/spectre-meltdown It has just 99 lines, has no assembler at all, so I hope it would not be an issue to understand it and rewrite either in C++ or other programming language... – Andriy Berestovskyy Feb 03 '18 at 11:03

0 Answers0