2014-07-25 2 views
1

fopen() 함수를 후크하고 LD_PRELOAD를 사용하여 특정 디렉토리에 대한 액세스를 기록하려고합니다.fopen() 함수가 분할 오류를 던졌습니다.

  1. 첫 번째 질문은 : 파일을 여는 작업을 로그 할 수있을만큼 fopen()을 후크하고 있습니까?
  2. 내 코드에서 세그먼트 오류가 발생합니다. 특히, 코드는이 (무시 오류 검사)과 같다 : FILE* (my_fopen)(const char filename, const char* mode); void* libc_handle;
    void __attribute__ ((constructor)) init(void){ libc_handle = dlopen("libc.so.6", RTLD_LAZY); *(void**)(&my_fopen) = dlsym(libc_handle,"fopen"); } FILE* fopen(const char* filename, const char* mode){ printf("Hello world\n"); return my_fopen(filename, mode); }

컴파일하고 LD_PRELOAD의 새로운 라이브러리를 지정한 후, 나는

ls

를 실행하고 Segmenation 오류가 발생합니다. 그게 왜 일어 났는지 생각해? 심지어 printf()을 삭제하려고했지만 도움이되지 않았습니다.

+0

나는'fopen'보다는'open'을 걸 수 있습니다. –

+0

inotify 고려하셨습니까? –

+0

@MatteoItalia, 나는 열어 보았지만 파일을 여는 데 익숙하지 않았습니다. 나는 fopen()과 같은 것들이 개인적인 방법을 사용한다고 생각한다. 나는 훅 (open)을 – user1734905

답변

4

당신은 아래의 예제에서 수정 된 코드에서 일부 문제가 (나는 또한 관련 헤더를 추가하고 완벽한 프로그램을 제공하기 위해 main를 제공 한) : 어떤에서

#include <stdio.h> 
#include <dlfcn.h> 

FILE* (*my_fopen)(const char *filename, const char* mode); 
void* libc_handle; 

void __attribute__ ((constructor)) init(void){ 
    libc_handle = dlopen("libc.so.6", RTLD_LAZY); 
    my_fopen = dlsym(libc_handle,"fopen"); 
} 
FILE* fopen(const char* filename, const char* mode){ 
    printf("Hello, Pax\n"); 
    return my_fopen(filename, mode); 
} 

int main (void) { 
    FILE *fout = fopen ("xyzzy.txt","w"); 
    fclose (fout); 
    return 0; 
} 

변경을 당신은 다음과 같습니다 :

  • my_fopen 함수 포인터는 정확히 포인터이어야합니다. 나는 당신이 FILE*을 그렇게 만들었다 고 생각할지도 모른다고 생각합니다. 그러나 실제로는 정확하지 않습니다. FILE 포인터를 반환하는 ffunction 포인터를 지정하려면 FILE * (*fn)(blah, blah)이 필요합니다.

  • 마찬가지로 함수의 첫 번째 인수는 const char *, 포인터이어야합니다. 당신은 단순히 const char으로 그것을 가지고있었습니다.

  • my_fopen 포인터 (캐스팅, 주소 지정, 참조 해제)를 설정하는 데 실제로 복잡한 형식이 필요하지 않습니다. 훨씬 단순한 my_fopen = ...을 사용할 수 있습니다. 사실, 캐스팅이 실제로 어떤 일을하는지 알기 때문에 캐스팅이 실제로는 gcc이 오류를보고하는 것을 막을 수 있다고 생각합니다.

  • 아마도 dlopen의 반환 값을 확인해야합니다. 나는이 코드에서 그렇게하지 않았지만, 어떤 이유로 라이브러리를 찾지 못하거나로드 할 수 없다면 그 이후의 행은 아마도 슬픔을 일으킬 것이다. 내가 컴파일하고 Red Hat Enterprise Linux Workstation release 6.4 (Santiago)에서이 프로그램을 실행하면

, 나는 Hello, Pax 파일 xyzzy.txt의 출력 생성을 얻는다.


그리고, 여담이 다른 파일 시스템에 액세스하기 위해 사용될 수있다 기능, 상황이 openopendir, freopen, creat, mkfifo (나는 생각한다)와 같은있다 것처럼.

필요에 따라 추가 작업이 필요할 수 있습니다.


하나는 을 고려하는 것이 좋습니다 점은 ls 수도조차 사용fopen입니다. 실제로는 opendir/readdirstat으로 만들 수 있습니다.

그럼 을 알고있는 프로그램을 사용하여 fopen으로 전화를 걸자. 다음을 실행

#include <stdio.h> 
int main (void) { 
    FILE *fh = fopen ("xyzzy.txt", "w"); 
    fclose (fh); 
    return 0; 
} 

gcc -o qqtest qqtest.c로 컴파일 다음 프로그램 qqtest.c를 입력합니다. 출력이 표시되지 않지만 xyzzy.txt 파일을 만들어야합니다.

#include <stdio.h> 
#include <dlfcn.h> 

FILE* (*my_fopen)(const char *filename, const char* mode); 
void* libc_handle; 

void __attribute__ ((constructor)) init(void){ 
    libc_handle = dlopen("libc.so.6", RTLD_LAZY); 
    my_fopen = dlsym(libc_handle,"fopen"); 
} 

FILE* fopen(const char* filename, const char* mode){ 
    printf("Hello, Pax\n"); 
    return my_fopen(filename, mode); 
} 

gcc -shared -o qq.so qq.c -ldl 이것을 컴파일 한 다음 qqtest 프로그램 (물론 자신의 디렉토리에 공유 객체의 경로를 변경)를 실행 : 당신이 xyzzy.txt 파일을 삭제 있음을 확인하면, 다음 프로그램 qq.c를 입력 : xyzzy.txt 파일이 생성되기 전에

LD_PRELOAD=/home/pax/qq.so ./qqtest 

이 시간, 당신은 그것을 다시 원래 fopen 호출 래퍼 함수를 ​​부르고 있다는 증거를 Hello, Pax 문자열 출력을 볼 수 있습니다.


자, 당신이이 비트는 작업을 진행하더라도 일단, 아주 잘 전부지만, 당신은 당신이 모든 변경 사항을 잡을 수 있도록하는 것은 매우 몇 가지 다른 호출을 차단해야합니다.

Chris Stratton이 주석에서 지적한대로 Linux 커널이 이미 일 때에 파일 시스템 변경 사항을보고 할 수있는 기능이 있습니다.

당신의 목표는 단지 ​​바퀴를 다시 발명에 필요없이 을 수행하는 방법을 볼 수 inotify로 보면, 파일 시스템 변경 사항을 추적하기보다는 그것을 할 수있는 방법에 자신을 교육하는 것입니다 경우.

+0

에 끼워 넣을 수는 없다고 생각하지만, 편집의 실수였다. (코드는 컴파일되지 않았을 것이다.). 그냥 내 질문을 편집, 여전히 같은 오류. – user1734905

+0

@ user1734905 님, 더 깊이 살펴 보았습니다. 업데이트를 참조하십시오. – paxdiablo

+0

"ls"로 테스트 했습니까? 나는 여전히 "ls"와 함께 Segmentation Fault 오류가 있습니다 – user1734905

관련 문제