Colors of Ray+Hue'

LD_PRELOAD rootkits

NVM2016. 8. 26. 08:49

# LD_PRELOAD rootkits

original source: http://hyunmini.tistory.com/55

original source: https://blog.gopheracademy.com/advent-2015/libc-hooking-go-shared-libraries/


How LD_PRELOAD rootkits work

An LD_PRELOAD rootkit works by implementing alternative versions of functions provided by the libc library that many Unix binaries link to dynamically. Using these ‘hooks’, the rootkit can evade detection by modifying the behaviour of the functions and bypassing authentication mechanisms, e.g. PAM, to provide an attacker with a backdoor such as an SSH login using credentials configured by the rootkit.

For example, the Azazel rootkit hooks into the fopen function and conceals evidence of network activity or files related to the rootkit. If there is nothing to hide, Azazel invokes the original libc function so that the application behaves as normal from the user’s perspective.

Using LD_PRELOAD to hook into other libraries is an old trick and can usefully be used for debugging applications, especially when you don’t have access to an application’s source code.

LD_PRELOAD

프로세스 실행 과정 중 라이브러리를 로딩 할때, LD_PRELOAD 변수가 설정되어 있으면 해당 변수에 지정된

라이브러리를 먼저 로딩하고, 이중 libc 함수명과 동일한 함수가 있다면 해당 함수를 먼저 호출해 준다.

즉, 자동으로 후킹을 수행하도록 해준다는 말과 같다.

참고 - OS 별 PRELOAD 환경변수


Linux : LD_PRELOAD 

AIX : LDR_PRELOAD

Solaris : LD_PRELOAD

FreeBSD : LD_PRELOAD

간단히 개념 정리를 위한 예제를 살펴보자. 

$ ls

secuholic  test1  test2  test3

ls 명령 수행 시 현재 디렉토리의 파일 목록이 보인다. 파일 중 secuholic 이 보이지 않도록 해 본다.

$ ltrace ls

         ...

strcpy(0x08058758, "test1")                                               = 0x08058758

readdir64(0x08057720, 0x08057700, 0xbffffb84, 1, 0x0805777c) = 0x08057794

malloc(6)                                                                      = 0x08058768

strcpy(0x08058768, "test2")                                               = 0x08058768

readdir64(0x08057720, 0x08057700, 0xbffffb84, 1, 0x08057794) = 0x080577ac

malloc(6)                                                                       = 0x08058778

strcpy(0x08058778, "test3")                                               = 0x08058778

readdir64(0x08057720, 0x08057700, 0xbffffb84, 1, 0x080577ac) = 0x080577c4

malloc(10)                                                                     = 0x08058788

strcpy(0x08058788, "secuholic")                                       = 0x08058788

readdir64(0x08057720, 0x08057700, 0xbffffb84, 1, 0x080577c4) = 0x080577e0

malloc(7)                                                                      = 0x08058798

         ...

secuholic  test1  test2  test3

중간 문자열 처리 과정에서 strcpy 함수 호출 시 src 가 secuholic 인지 비교하여 참인 경우 변조를 하면 된다.

$ cat test.c

#include <stdio.h>

#include <string.h>


char *strcpy(char *dest, const char *src)

{

int i =0;

while (src[i] != '\0')

{

dest[i] = src[i];

i++;

}

dest[i] = '\0';

printf("[hooked] : strcpy(%x,\"%s\")\n",dest,src);

return &dest[0];

}

$ LD_PRELOAD=./hook.so ls

[hooked] : strcpy(8054a48,"xterm-redhat")

[hooked] : strcpy(8054c18,"xterm-xfree86")

[hooked] : strcpy(bffffa87,"46")

[hooked] : strcpy(8054a4c,"li#46")

[hooked] : strcpy(bffffa87,"98")

[hooked] : strcpy(8054c1c,"co#98")

[hooked] : strcpy(8054fa0,"no=00:fi=00:di=01;34:ln=")

[hooked] : strcpy(80549b8,".")

[hooked] : strcpy(80549c8,"test1")

[hooked] : strcpy(80549d8,"test2")

[hooked] : strcpy(80549e8,"test3")

[hooked] : strcpy(80549f8,"secuholic")   // secuholic 문자열 복사

[hooked] : strcpy(8054b28,"test.c")

[hooked] : strcpy(8054b38,"hook.so")

hook.so  secuholic  test.c  test1  test2  test3


이제 해당 부분을 수정해 보자.


$ cat test.c

#include <stdio.h>

#include <string.h>


char *strcpy(char *dest, const char *src)

{

int i =0;

if(strcmp(src,"secuholic")==0){

dest[i] = '\0';

return &dest[0]; // src가 secuholic 인 경우 바로 리턴

}

while (src[i] != '\0')

{

dest[i] = src[i];

i++;

}

dest[i] = '\0';

// printf("[hooked] : strcpy(%x,\"%s\")\n",dest,src);

return &dest[0];

}

gcc -shared -fPIC -o hook.so test.c


$ ls 

 hook.so secuholic test.c test1 test2 test3   // secuholic 존재


$ LD_PRELOAD=./hook.so ls 

 hook.so test.c test1 test2 test3   //  secuholic 숨김

이렇게 간단히 후킹이 가능함을 확인해 보았다. LD_PRELOAD 는 setuid 가 걸려 있으면 동작하지 않으며, 타인의 프로세스에는 영향을

줄 수 없는 등 몇가지 제한 사항이 있으나, 쉽게 후킹이 가능하다는 점에서 유용하다 볼 수있겠다.  :)

'NVM' 카테고리의 다른 글

libvmmalloc initialization analysis  (0) 2016.08.30
libvmmalloc  (0) 2016.08.24
libpmem library  (0) 2016.08.09
libnvdimm  (0) 2016.08.05
PCMSIM  (0) 2016.08.05