From 831672663578b555880717c43149efdd5679abf6 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Tue, 31 Dec 2024 12:19:20 +0100 Subject: [PATCH] Add test_wrap.c --- Makefile | 5 ++ README.md | 2 + doc/README.md | 23 +++++- proj/test1/.gitignore | 1 + proj/test1/Makefile | 15 ++-- proj/test1/src/{test.c => test_preload.c} | 10 +-- proj/test1/src/test_wrap.c | 90 +++++++++++++++++++++++ 7 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 Makefile rename proj/test1/src/{test.c => test_preload.c} (93%) create mode 100644 proj/test1/src/test_wrap.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6fb03fd --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +.PHONY: all clean +all: + $(MAKE) -C proj/test1/ +clean: + $(MAKE) -C proj/test1/ diff --git a/README.md b/README.md index 87396c7..ff48b01 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,5 @@ Bachelor's Thesis ================= See [doc/](doc) for more details. + +[LaTeX template](https://www.overleaf.com/latex/templates/thesis-template-tu-wien-faculty-of-informatics-vutinfth/ygcskyrqcrff). diff --git a/doc/README.md b/doc/README.md index dea3ab1..5a1d41d 100644 --- a/doc/README.md +++ b/doc/README.md @@ -8,8 +8,9 @@ Option 1: `LD_PRELOAD` * No need to re-link * Works for *all* functions * Works only on dynamically linked executables +* Intercepts all calls (including stack allocations etc.) -Example: +Example (`preload.c`): ```c #include #include @@ -17,7 +18,7 @@ Example: void *malloc(size_t size) { // before call to malloc - void *(* _malloc)(size_t); + void *(*_malloc)(size_t); if ((_malloc = dlsym(RTLD_NEXT, "malloc")) == NULL) { errno = ENOSYS; return NULL; @@ -28,21 +29,30 @@ void *malloc(size_t size) { } ``` +```shell +# ./main is already compiled and ready +gcc -shared -fPIC -o preload.so preload.c +LD_PRELOAD="$(pwd)/preload.so" ./main +``` + Option 2: `gcc --wrap` ---------------------- -* Need to re-link +* Need to re-link(/-comiple) * Relatively simple code: * Function name: `__wrap_` * Call to real function inside wrapper: `__real_` * Works for *all* functions * Works only on dynamically linked executables +* Intercepts only calls inside the given source file -Example: +Example (`wrap.c`): ```c #include +extern void *__real_malloc(size_t size); + void *__wrap_malloc(size_t size) { // before call to malloc void *ret = __real_malloc(size); @@ -51,6 +61,11 @@ void *__wrap_malloc(size_t size) { } ``` +```shell +gcc -o main_wrapped main.c wrap.c -Wl,--wrap=malloc +./main_wrapped +``` + Option 3: Linux kernel ---------------------- diff --git a/proj/test1/.gitignore b/proj/test1/.gitignore index 95811e0..fb76a04 100644 --- a/proj/test1/.gitignore +++ b/proj/test1/.gitignore @@ -1 +1,2 @@ /main +/main_wrapped diff --git a/proj/test1/Makefile b/proj/test1/Makefile index 52a67d0..d49d6e6 100644 --- a/proj/test1/Makefile +++ b/proj/test1/Makefile @@ -5,13 +5,16 @@ LDFLAGS=-lc .PHONY: all clean all: default -default: main test.so +default: main main_wrapped test_preload.so -test.so: src - $(CC) -shared -fPIC -o $@ $< $(CFLAGS) $(LDFLAGS) +test_preload.so: src/test_preload.c + $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(LDFLAGS) -main: src - $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) +main: src/main.c + $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) + +main_wrapped: src/main.c src/test_wrap.c + $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--wrap=calloc -Wl,--wrap=realloc -Wl,--wrap=getopt clean: - rm -rf main test.so + rm -rf main test_preload.so main_wrapped diff --git a/proj/test1/src/test.c b/proj/test1/src/test_preload.c similarity index 93% rename from proj/test1/src/test.c rename to proj/test1/src/test_preload.c index feeb3c7..cb2afa9 100644 --- a/proj/test1/src/test.c +++ b/proj/test1/src/test_preload.c @@ -37,7 +37,7 @@ static void log_array_str(FILE *out, char *const array[], int n) { void *malloc(size_t size) { fprintf(stderr, PREFIX "malloc(%li)\n", size); - void *(* _malloc)(size_t); + void *(*_malloc)(size_t); if ((_malloc = dlsym(RTLD_NEXT, "malloc")) == NULL) { errno = ENOSYS; return NULL; @@ -49,7 +49,7 @@ void *malloc(size_t size) { void *calloc(size_t nmemb, size_t size) { fprintf(stderr, PREFIX "calloc(%li, %li)\n", nmemb, size); - void *(* _calloc)(size_t, size_t); + void *(*_calloc)(size_t, size_t); if ((_calloc = dlsym(RTLD_NEXT, "calloc")) == NULL) { errno = ENOSYS; return NULL; @@ -61,7 +61,7 @@ void *calloc(size_t nmemb, size_t size) { void *realloc(void *ptr, size_t size) { fprintf(stderr, PREFIX "realloc(%p, %li)\n", ptr, size); - void *(* _realloc)(void *, size_t); + void *(*_realloc)(void *, size_t); if ((_realloc = dlsym(RTLD_NEXT, "realloc")) == NULL) { errno = ENOSYS; return NULL; @@ -73,7 +73,7 @@ void *realloc(void *ptr, size_t size) { void free(void *ptr) { fprintf(stderr, PREFIX "free(%p)\n", ptr); - void (* _free)(void *); + void (*_free)(void *); if ((_free = dlsym(RTLD_NEXT, "free")) == NULL) { errno = ENOSYS; return; @@ -89,7 +89,7 @@ int getopt(const int argc, char *const argv[], const char *shortopts) { log_str(stderr, shortopts); fputs(")\n", stderr); - int (* _getopt)(int, char *const[], const char *); + int (*_getopt)(int, char *const[], const char *); if ((_getopt = dlsym(RTLD_NEXT, "getopt")) == NULL) { errno = ENOSYS; return -1; diff --git a/proj/test1/src/test_wrap.c b/proj/test1/src/test_wrap.c new file mode 100644 index 0000000..f61657f --- /dev/null +++ b/proj/test1/src/test_wrap.c @@ -0,0 +1,90 @@ + +#include +#include +#include + +#define PREFIX "---====[ " + +static void log_str(FILE *out, const char *str) { + fprintf(out, "%p:\"", str); + for (char ch; (ch = *str) != 0; str++) { + if (ch == '\\' || ch == '"') { + fputc('\\', out); + fputc(ch, out); + } else if (ch == '\t') { + fputs("\\t", out); + } else if (ch == '\n') { + fputs("\\n", out); + } else if (ch == '\r') { + fputs("\\r", out); + } else if ((ch >= 0 && ch < 0x20) || ch == 0x7F) { + fprintf(out, "\\x%02x", ch); + } else { + fputc(ch, out); + } + } + fputc('"', out); +} + +static void log_array_str(FILE *out, char *const array[], int n) { + fprintf(out, "%p:[", (void *)array); + for (int i = 0; i < n; i++) { + if (i > 0) fputs(", ", stderr); + log_str(stderr, array[i]); + } + fputc(']', out); +} + +extern void *__real_malloc(size_t size); + +void *__wrap_malloc(size_t size) { + fprintf(stderr, PREFIX "malloc(%li)\n", size); + void *ret = __real_malloc(size); + fprintf(stderr, PREFIX "-> %p\n", ret); + return ret; +} + +extern void *__real_calloc(size_t nmemb, size_t size); + +void *__wrap_calloc(size_t nmemb, size_t size) { + fprintf(stderr, PREFIX "calloc(%li, %li)\n", nmemb, size); + void *ret = __real_calloc(nmemb, size); + fprintf(stderr, PREFIX "-> %p\n", ret); + return ret; +} + +extern void *__real_realloc(void *ptr, size_t size); + +void *__wrap_realloc(void *ptr, size_t size) { + fprintf(stderr, PREFIX "realloc(%p, %li)\n", ptr, size); + void *ret = __real_realloc(ptr, size); + fprintf(stderr, PREFIX "-> %p\n", ret); + return ret; +} + +extern void __real_free(void *ptr); + +void __wrap_free(void *ptr) { + fprintf(stderr, PREFIX "free(%p)\n", ptr); + __real_free(ptr); + fprintf(stderr, PREFIX "-> void\n"); +} + +extern int __real_getopt(int argc, char *const argv[], const char *shortopts); + +int __wrap_getopt(const int argc, char *const argv[], const char *shortopts) { + fprintf(stderr, PREFIX "getopt(%i, ", argc); + log_array_str(stderr, argv, argc); + fputs(", ", stderr); + log_str(stderr, shortopts); + fputs(")\n", stderr); + + int ret = __real_getopt(argc, argv, shortopts); + fprintf(stderr, PREFIX "-> %i", ret); + if (ret >= 0x20 && ret < 0x7F) { + fprintf(stderr, " ('%c')\n", ret); + } else { + fprintf(stderr, "\n"); + } + return ret; +}