Hooking Library Function Calls

LD_PRELOAD 환경변수를 사용하면 로더가 프로그램을 로드할 때 동적 로드해야 할 바이너리 코드를 해당 변수의 값의 디렉토리에서부터 뒤지도록 합니다. 따라서 이를 이용해 malloc(), free() 등의 일반적으로 사용하는 라이브러리 함수를 우리의 구현으로 대체하거나 후킹할 수 있습니다. 이 글은 이런 방법으로 malloc() 을 후킹하는 방법을 예제를 통해 간단히 설명합니다.

Original Program

먼저 다음과 같은 프로그램이 있을 수 있을 겁니다:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	char *abc;

	abc = (char *)malloc(8);
	printf("malloced address: %p\n", abc);
	sprintf(abc, "hello\n");
	printf("%s\n", abc);
	free(abc);

	return 0;
}

단순히 malloc() 을 통해 8바이트 메모리를 할당받아 그 영역을 표시하고 종료하는 프로그램입니다. 위 코드를 program.c 라는 파일로 저장하고, 아래와 같이 컴파일하고 수행해 보면 우리가 익히 아는, 예상대로의 결과가 나옵니다.

$ gcc -o program program.c
$ ./program
malloced address: 0x1cc5010
hello

malloc Hooking Code

이제 malloc() 함수를 후킹하는 코드를 만들어 봅시다:

#define _GNU_SOURCE

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

typedef void *(*malloc_t)(size_t size);

void *malloc(size_t size)
{
	malloc_t malloc_fn;

	fprintf(stderr, "malloc(%zu) hooked\n", size);
	malloc_fn = (malloc_t)dlsym(RTLD_NEXT, "malloc");
	return malloc_fn(size);
}

이 코드는 우리가 아는 malloc() 함수와 동일한 함수명, signature 의 함수를 구현하고 있습니다. 단순히 우리가 후킹했음을 알리고, 동적 라이브러리 구조를 통해 이 다음으로 검색되는 malloc 이름의 라이브러리 함수 (이게 우리가 익히 아는 그 malloc() 구현이겠죠) 를 찾아, 같은 인자로 수행하고 그 결과를 리턴합니다. 즉, 우리가 아는 malloc() 과 같은 일을 하긴 하지만 malloc() 이 호출되었음을 알리는 것이죠.

이 코드를 mallochook.c 라는 이름으로 저장 후, 다음과 같이 라이브러리로 빌드합니다:

$ gcc -shared -fPIC mallochook.c -o mallochook.so -ldl

Install The Hook

프로그램이 기존 malloc() 대신 우리가 구현한 malloc() 을 수행하게 하는 건 LD_PRELOAD 를 활용하면 간단합니다.

$ LD_PRELOAD=./mallochook.so ./program
malloc(8) hooked
malloc(1024) hooked
malloced address: 0x20a5010
hello

두번째, 세번째 줄을 보면 malloc() 이 후킹되어 우리의 메세지가 나오는 걸 볼 수 있습니다. 앞의 program.c 에서는 8 바이트 malloc() 호출만 있었는데 세번째 줄의 1024 바이트 malloc()은 어디서 나온 걸까요? 아마도 뒤의sprintf()` 등의 라이브러리 함수가 호출한 거 아닐까 싶은데 그걸 분석하는 건 여러분의 몫으로 두겠습니다.

Conclusion

자세한 원리는 생략했습니다만, 간단히 주요 라이브러리 함수를 후킹하는 방법을 알아봤습니다. 여기서 사용된 예제 코드와 명령어는 제 [Github repo] (https://github.com/sjp38/mallochook) 에 올려뒀으니 필요하면 참고 바랍니다.

Avatar
SeongJae Park (SJ)
Kernel Programmer

SeongJae Park (SJ) is a programmer who loves to analyze and develop systems.