LD_PRELOAD를 이용해 echo 명령시 printf() 함수 후킹에 관하여

LD_PRELOAD를 이용해서 리눅스(centos)에서
echo 명령어 동작중에 printf() 함수를 후킹을 해보려고 시도하는데
어디서 부터 막힌건지 전혀 감이 오지를 않네요. 조언 부탁드립니다.
우선은 간략하게 my_printf() 소스입니다. 그저 어떤한 값들이 지나가는지 로그를 남기는 형태지요
my_printf.c int (*my_printf)(const char *format, ...); int printf(const char *format, ...) { LOG("format:%s", format); char buffer[100] = {0, }; int rval =0; va_list ap; va_start(ap, format); rval = vsprintf(buffer, format, ap); va_end(ap); LOG("len:%d, buffer:%s", rval, buffer); my_printf = dlsym(RTLD_NEXT, "printf) rval = (*my_printf)(format, "%s", buffer); return rval; }
테스트 방식은 쉘에다 입혀서 후킹하는 방식입니다.
$LD_PRELOAD=./my_prinf.so bash
bash 쉘일 경우 echo 를 자체적으로 지원하더군요.
/usr/bin/echo 를 삭제하더라도 echo가 동작되는...
그래서 bash 쉘 소스를 분석해보니
리눅스일 경우 printf() 문으로 출력하는 구조였습니다.
SunOS일 경우는 fflush() 방법으로...
이러한 방법으로 "$echo abcd" 명령에 대한 로그를 확인해보면 .... printf()를 전혀 잡지 못하더군요.
그러다 stdio.h를 까보고 bits/stdio2.h 까지 살펴봤는데
놀랍게도 __printf_chk() fortify 함수를 가로채면 잡히더라구요
그러나... 테스트 코드로 printf() 수행하는 실행파일을 만들면 printf()문 후킹이 잘되고...
test.c #include <stdio.h> int main() { int i=0; printf("abcd : %d\n", i); return 0; }
stdio2.h 에서 __printf_chk 함수는
#ifdef __USE_FORTIFY_LEVEL > 1로
printf() 대신 __printf_chk() 함수가 실행되도록 명시되어있습니다.
조금더 자세히 찾아보니
http://zer0day.tistory.com/351
gcc 보안 옵션이 걸려서 Stack BOF, Format String 취약점을 디폴트 옵션으로 보안하나 싶어서
컴파일시 -D_FORTIFY_SOURCE=0 , -fno-stack-ptrtector 플래그를 주어도 ... 먹히지 않더라구요
"$echo abcd" 할때 printf()문을 후킹할 수 있는 방안이 없는걸까요...
어디서 잘못된거지 조언 부탁드립니다.
LD_PRELOAD 를 해서 /usr/bin/echo
LD_PRELOAD 를 해서 /usr/bin/echo --help 를 실행시켜보면 도움말 한 줄에 대한 printf()는 잡아채실 수 있을 것 같습니다.
http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/echo.c
아... 어떻게해서든 bash 의 내장 echo 가 printf() 를 사용하게 만들고, 그걸 잡고 싶으신거네요.
bash 를 다시 컴파일해야 합니다.
bash 소스를 가져다 configure && make 하는 경우라면 그냥 하시면 되고,
배포본 패키지 매니저를 이용해서 다시 빌드하시는 거라면 좀 귀찮겠네요.
예를 들면, fedora 의 경우 rpm rc 의 __global_cflags 에 -D_FORTIFY_SOURCE=2 가 들어가 있습니다.
댓글 달기