/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方式があれば良いでしょう:)
修正する
良い解決策/答えは何ですか?
良い解決策/答えの基準は、理想的には、偽装されたファイルが最初にユーザーが書き込むことができないにもかかわらず、rootユーザーとの対話なしに「特定のプロセス用の他のファイルコンテンツ」を取得できることです。
もう一つの良い基準は、プロセスによって表示されるファイルの変更がプロセスごとに行われ、競合状態がないことが望ましいことです。
背景
/usr/lib/firefox/omni.ja
Mozilla Firefoxは、多くのFirefoxコード(ほとんどのJavascriptで書かれた項目)を含む2つのzipアーカイブを使用します/usr/lib/firefox/browser/omni.ja
。ファイルをスプーフィングしてFirefoxのバージョンを変更することができます(Droppedが提供している場合は拡張機能で実装できなくなったいくつかのアイテムを含む)。 XPCOMをサポートし、アドオン署名の実施が好きではありません)
答え1
はい、名前空間をマウントする方法は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
この方法は、プログラムが呼び出すfopen
かopen
ライブラリ関数を呼び出す場合にのみ機能します。別の関数を呼び出す場合は、その関数をオーバーライドする必要があります。あなたはそれを使用することができますltrace
プログラムがどのライブラリを呼び出すかを確認してください。