diff --git a/.gitattributes b/.gitattributes index 1384c7f2d562a15149f8200d46663bfba8de6a6e..f791851919faf4d1bffadcc47b95f534bd08c5bf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -60,6 +60,8 @@ libc/src/stdlib.c -text libc/src/strlen.c -text libc/src/syscall.s -text libc/src/write.c -text +mixr/Makefile.in -text +mixr/mixr.c -text p1/Makefile.in -text p1/p1callbacks.c -text rss/Makefile.in -text diff --git a/configure.in b/configure.in index b46ac9891b8eb0e3a00ad4f6212d896c83d87fa9..0c573ce379a272b8d7fbd5768d43ef64d62f6b10 100644 --- a/configure.in +++ b/configure.in @@ -72,6 +72,7 @@ enable_dir inferfn enable_dir rss enable_dir hookdynamic enable_dir canaries +enable_dir mixr enable_dir cookbook enable_dir buffrecv enable_dir datashadow diff --git a/mixr/Makefile.in b/mixr/Makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..9603c84722e8cf038a92ace9751205fbc6b3f7a0 --- /dev/null +++ b/mixr/Makefile.in @@ -0,0 +1,28 @@ + + +CC=@CC@ +CFLAGS=-fno-omit-frame-pointer @CFLAGS@ +LIB=@LIB@ +AR=@AR@ +AS=@AS@ +ASFLAGS=@ASFLAGS@ + +OBJS=mixr.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/mixr/mixr.c b/mixr/mixr.c new file mode 100644 index 0000000000000000000000000000000000000000..74eb7ea4aaf79c0c36bfce1ddf54ec91d382f79c --- /dev/null +++ b/mixr/mixr.c @@ -0,0 +1,350 @@ +#ifdef TEST +#include <stdio.h> +#include <sys/types.h> +#include <stdint.h> +#include <memory.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/syscall.h> +#else +#include <malloc.h> +#include <stdint.h> +#include <strlen.h> +#include <itox.h> +#endif + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define SYS_mprotect 10 + +#define DT_ENTRY_SIZE 8 +#define DT_LENGTH_SIZE 8 +#define DT_FIXED_SIZE_SIZE 8 +#define DT_FIRST_ENTRY_OFFSET (DT_LENGTH_SIZE+DT_FIXED_SIZE_SIZE) + +#define PAGE_SIZE 4096 +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#ifdef TEST +#define MIXR_FIXED_SIZE (sizeof(int)) +#else +#define MIXR_FIXED_SIZE (40) +#endif + +#ifdef DEBUG + #define print_str_debug mixr_print_str + #define print_int_debug mixr_print_int + #define print_unsigned_long_long_debug mixr_print_unsigned_long_long +#else + #define print_str_debug(a) + #define print_int_debug(a) + #define assert(a) +#endif + + +uint8_t swap_space[40]; +#ifdef DEBUG +#define write_fd 2 +void mixr_print_str(char *s) +{ + write(write_fd,s,strlen(s)); +} +void mixr_print_int(int x) +{ + char buf[100]; + itox(x,buf); + write(write_fd,buf,strlen(buf)); +} +void mixr_print_unsigned_long_long(unsigned long long x) +{ + char buf[100]; + itox(x,buf); + write(write_fd,buf,strlen(buf)); +} +#endif + +uint64_t 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; +} + +void _memcpy(void *dst, const void *src, unsigned long int len); +void _memcpy(void *dst, const void *src, unsigned long int len) +{ + unsigned long int i = 0; + for (i = 0; i<len; i++) { + ((uint8_t*)(dst))[i] = ((uint8_t*)(src))[i]; + } + return; +} + +int _mprotect(void *addr, size_t len, int flags); +int _mprotect(void *addr, size_t len, int flags) +{ +#ifdef TEST + printf("_mprotect: addr: %llx\n", addr); + //return mprotect(addr, len, flags); + return 0; +#else + return syscall(SYS_mprotect, addr, len, flags); +#endif +} + +uint64_t dt_table_length(void *dt_table_addr) +{ + uint64_t table_length = 0; + + _memcpy(&table_length, (const void*)dt_table_addr, sizeof(uint64_t)); + + return table_length; +} +uint64_t dt_fixed_size(void *dt_table_addr) +{ + uint64_t fixed_size = 0; + + _memcpy(&fixed_size, + (const void*)(((uint64_t)dt_table_addr) + DT_LENGTH_SIZE), + sizeof(uint64_t)); + + return fixed_size; +} + +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; + return (((uint64_t)dt_table_addr)+entry_offset); +} + +uint64_t dt_table_read_entry_address(void *dt_table_addr, unsigned int entry) +{ + uint64_t entry_address = 0; + + _memcpy(&entry_address, + (const void*)dt_table_entry_address(dt_table_addr, entry), + sizeof(uint64_t)); + + return entry_address; +} + +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), + (const void*)&entry_address, + sizeof(uint64_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); + uint64_t address_entry_b = dt_table_read_entry_address(dt_table_addr, b); + + dt_table_write_entry_address(dt_table_addr, a, address_entry_b); + dt_table_write_entry_address(dt_table_addr, b, address_entry_a); +} + +void dt_table_swap_entry_contents(void *dt_table_addr, unsigned int a, unsigned int b) +{ + uint64_t fixed_size = 40; //dt_fixed_size(dt_table_addr); + //void *swap_space = (void*)malloc(fixed_size); + 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) + + DT_FIXED_SIZE_SIZE + + DT_LENGTH_SIZE; + /* + * Three steps: + * 1. mprotect + w + * 2. copy + * 3. mprotect - w + * The assumption is that we are '-w' in these + * pages when we start. + */ + _mprotect((void*)(((uint64_t)dt_table_addr)&PAGE_MASK), + table_length + PAGE_SIZE, + PROT_READ|PROT_EXEC|PROT_WRITE); + _mprotect((void*)(((uint64_t)a_contents_addr)&PAGE_MASK), + PAGE_SIZE + PAGE_SIZE, + PROT_READ|PROT_EXEC|PROT_WRITE); + _mprotect((void*)(((uint64_t)b_contents_addr)&PAGE_MASK), + PAGE_SIZE + PAGE_SIZE, + PROT_READ|PROT_EXEC|PROT_WRITE); +#ifdef DEBUG + print_str_debug("swap_space: "); + print_int_debug((void*)(&swap_space)); + print_str_debug("\n"); + print_str_debug("b_contents_addr: "); + print_int_debug(a_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(a_contents_addr, b_contents_addr, fixed_size); + _memcpy(b_contents_addr, (void*)(&swap_space), fixed_size); + +#ifdef DEBUG + print_str_debug("a: "); + print_int_debug(dt_table_read_entry_address(dt_table_addr, a)); + print_str_debug("\n "); + print_str_debug("b: "); + print_int_debug(dt_table_read_entry_address(dt_table_addr, b)); + print_str_debug("\n "); +#endif + + dt_table_swap_entry_addresses(dt_table_addr, a, b); + +#ifdef DEBUG + print_str_debug("a: "); + print_int_debug(dt_table_read_entry_address(dt_table_addr, a)); + print_str_debug("\n "); + print_str_debug("b: "); + print_int_debug(dt_table_read_entry_address(dt_table_addr, b)); + print_str_debug("\n "); +#endif + + _mprotect((void*)(((uint64_t)dt_table_addr)&PAGE_MASK), + table_length + PAGE_SIZE, + PROT_READ|PROT_EXEC); + _mprotect((void*)(((uint64_t)a_contents_addr)&PAGE_MASK), + PAGE_SIZE + PAGE_SIZE, + PROT_READ|PROT_EXEC); + _mprotect((void*)(((uint64_t)b_contents_addr)&PAGE_MASK), + PAGE_SIZE + PAGE_SIZE, + PROT_READ|PROT_EXEC); +} + +#define get_rbp(output) \ +{ \ + uint64_t _rbp_value = 0xfeed; \ + asm volatile ("mov %%rbp, %0\n" \ + : "=r" (_rbp_value) \ + ); \ + output = _rbp_value; \ +} \ + +void zipr_hook_start(unsigned int id, + unsigned long long rax, + unsigned long long rsp) +{ + uint64_t table_addr = 0; + uint64_t table_length = 0; + uint64_t table_iterator = 2; + uint64_t ra = 0, rbp_value = 0; + + table_addr = (uint64_t)id; + 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)); + +#ifdef DEBUG + print_str_debug("rbp_value:"); + print_int_debug(rbp_value); + print_str_debug("\n"); + print_str_debug("ra:"); + print_int_debug(ra); + print_str_debug("\n"); +#endif + + for (table_iterator = 2; table_iterator<table_length; table_iterator+=2) + { + uint64_t a = table_iterator, b = a-1; +#ifdef DEBUG + print_str_debug("Swapping:"); + print_int_debug(a); + print_str_debug(":"); + print_int_debug(dt_table_read_entry_address(table_addr, a)); + print_str_debug("<->"); + print_int_debug(b); + print_str_debug(":"); + print_int_debug(dt_table_read_entry_address(table_addr, b)); + print_str_debug("\n"); +#endif + if ((dt_table_read_entry_address(table_addr, a) <= ra && + (dt_table_read_entry_address(table_addr, a)+MIXR_FIXED_SIZE) >= ra) || + (dt_table_read_entry_address(table_addr, b) <= ra && + (dt_table_read_entry_address(table_addr, b)+MIXR_FIXED_SIZE) >= ra)) + { +#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"); +#endif + continue; + } + dt_table_swap_entry_contents(table_addr, a, b); + } +} + +#ifdef TEST +int main() +{ + uint64_t table_entries = 11; + uint64_t table_fixed_size = MIXR_FIXED_SIZE; + uint64_t table_entry_address = 0xff00ff00; + void *table = (void*)malloc((table_entries*DT_ENTRY_SIZE)+DT_FIRST_ENTRY_OFFSET); + unsigned i = 0; + + int nine = 9; + int ten = 10; + + _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)), + (const void*)&table_fixed_size, + sizeof(uint64_t)); + + for (i = 0; i<table_entries-2; i++) + { + table_entry_address += 1; + printf("table_entry_address: (%d): %llx\n", i, table_entry_address); + dt_table_write_entry_address(table, i, table_entry_address); + } + + dt_table_write_entry_address(table, 9, &nine); + dt_table_write_entry_address(table, 10, &ten); + + printf("dt_table_length: %llu\n", dt_table_length(table)); + printf("dt_fixed_size: %llu\n", dt_fixed_size(table)); + printf("dt_table_read_entry_address(0): %llx\n", dt_table_read_entry_address(table, 0)); + printf("dt_table_read_entry_address(5): %llx\n", dt_table_read_entry_address(table, 5)); + printf("dt_table_read_entry_address(8): %llx\n", dt_table_read_entry_address(table, 8)); + + printf("swap 5 <-> 8\n"); + dt_table_swap_entry_addresses(table, 5, 8); + + printf("dt_table_read_entry_address(5): %llx\n", dt_table_read_entry_address(table, 5)); + printf("dt_table_read_entry_address(8): %llx\n", dt_table_read_entry_address(table, 8)); + printf("swap 8 <-> 0\n"); + dt_table_swap_entry_addresses(table, 0, 8); + printf("dt_table_read_entry_address(0): %llx\n", dt_table_read_entry_address(table, 0)); + printf("dt_table_read_entry_address(8): %llx\n", dt_table_read_entry_address(table, 8)); + + printf("dt_table_read_entry_address(9): %llx, %llx\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9))); + printf("dt_table_read_entry_address(10): %llx, %llx\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10))); + dt_table_swap_entry_contents(table, 10, 9); + printf("dt_table_read_entry_address(9): %llx, %llx\n", dt_table_read_entry_address(table, 9), *((int*)dt_table_read_entry_address(table, 9))); + printf("dt_table_read_entry_address(10): %llx, %llx\n", dt_table_read_entry_address(table, 10), *((int*)dt_table_read_entry_address(table, 10))); + return 0; +} +#endif