LD_PRELOAD rootkits
# 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 |