diff --git a/mixr/Makefile.in b/mixr/Makefile.in index 9b5668623889f31d7a098f83efc9b0fe4c585211..108a18a967fcac0de79bacf857a972e8e072212a 100644 --- a/mixr/Makefile.in +++ b/mixr/Makefile.in @@ -2,7 +2,7 @@ CC=@CC@ EXTRA_INCLUDES=-I$(PEASOUP_UMBRELLA_DIR)/zipr_mixr_plugin/ -CFLAGS=-fno-omit-frame-pointer @CFLAGS@ $(EXTRA_INCLUDES) +CFLAGS=-fno-omit-frame-pointer @CFLAGS@ -O0 $(EXTRA_INCLUDES) LIB=@LIB@ AR=@AR@ AS=@AS@ diff --git a/mixr/mixr.c b/mixr/mixr.c index 1d618f9ec530f9b191c276fd68e3d49b3f503f0c..d3a07bc4ef4a9732ec12d92a38414bbb35fc7db7 100644 --- a/mixr/mixr.c +++ b/mixr/mixr.c @@ -5,8 +5,11 @@ #include <memory.h> #include <stdlib.h> #include <unistd.h> +#include <fcntl.h> #include <sys/syscall.h> #else +int syscall(int number, ...); +#include <stdlib.h> #include <malloc.h> #include <stdint.h> #include <strlen.h> @@ -20,11 +23,14 @@ #define PROT_WRITE 0x2 #define PROT_EXEC 0x4 +static void *bottom_of_stack_ptr; +static void *global_table_addr; +static int q_fd; #ifndef TEST #define SYS_mprotect 10 #endif -#define DT_ENTRY_SIZE (8+2) +#define DT_ENTRY_SIZE (8+2+1) #define DT_LENGTH_SIZE 8 #define DT_FIXED_SIZE_SIZE 8 #define DT_FIRST_ENTRY_OFFSET (DT_LENGTH_SIZE+DT_FIXED_SIZE_SIZE) @@ -49,9 +55,14 @@ #define assert(a) #endif +int _mprotect(void *addr, size_t len, int flags); +void _memcpy(void *dst, const void *src, unsigned long int len); uint8_t swap_space[MIXR_FIXED_SIZE]; +uint64_t dt_table_length(void *); +uint64_t dt_table_read_entry_address(void *, unsigned int ); +void dt_table_write_entry_active(void *, unsigned int, uint8_t ); #ifdef DEBUG #define write_fd 2 void mixr_print_str(char *s) @@ -76,10 +87,117 @@ void mixr_print_addr(void *x) } #endif +void mixr_active_dollops_clear(void *table_addr) { + uint64_t table_length = dt_table_length(table_addr); + unsigned int table_iterator = 0; + volatile uint8_t empty = 0; + + _mprotect((void*)(((uintptr_t)table_addr)&PAGE_MASK), + (table_length*DT_ENTRY_SIZE) + + DT_FIXED_SIZE_SIZE + + DT_LENGTH_SIZE + + PAGE_SIZE, + PROT_READ|PROT_EXEC|PROT_WRITE); + for (table_iterator = 0; table_iterator<table_length; table_iterator++) + { + dt_table_write_entry_active(table_addr, table_iterator, empty); + } + _mprotect((void*)(((uintptr_t)table_addr)&PAGE_MASK), + (table_length*DT_ENTRY_SIZE) + + DT_FIXED_SIZE_SIZE + + DT_LENGTH_SIZE + + PAGE_SIZE, + PROT_READ|PROT_EXEC); +} + +unsigned int mixr_find_dollop_containing(void *table_addr, uint64_t addr, uint8_t *found) +{ + uint64_t table_length = dt_table_length(table_addr); + unsigned int table_iterator = 0; + uint64_t table_iterator_address = 0; + + *found = 0; + + for (table_iterator = 0; table_iterator<table_length; table_iterator++) + { + table_iterator_address = dt_table_read_entry_address(table_addr, table_iterator); + if (table_iterator_address<=addr && addr<=(table_iterator_address+MIXR_FIXED_SIZE)) { + *found = 1; + return table_iterator; + } + } + return 0; +} + +void mixr_active_dollops_mark_from_stack(void *table_addr) { + void *stack_ptr = NULL; + /* + * There are other hacks to get this, but + * let's just use the real thing. + */ + asm ("movq %%rsp, %0\n" + : "=r" (stack_ptr) + :); + + _mprotect((void*)(((uintptr_t)table_addr)&PAGE_MASK), + (dt_table_length(table_addr)*DT_ENTRY_SIZE) + + DT_FIXED_SIZE_SIZE + + DT_LENGTH_SIZE + + PAGE_SIZE, + PROT_READ|PROT_EXEC|PROT_WRITE); + + while (stack_ptr != bottom_of_stack_ptr) + { + uint64_t stack_value = *((uint64_t*)stack_ptr); + uint8_t found = 0; + unsigned int entry = 0; + + entry = mixr_find_dollop_containing(table_addr, stack_value, &found); +#ifdef DEBUG +#ifdef TEST + printf("stack_ptr: %lx @ 0x%lx\n", stack_value, stack_ptr); +#else + print_str_debug("stack: "); + print_int_debug(stack_value); + print_str_debug(" @ 0x"); + print_addr_debug(stack_ptr); + print_str_debug("\n"); +#endif +#endif + if (found) + { +#ifdef DEBUG +#ifdef TEST + printf("Pointer to dollop %lu at 0x%lx\n", entry, stack_ptr); +#else + print_str_debug("Pointer to dollop "); + print_int_debug(entry); + print_str_debug(" @ 0x"); + print_addr_debug(stack_ptr); + print_str_debug("\n"); +#endif +#endif + dt_table_write_entry_active(table_addr, entry, 1); + } + /* + * In x86-64 (and perhaps earlier), stack is + * 8-byte aligned. Let's walk at that + * resolution. + */ + stack_ptr+=0x8; + } + _mprotect((void*)(((uintptr_t)table_addr)&PAGE_MASK), + (dt_table_length(table_addr)*DT_ENTRY_SIZE) + + DT_FIXED_SIZE_SIZE + + DT_LENGTH_SIZE + + PAGE_SIZE, + PROT_READ|PROT_EXEC); +} + uint64_t read_random64(void) { unsigned long long random_value = -1; int fd = -1; - fd = open("/dev/urandom", 0x00); + fd = open("/dev/urandom", 0x00, 0x00); if (fd != -1) { read(fd, (void*)&random_value, sizeof(unsigned long long)); close(fd); @@ -87,7 +205,9 @@ uint64_t read_random64(void) { return random_value; } -void _memcpy(void *dst, const void *src, unsigned long int len); +#ifdef TEST +#define _memcpy memcpy +#else void _memcpy(void *dst, const void *src, unsigned long int len) { unsigned long int i = 0; @@ -96,6 +216,7 @@ void _memcpy(void *dst, const void *src, unsigned long int len) } return; } +#endif void make_writable(void *addr, size_t len) { @@ -105,7 +226,6 @@ void make_unwritable(void *addr, size_t len) { } -int _mprotect(void *addr, size_t len, int flags); int _mprotect(void *addr, size_t len, int flags) { #ifdef TEST @@ -183,6 +303,33 @@ uint64_t dt_fixed_size(void *dt_table_addr) return fixed_size; } +int dt_table_write_to_file(void *dt_table_addr, char *filename) +{ + uint64_t entry_count = dt_table_length(dt_table_addr); + uint64_t entry_size = dt_fixed_size(dt_table_addr); + int fd = -1; + + fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); + if (fd == -1) + return -1; + + write(fd, dt_table_addr, 8 /* entry count*/ + + 8 /* entry size*/ + + (8+2+1)*entry_count); + close(fd); +} + +int mixr_open_fifo_q(char *q_name) +{ + mkfifo(q_name, S_IRUSR|S_IWUSR); + return open(q_name, O_RDWR, S_IRUSR|S_IWUSR); +} + +int mixr_close_fifo_q(int q) +{ + return close(q); +} + uint64_t dt_table_entry_address(void *dt_table_addr, unsigned int entry) { uint64_t entry_offset = entry * DT_ENTRY_SIZE + DT_FIRST_ENTRY_OFFSET; @@ -209,6 +356,14 @@ uint16_t dt_table_read_entry_offset(void *dt_table_addr, unsigned int entry) return entry_offset; } +uint8_t dt_table_read_entry_active(void *dt_table_addr, unsigned int entry) +{ + uint8_t entry_active; + _memcpy(&entry_active, + (const void*)(dt_table_entry_address(dt_table_addr, entry)+10), + sizeof(uint8_t)); + return entry_active; +} void dt_table_write_entry_address(void *dt_table_addr, unsigned int entry, uint64_t entry_address) { _memcpy((void*)dt_table_entry_address(dt_table_addr, entry), @@ -223,6 +378,14 @@ void dt_table_write_entry_offset(void *dt_table_addr, unsigned int entry, uint16 sizeof(uint16_t)); } +void dt_table_write_entry_active(void *dt_table_addr, unsigned int entry, uint8_t entry_active) +{ + + _memcpy((void*)(dt_table_entry_address(dt_table_addr, entry)+10), + (const void*)&entry_active, + sizeof(uint8_t)); +} + void dt_table_swap_entry_addresses(void *dt_table_addr, unsigned int a, unsigned int b) { uint64_t address_entry_a = dt_table_read_entry_address(dt_table_addr, a); @@ -236,6 +399,7 @@ void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned { uint64_t fixed_size = MIXR_FIXED_SIZE; //void *swap_space = (void*)malloc(fixed_size); + //uint8_t swap_space[MIXR_FIXED_SIZE] = {0,}; void *a_contents_addr = (void*)dt_table_read_entry_address(dt_table_addr,a); void *b_contents_addr = (void*)dt_table_read_entry_address(dt_table_addr,b); uint64_t table_length = (dt_table_length(dt_table_addr)*DT_ENTRY_SIZE) + @@ -262,17 +426,20 @@ void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned print_str_debug("swap_space: "); print_addr_debug((void*)(&swap_space)); print_str_debug("\n"); - print_str_debug("b_contents_addr: "); + print_str_debug("a_contents_addr: "); print_addr_debug(a_contents_addr); print_str_debug("\n"); + print_str_debug("b_contents_addr: "); + print_addr_debug(b_contents_addr); + print_str_debug("\n"); print_str_debug("fixed_size: "); print_int_debug(fixed_size); print_str_debug("\n"); #endif - _memcpy((void*)(&swap_space), a_contents_addr, fixed_size); + _memcpy(&swap_space, a_contents_addr, fixed_size); _memcpy(a_contents_addr, b_contents_addr, fixed_size); - _memcpy(b_contents_addr, (void*)(&swap_space), fixed_size); + _memcpy(b_contents_addr, &swap_space, fixed_size); #ifdef DEBUG print_str_debug("a: "); @@ -386,38 +553,36 @@ void mixr_do_rw(uint64_t dollop_start, struct rw_table_entry rw_entry) output = _rbp_value; \ } \ -void zipr_hook_start(unsigned long long id, - unsigned long long rax, - unsigned long long rsp) +#define get_rsp(output) \ +{ \ + uint64_t _rsp_value = 0xfeed; \ + asm volatile ("mov %%rsp, %0\n" \ + : "=r" (_rsp_value) \ + ); \ + output = _rsp_value; \ +} \ + + + +void zipr_mixr(void *table_addr) { - void *table_addr = 0; uint64_t table_length = 0; uint64_t table_iterator = 2; - uint64_t ra = 0, rbp_value = 0; + uint64_t table_fixed_size = 0; - table_addr = (void*)id; + uint64_t q_value = 0xab; + table_length = dt_table_length(table_addr); - //a = read_random64() % table_length; - //b = read_random64() % table_length; - - get_rbp(rbp_value); - - /* - * The return value is 16 bytes above - * the rbp. - */ - ra = *((uint64_t*)(rbp_value+0x8)); + table_fixed_size = dt_fixed_size(table_addr); #ifdef DEBUG - print_str_debug("rbp_value:"); - print_unsigned_long_long_debug(rbp_value); - print_str_debug("\n"); - print_str_debug("ra:"); - print_unsigned_long_long_debug(ra); - print_str_debug("\n"); + print_str_debug("dt_fixed_size:"); + print_unsigned_long_long_debug(table_fixed_size); + print_str_debug("\n"); #endif -#if 1 - for (table_iterator = 2; table_iterator<table_length; table_iterator+=2) + + mixr_active_dollops_mark_from_stack(table_addr); + for (table_iterator = 1; table_iterator<table_length; table_iterator+=2) { uint64_t a = table_iterator, b = a-1; uint64_t dt_address_a = dt_table_read_entry_address(table_addr, a); @@ -429,6 +594,7 @@ void zipr_hook_start(unsigned long long id, uint64_t rw_address_b = dt_address_b + dt_offset_b; uint16_t rw_entry_count_b = rw_table_entry_count((void*)rw_address_b); uint16_t rw_entry_count_iterator = 0; + #ifdef DEBUG print_str_debug("Swapping:"); print_unsigned_long_long_debug(a); @@ -448,20 +614,20 @@ void zipr_hook_start(unsigned long long id, print_int_debug(rw_entry_count_b); print_str_debug(")\n"); #endif - if ((dt_address_a <= ra && (dt_address_a+MIXR_FIXED_SIZE) >= ra) || - (dt_address_b <= ra && (dt_address_b+MIXR_FIXED_SIZE) >= ra)) + if (dt_table_read_entry_active(table_addr, a) || + dt_table_read_entry_active(table_addr, b)) { #ifdef DEBUG print_str_debug("Skipping swap "); print_int_debug(a); print_str_debug("<->"); print_int_debug(b); - print_str_debug(" because it is active.\n"); + print_str_debug(" because it is marked active.\n"); #endif continue; } - dt_table_swap_entry_contents(table_addr, a, b); + dt_table_swap_entry_contents(table_addr, a, b); /* * Rewrite a. */ @@ -495,7 +661,63 @@ void zipr_hook_start(unsigned long long id, rw_entry_count_iterator)); } } + mixr_active_dollops_clear(table_addr); +#ifdef DEBUG + print_str_debug("Done with the clearing swapping!\n"); +#endif + +#ifdef DEBUG + print_str_debug("Done with swapping!\n"); +#endif + +#ifdef DEMO + dt_table_write_to_file(table_addr, "/tmp/testwrite.bin"); #endif + + if (q_fd == -1) + q_fd = mixr_open_fifo_q("/tmp/testfifo.txt"); + write(q_fd, (const char *)&q_value, sizeof(uint64_t)); +} + +void zipr_hook_start(unsigned long long id, + unsigned long long rax, + unsigned long long rsp) +{ + global_table_addr = 0; + uint64_t ra = 0, rbp_value = 0, rsp_value = 0; + + //a = read_random64() % table_length; + //b = read_random64() % table_length; + + q_fd = -1; + + get_rbp(rbp_value); + + get_rsp(rsp_value); + bottom_of_stack_ptr = (void*)rbp_value; + + /* + * The return value is 16 bytes above + * the rbp. + */ + ra = *((uint64_t*)(rbp_value+0x8)); + +#ifdef DEBUG + print_str_debug("rbp_value:"); + print_unsigned_long_long_debug(rbp_value); + print_str_debug("\n"); + print_str_debug("ra:"); + print_unsigned_long_long_debug(ra); + print_str_debug("\n"); +#endif + + global_table_addr = (void*)id; + zipr_mixr(global_table_addr); +} + +void zipr_hook_dynamic_callback(unsigned int id, unsigned long long rax, unsigned long long rsp) +{ + zipr_mixr(global_table_addr); } #ifdef TEST @@ -514,6 +736,9 @@ void test_dollop_table(void) uint16_t nine_offset = 0x9; uint16_t ten_offset = 0xa; + uint8_t nine_active = 0x9; + uint8_t ten_active = 0xa; + _memcpy(table, (const void*)&table_entries, sizeof(uint64_t)); _memcpy(table, (const void*)&table_entries, sizeof(uint64_t)); _memcpy((void*)(((uint64_t)table)+(DT_LENGTH_SIZE)), @@ -532,8 +757,10 @@ void test_dollop_table(void) dt_table_write_entry_address(table, 9, (uint64_t)&nine); dt_table_write_entry_offset(table, 9, nine_offset); + dt_table_write_entry_active(table, 9, nine_active); dt_table_write_entry_address(table, 10, (uint64_t)&ten); dt_table_write_entry_offset(table, 10, ten_offset); + dt_table_write_entry_active(table, 10, ten_active); printf("dt_table_length: %lu\n", dt_table_length(table)); printf("dt_fixed_size: %lu\n", dt_fixed_size(table)); @@ -543,6 +770,9 @@ void test_dollop_table(void) printf("dt_table_read_entry_offset(0): %hx\n", dt_table_read_entry_offset(table, 0)); printf("dt_table_read_entry_offset(5): %hx\n", dt_table_read_entry_offset(table, 5)); printf("dt_table_read_entry_offset(8): %hx\n", dt_table_read_entry_offset(table, 8)); + printf("dt_table_read_entry_active(0): %hx\n", dt_table_read_entry_active(table, 0)); + printf("dt_table_read_entry_active(5): %hx\n", dt_table_read_entry_active(table, 5)); + printf("dt_table_read_entry_active(8): %hx\n", dt_table_read_entry_active(table, 8)); printf("swap 5 <-> 8\n"); dt_table_swap_entry_addresses(table, 5, 8); @@ -561,15 +791,21 @@ void test_dollop_table(void) printf("dt_table_read_entry_address(9): %lx, %x\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9))); printf("dt_table_read_entry_offset(9): %hx\n", dt_table_read_entry_offset(table, 9)); + printf("dt_table_read_entry_active(9): %hx\n", dt_table_read_entry_active(table, 9)); printf("dt_table_read_entry_address(10): %lx, %x\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10))); printf("dt_table_read_entry_offset(10): %hx\n", dt_table_read_entry_offset(table, 10)); + printf("dt_table_read_entry_active(10): %hx\n", dt_table_read_entry_active(table, 10)); dt_table_swap_entry_contents(table, 10, 9); printf("dt_table_read_entry_address(9): %lx, %x\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9))); printf("dt_table_read_entry_offset(9): %hx\n", dt_table_read_entry_offset(table, 9)); + printf("dt_table_read_entry_active(9): %hx\n", dt_table_read_entry_active(table, 9)); printf("dt_table_read_entry_address(10): %lx, %x\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10))); printf("dt_table_read_entry_offset(10): %hx\n", dt_table_read_entry_offset(table, 10)); + printf("dt_table_read_entry_active(10): %hx\n", dt_table_read_entry_active(table, 10)); + + dt_table_write_to_file(table, "/tmp/testtable.bin"); } void test_rw_table(void)