tokencap now wraps common routines and uses RTLD_NEXT
MODIFY
.custom-format.py
.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:
+ 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'

MODIFY
libtokencap/Makefile
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

MODIFY
libtokencap/libtokencap.so.c
libtokencap/libtokencap.so.c
*/
+#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__
+#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__*/
+#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ && ! __OpenBSD__ && \
+ !__NetBSD__*/
#if defined __APPLE__
#include <mach/vm_map.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 */
#define MAX_MAPPINGS 1024
@@ -98,19 +121,29 @@ static void __tokencap_load_mappings(void) {
while (1) {
if (vm_region_recurse_64(mach_task_self(), &base, &size, &depth,
- (vm_region_info_64_t)&region, &cnt) != KERN_SUCCESS) break;
+ (vm_region_info_64_t)&region,
+ &cnt) != KERN_SUCCESS)
+ break;
if (region.is_submap) {
+
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)) {
+ 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__
@@ -120,7 +153,8 @@ static void __tokencap_load_mappings(void) {
#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]);
@@ -150,6 +184,7 @@ static void __tokencap_load_mappings(void) {
__tokencap_ro_loaded = 1;
while (low < high) {
+
struct kinfo_vmentry* region = (struct kinfo_vmentry*)low;
#if defined __FreeBSD__ || defined __NetBSD__
@@ -162,7 +197,8 @@ static void __tokencap_load_mappings(void) {
size_t size = sizeof(*region);
#endif
- /* We go through the whole mapping of the process and track read-only addresses */
+ /* 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)) {
@@ -170,21 +206,26 @@ static void __tokencap_load_mappings(void) {
size_t size = sizeof(*region);
- /* We go through the whole mapping of the process and track read-only addresses */
+ /* 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;
if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
+
}
low += size;
+
}
munmap(buf, len);
#endif
+
}
/* Check an address against the list of read-only mappings. */
@@ -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,6 +394,10 @@ 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);
+#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;
@@ -360,6 +421,10 @@ 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);
+#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;
@@ -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,13 +501,18 @@ 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);
+#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;
@@ -447,6 +526,7 @@ void* memmem(const void *haystack, size_t haystack_len, const void *needle, size
if (*h == *n) {
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);
+
}

tokencap now wraps common routines and uses RTLD_NEXT