Redireciona um descritor de arquivo antes da execução

2

Eu sei que posso alterar o arquivo que um programa grava interrompendo o processo no gdb, fechando usando o descritor de arquivo e, em seguida, reabrindo com o nome do arquivo que eu quero. Existe uma maneira de fazer a mesma coisa em tempo de execução?

Por exemplo, eu sei que o arquivo que eu quero mudar usa o descritor de arquivo 5, então eu tentei

./myexe 5>/dev/null

Mas tudo o que isso faz é mudar as coisas para que o arquivo de interesse esteja em fd = 6.

    
por user3856370 22.06.2015 / 19:36

1 resposta

5

Quando um programa abre um arquivo, esse arquivo termina em um descritor de arquivo que é gratuito no momento. Ao abrir um arquivo antes do início do programa, você só estará fazendo mais um descritor de arquivo ocupado, para que o arquivo em que você está interessado possa acabar em um descritor diferente. Se você quiser que o programa abra um arquivo diferente, você precisará modificar a operação de abertura quando ocorrer, ou intervir depois.

Uma maneira de modificar a operação é colocar algum código entre o programa e a biblioteca do sistema, por pré-carregando um pequeno pedaço de código. Isso pressupõe que o programa é um binário vinculado dinamicamente, ou um script executado por um binário vinculado dinamicamente (ou seja, ele não está vinculado estaticamente). Escreva o seguinte código em um arquivo override_fopen.c :

#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifndef FROM
#error "Define FROM to the path to override in double quotes, e.g. -DFROM='\"/bad\"'"
#endif
#ifndef TO
#error "Define TO to the path to use instead in double quotes, e.g. -DFROM='\"/good\"'"
#endif
FILE *fopen(const char *path, const char *mode) {
    void *(*original_fopen)(const char *, const char *) = dlsym(RTLD_NEXT, "fopen");
    if (!strcmp(path, FROM)) {
        path = TO;
    }
    return original_fopen(path, mode);
}
int open(const char *path, int oflag, ...) {
    int (*original_open)(const char *, int, ...) = dlsym(RTLD_NEXT, "open");
    int ret;
    va_list args;
    if (!strcmp(path, FROM)) {
        path = TO;
    }
    va_start(args, oflag);
    if (oflag & O_CREAT) {
        ret = original_open(path, oflag, (mode_t)va_arg(args, mode_t));
    } else {
        ret = original_open(path, oflag);
    }
    va_end(args);
    return ret;
}

Compile com o seguinte comando (para o Linux, outras variantes do Unix podem exigir opções diferentes). Observe as aspas ao redor do caminho que você deseja substituir.

gcc -DFROM='"/some/path"' -DTO='"/dev/null"' -D_GNU_SOURCE -O -Wall -fPIC -shared -o override_fopen.so override_fopen.c -ldl

Execute o programa da seguinte maneira (no OSX, use DYLD_PRELOAD em vez de LD_PRELOAD ):

LD_PRELOAD=./override_fopen.so ./myexe

Isso só funciona se o programa estiver chamando a função de biblioteca fopen ou open . Se ele chamar outra função, você precisará substituir essa. Você pode usar ltrace para ver que biblioteca chama o programa.

    
por 23.06.2015 / 01:35

Tags