我知道,我可以通过中断gdb中的进程,使用文件描述符关闭,然后用我想要的文件名重新打开来更改程序写入的文件。有办法在运行时做同样的事情吗?
例如,我知道我想要更改的文件使用文件描述符5,所以我尝试了
./myexe 5>/dev/null
但是所做的只是改变事情,所以感兴趣的文件就在fd=6上了。
发布于 2015-06-22 23:35:27
当一个程序打开一个文件时,该文件最终被放在一个文件描述符上,该描述符当时是免费的。通过在程序开始之前打开一个文件,您只会使另一个文件描述符忙碌,因此您感兴趣的文件可能会以另一个描述符结束。如果希望程序打开不同的文件,则需要在打开操作发生时修改该操作,或在此之后进行干预。
修改操作的一种方法是在程序和系统库之间插入一些代码,由预压编写一小部分代码。这假设程序是动态链接的二进制文件,或者是由动态链接的二进制程序执行的脚本(即它不是静态链接的)。将以下代码写入文件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;
}使用以下命令编译(对于Linux,其他Unix变体可能需要不同的选项)。注意要覆盖的路径周围的引号。
gcc -DFROM='"/some/path"' -DTO='"/dev/null"' -D_GNU_SOURCE -O -Wall -fPIC -shared -o override_fopen.so override_fopen.c -ldl按以下方式运行程序(在OSX上,使用DYLD_PRELOAD而不是LD_PRELOAD):
LD_PRELOAD=./override_fopen.so ./myexe这只在程序调用fopen或open库函数时才有效。如果它调用了其他函数,则需要重写该函数。您可以使用ltrace查看程序调用的库是什么。
https://unix.stackexchange.com/questions/211394
复制相似问题