Initial commit
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.idea/
|
||||||
|
bin/
|
||||||
|
*.so
|
||||||
|
*.o
|
||||||
5
README.md
Normal file
5
README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
Bachelor's Thesis
|
||||||
|
=================
|
||||||
|
|
||||||
|
See [doc/](doc) for more details.
|
||||||
59
doc/README.md
Normal file
59
doc/README.md
Normal file
@@ -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 <stdlib.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
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_<symbol>`
|
||||||
|
* Call to real function inside wrapper: `__real_<symbol>`
|
||||||
|
* Works for *all* functions
|
||||||
|
* Works only on dynamically linked executables
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```c
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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
|
||||||
1
proj/test1/.gitignore
vendored
Normal file
1
proj/test1/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/main
|
||||||
17
proj/test1/Makefile
Normal file
17
proj/test1/Makefile
Normal file
@@ -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
|
||||||
39
proj/test1/src/main.c
Normal file
39
proj/test1/src/main.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
105
proj/test1/src/test.c
Normal file
105
proj/test1/src/test.c
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
0
thesis/thesis.tex
Normal file
0
thesis/thesis.tex
Normal file
Reference in New Issue
Block a user