PLT(Procedure Linkage Table)과 GOT(Global Offset Table)는 동적 링크된 심볼의 주소를 라이브러리에서 찾을 때 사용하는 테이블이다.
[system] library - Static Link vs Dynamic Link
코딩을 하면 #include 를 항상 넣어준다. printf 함수를 사용할 때, printf 함수를 직접 정의하지 않고 libc에 정의된 함수를 가져다가 사용한다. 이를 라이브러리라고 한다. 여러 프로그램이 printf를 사
3omh4.tistory.com
PLT & GOT
ASLR이 적용된 환경에서, 동적 링킹 바이너리는 바이너리가 실행될 때마다 라이브러리가 매핑된다. 바이너리가 실행되기 전까지 라이브러리 함수의 주소를 알 수 없기 때문에, 라이브러리가 메모리에 매핑된 후 PLT와 GOT 영역에 접근해 함수주소를 얻는다.
바이너리가 실행되면 ASLR에 의해 라이브러리가 랜덤한 위치에 매핑된다. 이때 라이브러리의 함수가 호출되면, 함수 이름을 바탕으로 라이브러리에서 심볼을 탐색하고, 해당 함수를 찾으면 그 주소로 실행 흐름을 옮긴다. 이 과정을 통틀어 runtime resolve
라고 한다.
이 과정이 매번 메모리에서 찾고 흐름바꾸고 찾고 흐름바꾸고 하면 비효율 적이다. 그래서 GOT라는 테이블을 두고, resolve된 함수의 주소를 테이블에 저장한다. 예제를 통해 GOT 테이블에서 어떻게 함수를 읽어오는지 살표보자.
Runtime resolve
다시 한번 runtime resolve 과정을 정리해보면 다음과 같다.
- 라이브러리의 함수 호출
- 함수 이름을 바탕으로 라이브러리에서 심볼 탐색
- 함수를 찾으면 그 주소로 실행 흐름 옮김
위의 과정이 끝나면 GOT 테이블에 resolve된 함수의 주소를 저장한다.
// Compile: gcc -o got got.c
#include <stdio.h>
int main() {
puts("Resolving address of 'puts'.");
puts("Get address from GOT");
}
위의 코드를 통해 간단히 보자면 아래와 같이 함수 호출 전(PLT)과 후(GOT)의 주소가 다르고, 두 번째 호출부터는 puts함수의 주소를 가리키고 있는 것을 알 수 있다.
동적 링크로 프로그램이 만들어지면 함수를 호출할 때 PLT를 참조한다. PLT에서는 GOT로 jmp하는데, GOT에 실제 함수의 주소가 쓰여있다.
이 때, 첫 호출이라면 GOT에 실제 주소가 쓰여있지 않아 링커가 dl_resolve 함수를 사용해 필요한함수 주소를 알아와 GOT에 저장한다.
GOT 함수 주소 저장 과정
처음 함수를 실행할 때, GOT에는 실제 주소가 없으므로 _dl_runtime_resolve 함수를 통해 실제 함수의 주소를 구하는 과정이 필요하다. 해당 함수를 거치고 나면 GOT에는 실제 함수 주소가 저장되므로 바로 함수를 실행할 수 있다.
요약
함수를 호출할 때, PLT(Procedure Linkage Table)라는 table로 이동해 GOT(Global Offset Table)라는 table에 해당 함수가 계산된 주소가 있는지 확인을 한다. 계산된 주소가 없으면 _dl_runtime_resolve로 함수 주소를 계산한다. 또 계산하기엔 비효율적이니 계산된 주소를 GOT에 저장한다.
'CS > system' 카테고리의 다른 글
[System][Dreamhack] Exploit Tech : Return Oriented Programming(ROP) (0) | 2023.12.22 |
---|---|
[System][Dreamhack] Exploit Tech : Return to Library(RTL) (0) | 2023.02.01 |
[System] library - Static Link vs Dynamic Link (1) | 2022.11.26 |
[System][Dreamhack] 메모리 보호기법 Mitigation: NX & ASLR (0) | 2022.11.25 |
[System][Dreamhack] Exploit tech : Return to Shellcode (0) | 2022.09.06 |