From ab0b73af5b2f2c3a4ee651e815d6c0a6ce1f3386 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Mon, 30 Dec 2024 19:35:44 +0100 Subject: [PATCH] Initial commit --- .gitignore | 4 ++ README.md | 5 ++ doc/README.md | 59 ++++++++++++++++++++++++ proj/test1/.gitignore | 1 + proj/test1/Makefile | 17 +++++++ proj/test1/src/main.c | 39 ++++++++++++++++ proj/test1/src/test.c | 105 ++++++++++++++++++++++++++++++++++++++++++ thesis/thesis.tex | 0 8 files changed, 230 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 doc/README.md create mode 100644 proj/test1/.gitignore create mode 100644 proj/test1/Makefile create mode 100644 proj/test1/src/main.c create mode 100644 proj/test1/src/test.c create mode 100644 thesis/thesis.tex diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..102b9f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea/ +bin/ +*.so +*.o diff --git a/README.md b/README.md new file mode 100644 index 0000000..87396c7 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ + +Bachelor's Thesis +================= + +See [doc/](doc) for more details. diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..dea3ab1 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,59 @@ + +Intercepting Function/System Calls in Linux +=========================================== + +Option 1: `LD_PRELOAD` +---------------------- + +* No need to re-link +* Works for *all* functions +* Works only on dynamically linked executables + +Example: +```c +#include +#include +#include + +void *malloc(size_t size) { + // before call to malloc + void *(* _malloc)(size_t); + if ((_malloc = dlsym(RTLD_NEXT, "malloc")) == NULL) { + errno = ENOSYS; + return NULL; + } + void *ret = _malloc(size); + // after call to malloc + return ret; +} +``` + + +Option 2: `gcc --wrap` +---------------------- + +* Need to re-link +* Relatively simple code: + * Function name: `__wrap_` + * Call to real function inside wrapper: `__real_` +* Works for *all* functions +* Works only on dynamically linked executables + +Example: +```c +#include + +void *__wrap_malloc(size_t size) { + // before call to malloc + void *ret = __real_malloc(size); + // after call to malloc + return ret; +} +``` + + +Option 3: Linux kernel +---------------------- + +* Only works with Linux system calls +* Also works with statically linked executables diff --git a/proj/test1/.gitignore b/proj/test1/.gitignore new file mode 100644 index 0000000..95811e0 --- /dev/null +++ b/proj/test1/.gitignore @@ -0,0 +1 @@ +/main diff --git a/proj/test1/Makefile b/proj/test1/Makefile new file mode 100644 index 0000000..52a67d0 --- /dev/null +++ b/proj/test1/Makefile @@ -0,0 +1,17 @@ + +CC=gcc +CFLAGS=-std=c99 -pedantic -Wall -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_POSIX_C_SOURCE=200809L -g +LDFLAGS=-lc + +.PHONY: all clean +all: default +default: main test.so + +test.so: src + $(CC) -shared -fPIC -o $@ $< $(CFLAGS) $(LDFLAGS) + +main: src + $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) + +clean: + rm -rf main test.so diff --git a/proj/test1/src/main.c b/proj/test1/src/main.c new file mode 100644 index 0000000..3c311b4 --- /dev/null +++ b/proj/test1/src/main.c @@ -0,0 +1,39 @@ + +#include +#include +#include +#include +#include + +static void usage(const char *prog_name) { + fprintf(stderr, "usage: %s [-a]\n", prog_name); + exit(1); +} + +void do_something(void) { + printf("Hello World!\n"); + void *mem = malloc(123); + if (mem == NULL) { + fprintf(stderr, "Unable to malloc: %s\n", strerror(errno)); + return; + } + printf("%p\n", mem); + free(mem); +} + +int main(const int argc, char *const argv[]) { + for (int ch; (ch = getopt(argc, argv, "a")) != -1;) { + switch (ch) { + case 'a': + break; + default: + usage(argv[0]); + } + } + if (optind != argc) + usage(argv[0]); + + do_something(); + do_something(); + do_something(); +} diff --git a/proj/test1/src/test.c b/proj/test1/src/test.c new file mode 100644 index 0000000..feeb3c7 --- /dev/null +++ b/proj/test1/src/test.c @@ -0,0 +1,105 @@ + +#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); +} + +void *malloc(size_t size) { + fprintf(stderr, PREFIX "malloc(%li)\n", size); + void *(* _malloc)(size_t); + if ((_malloc = dlsym(RTLD_NEXT, "malloc")) == NULL) { + errno = ENOSYS; + return NULL; + } + void *ret = _malloc(size); + fprintf(stderr, PREFIX "-> %p\n", ret); + return ret; +} + +void *calloc(size_t nmemb, size_t size) { + fprintf(stderr, PREFIX "calloc(%li, %li)\n", nmemb, size); + void *(* _calloc)(size_t, size_t); + if ((_calloc = dlsym(RTLD_NEXT, "calloc")) == NULL) { + errno = ENOSYS; + return NULL; + } + void *ret = _calloc(nmemb, size); + fprintf(stderr, PREFIX "-> %p\n", ret); + return ret; +} + +void *realloc(void *ptr, size_t size) { + fprintf(stderr, PREFIX "realloc(%p, %li)\n", ptr, size); + void *(* _realloc)(void *, size_t); + if ((_realloc = dlsym(RTLD_NEXT, "realloc")) == NULL) { + errno = ENOSYS; + return NULL; + } + void *ret = _realloc(ptr, size); + fprintf(stderr, PREFIX "-> %p\n", ret); + return ret; +} + +void free(void *ptr) { + fprintf(stderr, PREFIX "free(%p)\n", ptr); + void (* _free)(void *); + if ((_free = dlsym(RTLD_NEXT, "free")) == NULL) { + errno = ENOSYS; + return; + } + _free(ptr); + fprintf(stderr, PREFIX "-> void\n"); +} + +int 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 (* _getopt)(int, char *const[], const char *); + if ((_getopt = dlsym(RTLD_NEXT, "getopt")) == NULL) { + errno = ENOSYS; + return -1; + } + int ret = _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; +} diff --git a/thesis/thesis.tex b/thesis/thesis.tex new file mode 100644 index 0000000..e69de29