diff --git a/canaries/canaries_callbacks.c b/canaries/canaries_callbacks.c index 037c21fe3b096e7ae3f3f076d86e0eec2c9830c0..d64998ff16870cf6b27e9323451cb483305fe09e 100644 --- a/canaries/canaries_callbacks.c +++ b/canaries/canaries_callbacks.c @@ -27,7 +27,7 @@ #include "null.h" #endif #define DEBUG_ADD -static unsigned long long canaries_top_of_stack = 0; +unsigned long long canaries_top_of_stack = 0; #ifdef DEBUG #define print_str_debug canaries_print_str @@ -104,6 +104,8 @@ void zipr_set_top_of_stack(unsigned long long ignore, print_str_debug("\n"); #endif canaries_top_of_stack = rsp; + + asm volatile ("mov %%dx, %%fs:0x28\n":::); } void rewrite_canaries(uint64_t new_canary) { @@ -155,6 +157,15 @@ void rewrite_canaries(uint64_t new_canary) { printf("offset: 0x%x\n", offset); printf("replacement canary: 0x%lx\n", replacement_canary); */ + print_str_debug("fs:0x28: 0x"); + print_unsigned_long_long_debug(old_canary); + print_str_debug("\n"); + print_str_debug("offset: "); + print_unsigned_long_long_debug(offset); + print_str_debug("\n"); + print_str_debug("replacement canary: "); + print_unsigned_long_long_debug(replacement_canary); + print_str_debug("\n"); #endif /* * The last 16 bits don't matter for @@ -166,7 +177,7 @@ void rewrite_canaries(uint64_t new_canary) { * Walk the canary stack and * update as we go. */ - while ((uint64_t)canary_loc <= canaries_top_of_stack) { + while ((uint64_t)canary_loc < canaries_top_of_stack) { #if DEBUG print_str_debug("We are inside the rewriting loop.\n"); print_str_debug("canary_loc:"); @@ -219,6 +230,7 @@ void rewrite_canaries(uint64_t new_canary) { /* */ #define FORK 57 +#define ACCEPT 57 #define PTHREAD_CREATE 58 void zipr_hook_dynamic_callback(unsigned int id, unsigned long long rax, unsigned long long rsp) { @@ -233,7 +245,7 @@ void zipr_hook_dynamic_callback(unsigned int id, unsigned long long rax, unsigne #endif zipr_set_top_of_stack(0ll, rsp); } - else if (id == FORK && rax!=0) { + else if (id == FORK /*&& rax!=0*/) { #ifdef DEBUG print_str_debug("In zipr_rewrite_canaries_callback, id="); print_int_debug(id); diff --git a/canaries/debug_canary_callbacks.c b/canaries/debug_canary_callbacks.c index a8a65c73ddfae88d9af3cf4d7e5d85a61af6c843..63e8c90dc8838bbfc370fb59f03c9ff9f3863238 100644 --- a/canaries/debug_canary_callbacks.c +++ b/canaries/debug_canary_callbacks.c @@ -53,6 +53,101 @@ void print_unsigned_long_long(unsigned long long x) } #endif +extern unsigned long long canaries_top_of_stack; + +void verify_all_canaries(void) { + void *canary_loc = NULL; + uint16_t offset = 0; + uint64_t canary = 0; + uint64_t old_canary = 0; + uint16_t distance_to_first_canary = 0; + /* + * Without the nop here, fix_canaries + * believes that this is a push canary operation. + */ + asm volatile ("mov %%fs:0x28, %0\n" + "nop\n" + : "+r" (old_canary) + : + :); + /* + * A trick to learn nearly the value of RSP, + * without resorting to ASM. + */ + canary_loc = &canary_loc; + + /* + * Emulate the logic for calculating a new canary value + * to learn the value of the most recent canary. + */ + distance_to_first_canary=(old_canary&0xFFFF)-(((uint64_t)canary_loc)&0xFFFF); + canary_loc = (void*)(((uint64_t)canary_loc) + distance_to_first_canary); + /* + * Offset is really only the last 16 bits. + */ + offset = old_canary & 0xFFFF; + +#ifdef DEBUG + print_str_debug("initial canary distance: 0x"); + print_unsigned_long_long_debug(distance_to_first_canary); + print_str_debug("\n"); + print_str_debug("fs:0x28: 0x"); + print_unsigned_long_long_debug(old_canary); + print_str_debug("\n"); + print_str_debug("offset: "); + print_unsigned_long_long_debug(offset); + print_str_debug("\n"); +#endif + /* + * The last 16 bits don't matter for + * the canary value. + */ + old_canary >>= 16; + + /* + * Walk the canary stack and + * update as we go. + */ + while ((uint64_t)canary_loc < canaries_top_of_stack) { +#if DEBUG + print_str_debug("We are inside the rewriting loop.\n"); + print_str_debug("canary_loc:"); + print_unsigned_long_long_debug(canary_loc); + print_str_debug("\n"); +#endif +/* + printf("*canary_loc: 0x%lx\n", *((uint64_t*)(canary_loc))); +*/ +#if DEBUG + print_str_debug("Check: "); + print_unsigned_long_long_debug((*((uint64_t*)(canary_loc)))>>16); + print_str_debug(" ?= "); + print_unsigned_long_long_debug(old_canary); + print_str_debug("\n"); +#endif + if (((*((uint64_t*)(canary_loc))) >> 16) != old_canary) { + __stack_chk_fail(); + break; + } + + canary_loc += *(uint64_t*)canary_loc & 0xFFFF; + +#if DEBUG + print_str_debug("canary_loc':"); + print_unsigned_long_long_debug(canary_loc); + print_str_debug("\n"); +#endif + + /* + * TODO: Defend against nefariousness: + * 1. Attacker setting offset to 0 -> infinite loop + * 2. Really deep stacks? + * 3. etc? + */ + } + print_str_debug("successfully done rewriting all canary values.\n"); +} + /* */ void zipr_debug_canary_callback(unsigned long long fs0x28, @@ -69,5 +164,6 @@ void zipr_debug_canary_callback(unsigned long long fs0x28, print_str_debug("rsp ="); print_unsigned_long_long_debug(rsp); print_str_debug("\n"); + verify_all_canaries(); #endif }