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