배경

배경

/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 방식이 있다면 좋을 것입니다 :)

고쳐 쓰다

좋은 해결책/대답은 무엇입니까?

좋은 솔루션/대답의 기준은 이상적으로는 스푸핑된 파일이 애초에 사용자가 쓸 수 없어야 함에도 불구하고 루트 사용자의 상호 작용 없이 "특정 프로세스에 대한 다른 파일 콘텐츠"를 얻을 수 있다는 것입니다.

또 다른 좋은 기준은 프로세스에 의해 표시되는 파일 수정이 프로세스별로 이루어지며 경쟁 조건이 없는 것이 바람직하다는 것입니다.

배경

/usr/lib/firefox/omni.jaMozilla Firefox는 많은 Firefox 코드 ( 대부분 Javascript로 작성된 항목)가 포함된 2개의 zip 아카이브를 사용합니다 /usr/lib/firefox/browser/omni.ja. 파일을 스푸핑하여 내 Firefox 버전을 수정할 수 있습니다(Dropped가 제공하는 경우 더 이상 확장으로 구현할 수 없는 일부 항목 포함). XPCOM을 지원하며 애드온 서명 시행을 좋아하지 않습니다)

답변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프로그램이 어떤 라이브러리를 호출하는지 확인하세요.

관련 정보