Executa programa e intercepta e redireciona syscalls

1

Gostaria de executar um programa e, quando esse programa tentar ler um arquivo específico, eu gostaria que ele lesse um arquivo diferente da minha preferência.

Especificamente, o programa tenta ler um arquivo de configuração e é mal projetado e não permite que o usuário especifique o local do arquivo de configuração. Eu também não tenho permissão para editar o arquivo no local onde o programa tenta ler.

Eu sei que é possível detectar syscalls feitas pelo programa usando strace , e eu posso ver a única open() syscall feita pelo programa rodando em strace . Existe alguma maneira de interceptar esse syscall e alterar seu comportamento para abrir um arquivo diferente de minha escolha?

    
por Drew 27.11.2018 / 06:55

1 resposta

3

LD_PRELOAD pode fazer isso no linux; primeiro a nossa aplicação para modificar, 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;
}

que serve para ler um caractere de um arquivo:

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

a alteração requer uma biblioteca que exclua 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);
}

que quando compilado e usado via LD_PRELOAD e quando o nome do arquivo é o que estamos procurando e assumindo FAKE tem algo que é o caminho:

$ 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

podemos fazer ./app a ler o arquivo b . É claro que haverá mais verificação de erros e outros rakes que possam ser aplicados, mas isso deve ser a essência da modificação de uma chamada open(2) .

    
por 27.11.2018 / 07:29