라이브러리 삽입 완전 이해하기
공유 라이브러리는 그 자체로도 유연하고 강력하지만, 우리가 몰랐던 또 하나의 능력이 있는데요. 바로 기존 함수의 동작을 가로채서, 내가 만든 함수로 바꿔치기 할 수 있다는 것인데, 이를 라이브러리 삽입(library interpositioning)이라고 합니다.
라이브러리 삽입은 단순한 해킹 기법이 아니라, 디버깅이나 로깅, 성능 측정, 보안 등 실제 프로덕션 환경에서도 폭넓게 활용됩니다. 이번 글에서는 CSAPP 7.13절 내용을 바탕으로 인터포지션의 개념과 동작 원리, 실전 적용 방법을 정리해 봅니다.
라이브러리 삽입이란?
라이브러리 삽입이란 한 마디로 기존 심볼(함수, 변수)을 내가 만든 것으로 가로채는 기술입니다.
핵심 아이디어는 곧 프로그램이 원래 호출하려던 심볼보다 내가 정의한 심볼이 먼저 발견되도록 만드는 것인데요. 링커는 심볼을 먼저 찾은 곳으로 연결하기 때문에, 그 결과 내가 만든 함수가 기존 함수 대신 실행됩니다.
라이브러리 삽입이 가능한 이유
이러한 기술이 가능한 이유는 바로 ELF 파일의 심볼 해석 규칙이 먼저 발견된 정의가 우선이기 때문인데요. 즉, 심볼이 중복될 경우 링커는 가장 먼저 찾은 것을 사용합니다. 그래서 우리가 내부 구현보다 앞서서 심볼을 정의하면, 기존 함수(libc의 malloc 등)는 우선 순위에서 밀리게 됩니다.
라이브러리 삽입 예시, malloc 가로채기
그러면 malloc 함수를 mymalloc 함수로 가로채는 예시를 실제 C 코드를 통해 살펴보겠습니다.
// mymalloc.c (malloc을 새롭게 정의한 C 파일)
#include <stdio.h>
#include <stdlib.h>
void *malloc(size_t size) {
printf("[LOG] malloc called with size %zu\n", size);
// 원래 malloc 함수의 포인터 가져오기
void *(*original_malloc)(size_t) = dlsym(RTLD_NEXT, "malloc");
return original_malloc(size);
}
위 코드를 통해 malloc 함수 호출 시 이를 가로채게 하는 명령어는 다음과 같습니다.
gcc -shared -fPIC -o mymalloc.so mymalloc.c -ldl
LD_PRELOAD=./mymalloc.so ./target_program
그 결과, target_program이 malloc()을 호출하면, libc의 malloc이 아닌 사용자가 만든 malloc이 실행됩니다. 그렇다고 원래 malloc을 아예 못쓰게 되는 건 아닌데요. 내부에서 dlsym(RTLD_NEXT, "malloc")
명령어를 통해 원래 malloc도 호출이 가능합니다.
라이브러리 삽입 실전 활용 예시
라이브러리 삽입은 실전에서 다양한 용도로 활용할 수 있는데요. 이를 알아보면 다음과 같습니다.
용도 | 설명 |
로깅 | 함수 호출 시마다 정보 출력 (파일 열기 로그 등) |
성능 측정 | gettimeofday()로 함수 시간 측정 |
테스트 | 테스트용 read, write, malloc 삽입 가능 |
보안 | 특정 동작 차단 (네트워크 함수 가로채기 등) |
디버깅 | 내부 라이브러리의 사용 패턴 관찰 |
라이브러리 삽입의 핵심 도구, LD_PRELOAD
환경변수인 LD_PRELOAD는 링커가 실행파일을 실행하기 직전, 지정된 .so를 먼저 로딩해서 심볼을 정의하도록 만듭니다. 이를 설정하는 명령어는 다음과 같습니다.
LD_PRELOAD=./libintercept.so ./target_app
이렇게 하면 libintercept.so 안의 함수가 우선적으로 심볼 테이블에 등록되면서, ELF의 심볼 해석 규칙에 따라 해당 심볼이 기존 함수보다 먼저 연결됩니다.
라이브러리 삽입 시 주의사항
- 인터포지션으로 가로채는 함수는 반드시 정확한 시그니처를 맞춰야 한다
- dlsym()으로 원래 함수 호출 시 RTLD_NEXT를 사용해야 한다
- 너무 많은 함수를 가로채면 디버깅이 오히려 어려워질 수 있다
핵심 요약
- 라이브러리 삽입은 기존 심볼을 내가 정의한 것으로 가로채는 기법이다
- ELF 해석 순서는 먼저 정의된 심볼을 우선으로 한다
- LD_PRELOAD는 내가 만든 .so를 먼저 로딩해 라이브러리 삽입을 구현한다
- dlsym(RTLD_NEXT, ..)은 원래 함수 호출을 위한 우회 방법이다
- 활용 분야로는 로깅, 테스트, 보안, 성능 분석 등이 있다
'크래프톤 정글 > 컴퓨터구조(CSAPP)' 카테고리의 다른 글
[CSAPP 8장 완전 정복] 8.1~8.3 예외와 프로세스, 시스템의 흐름을 바꾸는 힘 (0) | 2025.04.19 |
---|---|
[CSAPP 7장 완전 정복] 7.14~7.15 오브젝트 파일 분석과 실행 흐름 마무리 (0) | 2025.04.18 |
[CSAPP 7장 완전 정복] 7.12 공유 라이브러리의 핵심 기술 - PIC, GOT, PLT (0) | 2025.04.18 |
[CSAPP 7장 완전 정복] 7.10~7.11 정적 링크 vs 동적 링크, 라이브러리 연결의 두 방식 (0) | 2025.04.18 |
[CSAPP 7장 완전 정복] 7.7~7.9 링커의 마지막 퍼즐 - 재배치, 실행 가능 목적 파일, 그리고 로딩 (0) | 2025.04.18 |