From fe2be2f029b4cbb74eae8b9c13e6191a78424559 Mon Sep 17 00:00:00 2001 From: whh8b <whh8b@git.zephyr-software.com> Date: Thu, 3 Sep 2015 17:32:12 +0000 Subject: [PATCH] Initial checkin of canary callback code. --- .gitattributes | 3 + canaries/Makefile.in | 28 ++++ canaries/canaries_callbacks.c | 249 ++++++++++++++++++++++++++++++ canaries/debug_canary_callbacks.c | 73 +++++++++ 4 files changed, 353 insertions(+) create mode 100644 canaries/Makefile.in create mode 100644 canaries/canaries_callbacks.c create mode 100644 canaries/debug_canary_callbacks.c diff --git a/.gitattributes b/.gitattributes index cd3031d..a63e585 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,8 @@ * text=auto !eol /Makefile.in -text +canaries/Makefile.in -text +canaries/canaries_callbacks.c -text +canaries/debug_canary_callbacks.c -text /configure -text /configure.in -text /configure_for_cgc -text diff --git a/canaries/Makefile.in b/canaries/Makefile.in new file mode 100644 index 0000000..524da1b --- /dev/null +++ b/canaries/Makefile.in @@ -0,0 +1,28 @@ + + +CC=@CC@ +CFLAGS=@CFLAGS@ +LIB=@LIB@ +AR=@AR@ +AS=@AS@ +ASFLAGS=@ASFLAGS@ + +OBJS=canaries_callbacks.o debug_canary_callbacks.o + + +.SUFFIXES: .o .s .c + +.c.o: + $(CC) $(CFLAGS) $(INCLUDE) -D__$(ARCH) -c $< + +.s.o: + $(AS) $(ASFLAGS) $< + + +all: $(OBJS) + $(AR) -r $(LIB) $(OBJS) + +clean: + rm *.o + + diff --git a/canaries/canaries_callbacks.c b/canaries/canaries_callbacks.c new file mode 100644 index 0000000..037c21f --- /dev/null +++ b/canaries/canaries_callbacks.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2014 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#include <stdint.h> + +#ifdef DEBUG +#include "malloc.h" +#include "itox.h" +#include "strlen.h" +#include "null.h" +#endif +#define DEBUG_ADD +static unsigned long long canaries_top_of_stack = 0; + +#ifdef DEBUG + #define print_str_debug canaries_print_str + #define print_int_debug canaries_print_int + #define print_unsigned_long_long_debug canaries_print_unsigned_long_long +#else + #define print_str_debug(a) + #define print_int_debug(a) + #define assert(a) +#endif + + +#ifdef DEBUG +#define write_fd 2 +void canaries_print_str(char *s) +{ + write(write_fd,s,strlen(s)); +} +void canaries_print_int(int x) +{ + char buf[100]; + itox(x,buf); + write(write_fd,buf,strlen(buf)); +} +void canaries_print_unsigned_long_long(unsigned long long x) +{ + char buf[100]; + itox(x,buf); + write(write_fd,buf,strlen(buf)); +} +#endif + +unsigned long long read_random64(void) { + unsigned long long random_value = -1; + int fd = -1; + fd = open("/dev/urandom", 0x00); + if (fd != -1) { + read(fd, (void*)&random_value, sizeof(unsigned long long)); + close(fd); + } + return random_value; +} + +unsigned long read_random32(void) { + unsigned long random_value = -1; + int fd = -1; + fd = open("/dev/urandom", 0x00); + if (fd != -1) { + read(fd, (void*)&random_value, sizeof(unsigned long)); + close(fd); + } + return random_value; +} +void set_canary64(unsigned long long new_canary) { + asm volatile ("mov %0, %%fs:0x28\n" + : + : "r" (new_canary) + :); +} + +void set_canary32(unsigned long new_canary) { + asm volatile ("mov %0, %%fs:0x28\n" + : + : "r" (new_canary) + :); +} + +void zipr_set_top_of_stack(unsigned long long ignore, + unsigned long long rsp) +{ +#ifdef DEBUG + print_str_debug("rsp: 0x"); + print_unsigned_long_long_debug(rsp); + print_str_debug("\n"); +#endif + canaries_top_of_stack = rsp; +} + +void rewrite_canaries(uint64_t new_canary) { + void *canary_loc = NULL; + uint16_t offset = 0; + uint64_t canary = 0; + uint64_t old_canary = 0; + uint64_t replacement_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; + replacement_canary = (new_canary & ~0xFFFF) | offset; + +#ifdef DEBUG + print_str_debug("initial canary distance: 0x"); + print_unsigned_long_long_debug(distance_to_first_canary); + print_str_debug("\n"); +/* + printf("initial canary location: %p\n", canary_loc); +*/ + print_str_debug("new canary: 0x"); + print_unsigned_long_long_debug(new_canary); + print_str_debug("\n"); +/* + printf("fs:0x28: 0x%lx\n", old_canary); + printf("offset: 0x%x\n", offset); + printf("replacement canary: 0x%lx\n", replacement_canary); +*/ +#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; + } + /* + * Rewrite the canary value -- + * leave the offset in place. + */ + *(((uint16_t*)canary_loc)+3) = new_canary >> 48; + *(((uint16_t*)canary_loc)+2) = new_canary >> 32; + *(((uint16_t*)canary_loc)+1) = new_canary >> 16; + + canary_loc += *(uint64_t*)canary_loc & 0xFFFF; +/* + printf("'canary_loc: %p\n", (canary_loc)); +*/ + /* + * 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"); + /* + * Put the replacement canary in place. + */ + asm volatile ("mov %0, %%fs:0x28\n" + "nop\n" + : + : "r" (replacement_canary) + :); +} +/* + */ +#define FORK 57 +#define PTHREAD_CREATE 58 +void zipr_hook_dynamic_callback(unsigned int id, unsigned long long rax, unsigned long long rsp) +{ +#ifdef DEBUG + print_str_debug("In zipr_rewrite_canaries_callback\n"); +#endif + if (id == PTHREAD_CREATE) { +#ifdef DEBUG + print_str_debug("Setting top of stack to "); + print_unsigned_long_long_debug(rsp); + print_str_debug("\n"); +#endif + zipr_set_top_of_stack(0ll, rsp); + } + else if (id == FORK && rax!=0) { +#ifdef DEBUG + print_str_debug("In zipr_rewrite_canaries_callback, id="); + print_int_debug(id); + print_str_debug(", rax="); + print_int_debug(rax); + print_str_debug("\n"); +#endif + /* + * Parent! + */ + rewrite_canaries(read_random64()); + } +} diff --git a/canaries/debug_canary_callbacks.c b/canaries/debug_canary_callbacks.c new file mode 100644 index 0000000..a8a65c7 --- /dev/null +++ b/canaries/debug_canary_callbacks.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#ifdef DEBUG +#include "malloc.h" +#include "itox.h" +#include "strlen.h" +#include "null.h" + +#else + +#endif + + +#ifdef DEBUG + #define print_str_debug print_str + #define print_unsigned_long_long_debug print_unsigned_long_long +#else + #define print_str_debug(a) + #define print_unsigned_long_long_debug(a) + #define assert(a) +#endif + + +#ifdef DEBUG +#define write_fd 2 +void print_str(char *s) +{ + write(write_fd,s,strlen(s)); +} +void print_unsigned_long_long(unsigned long long x) +{ + char buf[100]; + itox(x,buf); + write(write_fd,buf,strlen(buf)); +} +#endif + +/* + */ +void zipr_debug_canary_callback(unsigned long long fs0x28, + unsigned long long reg, unsigned long long rsp) +{ +#ifdef DEBUG + print_str_debug("In zipr_debug_canary_callback,\n"); + print_str_debug("fs:0x28="); + print_unsigned_long_long_debug(fs0x28); + print_str_debug("\n"); + print_str_debug("reg ="); + print_unsigned_long_long_debug(reg); + print_str_debug("\n"); + print_str_debug("rsp ="); + print_unsigned_long_long_debug(rsp); + print_str_debug("\n"); +#endif +} -- GitLab