プログラムを実行し、システムコールを傍受してリダイレクトします。

プログラムを実行し、システムコールを傍受してリダイレクトします。

プログラムを実行したいのですが、プログラムが特定のファイルを読み取ろうとしたときに選択した他のファイルを読み取るようにしたいと思います。

特に、プログラムは構成ファイルを読み取ろうとしますが、設計が誤っているため、ユーザーは構成ファイルの場所を指定できません。また、プログラムが読み取ろうとしている場所でファイルを編集する権限もありません。

私はそれが可能であることを知っています発覚プログラムは作成されたシステムコールを使用しstraceopen()からプログラムを実行すると、プログラムが作成したシステムコールのみを表示できます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

これを変更するには、偽のライブラリが必要ですopenfakeopen.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)必要があります。

おすすめ記事