背景

背景

為了解決這個問題,我們假設/path/to/file檔案系統中有一個檔案 ( ),其內容如下:

$> cat /path/to/file
this is the content of the
file /path/to/file 

我對幾乎所有正在運行的進程(並且具有對此文件的讀取訪問權限)以及閱讀此內容感到滿意。
然而應該有(這是問題的核心)是一個特定的進程,在讀取時應/path/to/file提供不同的檔案內容。

$> cat /path/to/file
this is the DIFFERNT content of the
file /path/to/file 

如何以某種方式欺騙特定流程的文件內容?

我的一些猜測,採取哪條路將是與以下相關的解決方案:

  • 符號連結技巧
  • (linux)命名空間(檔案系統命名空間)技巧
  • chroot詭計
  • $LD_PRELOAD掛鉤技巧
  • 覆蓋檔案系統

我的平台是 GNU/linux,但如果有 POSIX 方式來實現那就更好了:)

更新

什麼是好的解決方案/答案?

一個好的解決方案/答案的標準是,可以實現“特定進程的不同文件內容”,而不需要根用戶的交互,即使理想情況下,欺騙文件一開始就不應該是用戶可寫的。

另一個好的標準是對進程顯示的檔案進程的修改是特定的,最好沒有競爭條件。

背景

Mozilla firefox 使用 2 個 zip 檔案/usr/lib/firefox/omni.ja/usr/lib/firefox/browser/omni.ja,其中包含大量的 firefox 程式碼(主要是用 Javascript 編寫的內容),透過欺騙該文件,我將能夠修改我的 firefox 版本(包括一些我無法再實現為擴展,提供了放棄的XPCOM 支援並且不喜歡addon-siging 強制)

答案1

是的,掛載命名空間是一種方法:

$ cat file
foo
$ cat other-file
bar
$ sudo unshare -m zsh -c 'mount --bind other-file file; USERNAME=$SUDO_USER; cat file'
bar
$ cat file
foo

上面用於zsh恢復被劫持的 cat 命令的原始用戶的 uid/gids。

答案2

這是一種方法預先載入透過一小段程式碼在程式和系統庫之間插入一些程式碼。這假設該程式是動態連結的二進位文件,或是由動態連結的二進位檔案執行的腳本(即它不是靜態連結的)。將以下程式碼寫入檔案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='"/path/to/file"' -DTO='"/path/to/alternate/content"' -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查看程式呼叫了哪些函式庫。

相關內容