2

I would like to run a program, and when that program attempts to read a specific file, I would like it to read a different file of my choosing instead.

Specifically, the program attempts to read a configuration file, and is poorly designed and doesn't allow the user to specify the location of the configuration file. I also don't have permission to edit the file at the location the program attempts to read from.

I know it's possible to detect syscalls made by the program using strace, and I am able to see the sole open() syscall made by the program by running it under strace. It there any way to intercept that syscall and change it's behaviour to open a different file of my choice?

0

1 Answer 1

4

LD_PRELOAD can do this on linux; first up our application to modify, app.c

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    char c;
    int fd;
    fd = open(*++argv, O_RDONLY);
    read(fd, &c, 1);
    printf("%c\n", c);
    return 0;
}

which serves to read a character from a file:

$ make app
cc     app.c   -o app
$ echo a > a
$ echo b > b
$ ./app a ; ./app b
a
b

changing this up requires a library that fakes out open, fakeopen.c:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

typedef int (*orig_open) (const char *path, int oflag, ...);

int open(const char *path, int oflag, ...)
{
    orig_open fn;
    mode_t cmode = 0;
    va_list ap;
    if ((oflag & O_CREAT) == O_CREAT) {
        va_start(ap, oflag);
        cmode = (mode_t) va_arg(ap, int);
        va_end(ap);
    }
    if (strncmp(path, "a", 2) == 0)
        path = getenv("FAKE");
    fn = (orig_open) dlsym(RTLD_NEXT, "open");
    return fn(path, oflag, cmode);
}

which when compiled and used via LD_PRELOAD and when the filename is what we're looking for and assuming FAKE has something that is the path:

$ cat Makefile
fakeopen.so: fakeopen.c
    $(CC) $(CFLAGS) -shared -fPIC -ldl fakeopen.c -o fakeopen.so
$ rm fakeopen.so
$ cat Makefile
fakeopen.so: fakeopen.c
    $(CC) $(CFLAGS) -shared -fPIC -ldl fakeopen.c -o fakeopen.so
$ make fakeopen.so
cc  -shared -fPIC -ldl fakeopen.c -o fakeopen.so
$ FAKE=b LD_PRELOAD=`pwd`/fakeopen.so ./app a
b

we can make ./app a instead read file b. Of course there will need to be more error checking and other rakes that may be stepped on, but this should be the gist of modifying an open(2) call.

2
  • that will only work if open(2) is called directly, not via fopen(3); eg. your fakeopen.so will work will cat file but not with sort file. And it's the same with all libc functions that call open(2) internally.
    – user313992
    Nov 27, 2018 at 13:27
  • 1
    This is not syscall redirection, it's redirection of calls to functions defined in shared objects.
    – larsw
    Nov 30, 2022 at 11:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .