Files

在執行前重定向文件描述符

  • July 21, 2019

我知道我可以通過中斷 gdb 中的程序、使用文件描述符關閉然後使用我想要的文件名重新打開來更改程序寫入的文件。有沒有辦法在執行時做同樣的事情?

例如,我知道我要更改的文件使用文件描述符 5,所以我嘗試了

./myexe 5>/dev/null

但所做的只是改變事情,所以感興趣的文件在 fd=6 上。

當程序打開一個文件時,該文件以當時空閒的文件描述符結束。通過在程序啟動之前打開一個文件,您只會讓一個文件描述符忙碌,因此您感興趣的文件可能最終會出現在不同的描述符上。如果您希望程序打開不同的文件,則需要在打開操作發生時對其進行修改,或者在之後進行干預。

修改操作的一種方法是通過預載入一小段程式碼,在程序和系統庫之間插入一些程式碼。這假定程序是動態連結的二進製文件,或者是由動態連結的二進製文件執行的腳本(即它不是靜態連結的)。將以下程式碼寫入文件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

這僅在程序呼叫fopenopen庫函式時才有效。如果它呼叫其他函式,則需要覆蓋該函式。您可以使用ltrace查看程序呼叫的庫。

引用自:https://unix.stackexchange.com/questions/211394