プログラムを実行したいのですが、プログラムが特定のファイルを読み取ろうとしたときに選択した他のファイルを読み取るようにしたいと思います。
特に、プログラムは構成ファイルを読み取ろうとしますが、設計が誤っているため、ユーザーは構成ファイルの場所を指定できません。また、プログラムが読み取ろうとしている場所でファイルを編集する権限もありません。
私はそれが可能であることを知っています発覚プログラムは作成されたシステムコールを使用しstrace
、open()
からプログラムを実行すると、プログラムが作成したシステムコールのみを表示できますstrace
。どのような方法がありますか?傍受システムコールを実行し、選択した別のファイルを開くように動作を変更しますか?
答え1
LD_PRELOAD
これはLinuxで行うことができます。まず、アプリケーションを変更する必要があります。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;
}
ファイルから文字を読み取るために使用されます。
$ make app
cc app.c -o app
$ echo a > a
$ echo b > b
$ ./app a ; ./app b
a
b
これを変更するには、偽のライブラリが必要です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);
}
コンパイルして使用するときに、LD_PRELOAD
ファイル名が私たちが探しているものであり、パスがあると仮定するFAKE
とき:
$ 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
./app a
代わりにファイルを読むことができますb
。もちろん、より多くのエラーチェックが必要であり、他の熊手を踏むこともありますが、これが呼び出しを修正するためのポイントであるopen(2)
必要があります。