diff options
-rwxr-xr-x | .custom-format.py | 15 | ||||
-rw-r--r-- | libtokencap/Makefile | 1 | ||||
-rw-r--r-- | libtokencap/libtokencap.so.c | 372 |
3 files changed, 319 insertions, 69 deletions
diff --git a/.custom-format.py b/.custom-format.py index 8d762006..70107997 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -27,12 +27,15 @@ with open(".clang-format") as f: CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN") if CLANG_FORMAT_BIN is None: - p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE) - o, _ = p.communicate() - o = str(o, "utf-8") - o = o[len("clang-format version "):].strip() - o = o[:o.find(".")] - o = int(o) + o = 0 + try: + p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE) + o, _ = p.communicate() + o = str(o, "utf-8") + o = o[len("clang-format version "):].strip() + o = o[:o.find(".")] + o = int(o) + except: pass if o < 7: if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0: CLANG_FORMAT_BIN = 'clang-format-7' diff --git a/libtokencap/Makefile b/libtokencap/Makefile index 6e1319d8..b1313430 100644 --- a/libtokencap/Makefile +++ b/libtokencap/Makefile @@ -20,6 +20,7 @@ VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) CFLAGS ?= -O3 -funroll-loops -I ../include/ CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign +LDFLAGS += -ldl ifeq "$(shell uname)" "Linux" TARGETS = libtokencap.so diff --git a/libtokencap/libtokencap.so.c b/libtokencap/libtokencap.so.c index eea6d29f..e16fb772 100644 --- a/libtokencap/libtokencap.so.c +++ b/libtokencap/libtokencap.so.c @@ -19,27 +19,50 @@ */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include <stdio.h> #include <string.h> #include <ctype.h> #include <unistd.h> #include <fcntl.h> +#include <stdbool.h> #include "../types.h" #include "../config.h" -#if !defined __linux__ && !defined __APPLE__ && !defined __FreeBSD__ && !defined __OpenBSD__ && !defined __NetBSD__ -# error "Sorry, this library is unsupported in this platform for now!" -#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ && ! __OpenBSD__ && !__NetBSD__*/ +#if !defined __linux__ && !defined __APPLE__ && !defined __FreeBSD__ && \ + !defined __OpenBSD__ && !defined __NetBSD__ +#error "Sorry, this library is unsupported in this platform for now!" +#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ && ! __OpenBSD__ && \ + !__NetBSD__*/ #if defined __APPLE__ -# include <mach/vm_map.h> -# include <mach/mach_init.h> +#include <mach/vm_map.h> +#include <mach/mach_init.h> #elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ -# include <sys/types.h> -# include <sys/sysctl.h> -# include <sys/user.h> -# include <sys/mman.h> +#include <sys/types.h> +#include <sys/sysctl.h> +#include <sys/user.h> +#include <sys/mman.h> +#endif + +#include <dlfcn.h> + +#ifdef RTLD_NEXT +/* The libc functions are a magnitude faster than our replacements. + Use them when RTLD_NEXT is available. */ +int (*__libc_strcmp)(const char* str1, const char* str2); +int (*__libc_strncmp)(const char* str1, const char* str2, size_t len); +int (*__libc_strcasecmp)(const char* str1, const char* str2); +int (*__libc_strncasecmp)(const char* str1, const char* str2, size_t len); +int (*__libc_memcmp)(const void* mem1, const void* mem2, size_t len); +int (*__libc_bcmp)(const void* mem1, const void* mem2, size_t len); +char* (*__libc_strstr)(const char* haystack, const char* needle); +char* (*__libc_strcasestr)(const char* haystack, const char* needle); +void* (*__libc_memmem)(const void* haystack, size_t haystack_len, + const void* needle, size_t needle_len); #endif /* Mapping data and such */ @@ -50,7 +73,7 @@ static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS]; static u32 __tokencap_ro_cnt; static u8 __tokencap_ro_loaded; -static int __tokencap_out_file = -1; +static int __tokencap_out_file = -1; static pid_t __tokencap_pid = -1; /* Identify read-only regions in memory. Only parameters that fall into these @@ -88,49 +111,60 @@ static void __tokencap_load_mappings(void) { #elif defined __APPLE__ struct vm_region_submap_info_64 region; - mach_msg_type_number_t cnt = VM_REGION_SUBMAP_INFO_COUNT_64; - vm_address_t base = 0; - vm_size_t size = 0; - natural_t depth = 0; + mach_msg_type_number_t cnt = VM_REGION_SUBMAP_INFO_COUNT_64; + vm_address_t base = 0; + vm_size_t size = 0; + natural_t depth = 0; __tokencap_ro_loaded = 1; while (1) { if (vm_region_recurse_64(mach_task_self(), &base, &size, &depth, - (vm_region_info_64_t)®ion, &cnt) != KERN_SUCCESS) break; + (vm_region_info_64_t)®ion, + &cnt) != KERN_SUCCESS) + break; if (region.is_submap) { - depth++; + + depth++; + } else { - /* We only care of main map addresses and the read only kinds */ - if ((region.protection & VM_PROT_READ) && !(region.protection & VM_PROT_WRITE)) { - __tokencap_ro[__tokencap_ro_cnt].st = (void *)base; - __tokencap_ro[__tokencap_ro_cnt].en = (void *)(base + size); - if (++__tokencap_ro_cnt == MAX_MAPPINGS) break; - } + /* We only care of main map addresses and the read only kinds */ + if ((region.protection & VM_PROT_READ) && + !(region.protection & VM_PROT_WRITE)) { + + __tokencap_ro[__tokencap_ro_cnt].st = (void*)base; + __tokencap_ro[__tokencap_ro_cnt].en = (void*)(base + size); + + if (++__tokencap_ro_cnt == MAX_MAPPINGS) break; + + } + } + } #elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ -#if defined __FreeBSD__ - int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid}; +#if defined __FreeBSD__ + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid}; #elif defined __OpenBSD__ int mib[] = {CTL_KERN, KERN_PROC_VMMAP, __tokencap_pid}; #elif defined __NetBSD__ - int mib[] = {CTL_VM, VM_PROC, VM_PROC_MAP, __tokencap_pid, sizeof(struct kinfo_vmentry)}; + int mib[] = {CTL_VM, VM_PROC, VM_PROC_MAP, __tokencap_pid, + sizeof(struct kinfo_vmentry)}; #endif - char *buf, *low, *high; - size_t miblen = sizeof(mib)/sizeof(mib[0]); + char * buf, *low, *high; + size_t miblen = sizeof(mib) / sizeof(mib[0]); size_t len; if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) return; #if defined __FreeBSD__ || defined __NetBSD__ len = len * 4 / 3; -#elif defined __OpenBSD__ +#elif defined __OpenBSD__ len -= len % sizeof(struct kinfo_vmentry); #endif @@ -139,8 +173,8 @@ static void __tokencap_load_mappings(void) { if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) { - munmap(buf, len); - return; + munmap(buf, len); + return; } @@ -150,41 +184,48 @@ static void __tokencap_load_mappings(void) { __tokencap_ro_loaded = 1; while (low < high) { - struct kinfo_vmentry *region = (struct kinfo_vmentry *)low; + + struct kinfo_vmentry* region = (struct kinfo_vmentry*)low; #if defined __FreeBSD__ || defined __NetBSD__ -#if defined __FreeBSD__ - size_t size = region->kve_structsize; +#if defined __FreeBSD__ + size_t size = region->kve_structsize; - if (size == 0) break; + if (size == 0) break; #elif defined __NetBSD__ - size_t size = sizeof (*region); + size_t size = sizeof(*region); #endif - /* We go through the whole mapping of the process and track read-only addresses */ - if ((region->kve_protection & KVME_PROT_READ) && - !(region->kve_protection & KVME_PROT_WRITE)) { + /* We go through the whole mapping of the process and track read-only + * addresses */ + if ((region->kve_protection & KVME_PROT_READ) && + !(region->kve_protection & KVME_PROT_WRITE)) { #elif defined __OpenBSD__ - size_t size = sizeof (*region); + size_t size = sizeof(*region); + + /* We go through the whole mapping of the process and track read-only + * addresses */ + if ((region->kve_protection & KVE_PROT_READ) && + !(region->kve_protection & KVE_PROT_WRITE)) { - /* We go through the whole mapping of the process and track read-only addresses */ - if ((region->kve_protection & KVE_PROT_READ) && - !(region->kve_protection & KVE_PROT_WRITE)) { #endif - __tokencap_ro[__tokencap_ro_cnt].st = (void *)region->kve_start; - __tokencap_ro[__tokencap_ro_cnt].en = (void *)region->kve_end; + __tokencap_ro[__tokencap_ro_cnt].st = (void*)region->kve_start; + __tokencap_ro[__tokencap_ro_cnt].en = (void*)region->kve_end; + + if (++__tokencap_ro_cnt == MAX_MAPPINGS) break; + + } - if (++__tokencap_ro_cnt == MAX_MAPPINGS) break; - } + low += size; - low += size; } munmap(buf, len); #endif + } /* Check an address against the list of read-only mappings. */ @@ -237,9 +278,9 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) { buf[pos] = 0; - int wrt_ok = ( 1 == write(__tokencap_out_file, "\"", 1)); - wrt_ok &= (pos == write(__tokencap_out_file, buf, pos)); - wrt_ok &= (2 == write(__tokencap_out_file, "\"\n", 2)); + int wrt_ok = (1 == write(__tokencap_out_file, "\"", 1)); + wrt_ok &= (pos == write(__tokencap_out_file, buf, pos)); + wrt_ok &= (2 == write(__tokencap_out_file, "\"\n", 2)); } @@ -253,6 +294,10 @@ int strcmp(const char* str1, const char* str2) { if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1); if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1); +#ifdef RTLD_NEXT + if (__libc_strcmp) return __libc_strcmp(str1, str2); +#endif + while (1) { const unsigned char c1 = *str1, c2 = *str2; @@ -273,6 +318,10 @@ int strncmp(const char* str1, const char* str2, size_t len) { if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1); if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1); +#ifdef RTLD_NEXT + if (__libc_strncmp) return __libc_strncmp(str1, str2, len); +#endif + while (len--) { unsigned char c1 = *str1, c2 = *str2; @@ -295,6 +344,10 @@ int strcasecmp(const char* str1, const char* str2) { if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1); if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1); +#ifdef RTLD_NEXT + if (__libc_strcasecmp) return __libc_strcasecmp(str1, str2); +#endif + while (1) { const unsigned char c1 = tolower(*str1), c2 = tolower(*str2); @@ -315,6 +368,10 @@ int strncasecmp(const char* str1, const char* str2, size_t len) { if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1); if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1); +#ifdef RTLD_NEXT + if (__libc_strncasecmp) return __libc_strncasecmp(str1, str2, len); +#endif + while (len--) { const unsigned char c1 = tolower(*str1), c2 = tolower(*str2); @@ -337,8 +394,12 @@ int memcmp(const void* mem1, const void* mem2, size_t len) { if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0); if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0); - const char *strmem1 = (const char *)mem1; - const char *strmem2 = (const char *)mem2; +#ifdef RTLD_NEXT + if (__libc_memcmp) return __libc_memcmp(mem1, mem2, len); +#endif + + const char* strmem1 = (const char*)mem1; + const char* strmem2 = (const char*)mem2; while (len--) { @@ -360,8 +421,12 @@ int bcmp(const void* mem1, const void* mem2, size_t len) { if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0); if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0); - const char *strmem1 = (const char *)mem1; - const char *strmem2 = (const char *)mem2; +#ifdef RTLD_NEXT + if (__libc_bcmp) return __libc_bcmp(mem1, mem2, len); +#endif + + const char* strmem1 = (const char*)mem1; + const char* strmem2 = (const char*)mem2; while (len--) { @@ -373,6 +438,7 @@ int bcmp(const void* mem1, const void* mem2, size_t len) { } return 0; + } #undef strstr @@ -384,6 +450,10 @@ char* strstr(const char* haystack, const char* needle) { if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1); +#ifdef RTLD_NEXT + if (__libc_strstr) return __libc_strstr(haystack, needle); +#endif + do { const char* n = needle; @@ -409,6 +479,10 @@ char* strcasestr(const char* haystack, const char* needle) { if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1); +#ifdef RTLD_NEXT + if (__libc_strcasestr) return __libc_strcasestr(haystack, needle); +#endif + do { const char* n = needle; @@ -427,26 +501,32 @@ char* strcasestr(const char* haystack, const char* needle) { #undef memmem -void* memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len) -{ - if (__tokencap_is_ro(haystack)) - __tokencap_dump(haystack, haystack_len, 1); +void* memmem(const void* haystack, size_t haystack_len, const void* needle, + size_t needle_len) { + + if (__tokencap_is_ro(haystack)) __tokencap_dump(haystack, haystack_len, 1); if (__tokencap_is_ro(needle)) __tokencap_dump(needle, needle_len, 1); - const char *n = (const char *)needle; - const char *h = (const char *)haystack; +#ifdef RTLD_NEXT + if (__libc_memmem) + return __libc_memmem(haystack, haystack_len, needle, needle_len); +#endif + + const char* n = (const char*)needle; + const char* h = (const char*)haystack; if (haystack_len < needle_len) return 0; - if (needle_len == 0) return (void *)haystack; + if (needle_len == 0) return (void*)haystack; if (needle_len == 1) return memchr(haystack, *n, haystack_len); - const char *end = h + (haystack_len - needle_len); + const char* end = h + (haystack_len - needle_len); do { if (*h == *n) { - if (memcmp(h, n, needle_len) == 0) return (void *)h; + if (memcmp(h, n, needle_len) == 0) return (void*)h; + } } while (h++ <= end); @@ -455,6 +535,158 @@ void* memmem(const void *haystack, size_t haystack_len, const void *needle, size } +/* Common libraries wrappers (from honggfuzz) */ + +/* + * Apache's httpd wrappers + */ +int ap_cstr_casecmp(const char* s1, const char* s2) { + + return strcasecmp(s1, s2); + +} + +int ap_cstr_casecmpn(const char* s1, const char* s2, size_t n) { + + return strncasecmp(s1, s2, n); + +} + +const char* ap_strcasestr(const char* s1, const char* s2) { + + return strcasestr(s1, s2); + +} + +int apr_cstr_casecmp(const char* s1, const char* s2) { + + return strcasecmp(s1, s2); + +} + +int apr_cstr_casecmpn(const char* s1, const char* s2, size_t n) { + + return strncasecmp(s1, s2, n); + +} + +/* + * *SSL wrappers + */ +int CRYPTO_memcmp(const void* m1, const void* m2, size_t len) { + + return memcmp(m1, m2, len); + +} + +int OPENSSL_memcmp(const void* m1, const void* m2, size_t len) { + + return memcmp(m1, m2, len); + +} + +int OPENSSL_strcasecmp(const char* s1, const char* s2) { + + return strcasecmp(s1, s2); + +} + +int OPENSSL_strncasecmp(const char* s1, const char* s2, size_t len) { + + return strncasecmp(s1, s2, len); + +} + +int32_t memcmpct(const void* s1, const void* s2, size_t len) { + + return memcmp(s1, s2, len); + +} + +/* + * libXML wrappers + */ +int xmlStrncmp(const char* s1, const char* s2, int len) { + + if (len <= 0) { return 0; } + if (s1 == s2) { return 0; } + if (s1 == NULL) { return -1; } + if (s2 == NULL) { return 1; } + return strncmp(s1, s2, (size_t)len); + +} + +int xmlStrcmp(const char* s1, const char* s2) { + + if (s1 == s2) { return 0; } + if (s1 == NULL) { return -1; } + if (s2 == NULL) { return 1; } + return strcmp(s1, s2); + +} + +int xmlStrEqual(const char* s1, const char* s2) { + + if (s1 == s2) { return 1; } + if (s1 == NULL) { return 0; } + if (s2 == NULL) { return 0; } + if (strcmp(s1, s2) == 0) { return 1; } + return 0; + +} + +int xmlStrcasecmp(const char* s1, const char* s2) { + + if (s1 == s2) { return 0; } + if (s1 == NULL) { return -1; } + if (s2 == NULL) { return 1; } + return strcasecmp(s1, s2); + +} + +int xmlStrncasecmp(const char* s1, const char* s2, int len) { + + if (len <= 0) { return 0; } + if (s1 == s2) { return 0; } + if (s1 == NULL) { return -1; } + if (s2 == NULL) { return 1; } + return strncasecmp(s1, s2, (size_t)len); + +} + +const char* xmlStrstr(const char* haystack, const char* needle) { + + if (haystack == NULL) { return NULL; } + if (needle == NULL) { return NULL; } + return strstr(haystack, needle); + +} + +const char* xmlStrcasestr(const char* haystack, const char* needle) { + + if (haystack == NULL) { return NULL; } + if (needle == NULL) { return NULL; } + return strcasestr(haystack, needle); + +} + +/* + * Samba wrappers + */ +int memcmp_const_time(const void* s1, const void* s2, size_t n) { + + return memcmp(s1, s2, n); + +} + +bool strcsequal(const void* s1, const void* s2) { + + if (s1 == s2) { return true; } + if (!s1 || !s2) { return false; } + return (strcmp(s1, s2) == 0); + +} + /* Init code to open the output file (or default to stderr). */ __attribute__((constructor)) void __tokencap_init(void) { @@ -464,10 +696,24 @@ __attribute__((constructor)) void __tokencap_init(void) { if (__tokencap_out_file == -1) __tokencap_out_file = STDERR_FILENO; __tokencap_pid = getpid(); +#ifdef RTLD_NEXT + __libc_strcmp = dlsym(RTLD_NEXT, "strcmp"); + __libc_strncmp = dlsym(RTLD_NEXT, "strncmp"); + __libc_strcasecmp = dlsym(RTLD_NEXT, "strcasecmp"); + __libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp"); + __libc_memcmp = dlsym(RTLD_NEXT, "memcmp"); + __libc_bcmp = dlsym(RTLD_NEXT, "bcmp"); + __libc_strstr = dlsym(RTLD_NEXT, "strstr"); + __libc_strcasestr = dlsym(RTLD_NEXT, "strcasestr"); + __libc_memmem = dlsym(RTLD_NEXT, "memmem"); +#endif + } /* closing as best as we can the tokens file */ __attribute__((destructor)) void __tokencap_shutdown(void) { + if (__tokencap_out_file != STDERR_FILENO) close(__tokencap_out_file); + } |