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)
.