나는 gdb의 프로세스를 중단하고 파일 설명자로 닫은 다음 원하는 파일 이름으로 다시 열어 프로그램이 쓰는 파일을 변경할 수 있다는 것을 알고 있습니다. 런타임에 동일한 작업을 수행할 수 있는 방법이 있습니까?
예를 들어, 내가 변경하려는 파일이 파일 설명자 5를 사용한다는 것을 알고 있으므로
./myexe 5>/dev/null
하지만 몇 가지 사항만 변경하면 관심 있는 파일이 fd=6에 있게 됩니다.
답변1
프로그램이 파일을 열면 해당 파일은 당시 사용 가능한 파일 설명자에 저장됩니다. 프로그램이 시작되기 전에 파일을 열면 다른 파일 설명자를 사용하게 만들 뿐이므로 관심 있는 파일이 다른 설명자에 있을 수 있습니다. 프로그램이 다른 파일을 열도록 하려면 열기 작업이 진행되는 동안 수정하거나 사후에 개입해야 합니다.
작업을 수정하는 한 가지 방법은 프로그램과 시스템 라이브러리 사이에 일부 코드를 삽입하는 것입니다.사전 로딩작은 코드 조각. 이는 프로그램이 동적으로 링크된 바이너리이거나 동적으로 링크된 바이너리에 의해 실행되는 스크립트라고 가정합니다(즉, 정적으로 링크되지 않음). 파일에 다음 코드를 작성합니다 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='"/some/path"' -DTO='"/dev/null"' -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
프로그램이 어떤 라이브러리를 호출하는지 확인하세요.