GOT and PLT
System Hacking - GOT and PLT
1. GOT와 PLT
GOT
란 Global Offset Table
로서, 라이브러리 함수의 실제 주소를 저장해두는 표이다. 원래 C 프로그램에서 사용되는 함수들은 libc
등의 라이브러리에 정의되어있고, 실제 주소는 프로그램 실행 시점에 결정된다. 그러나 컴파일할 때는 함수의 주소를 알 수 없고, GOT를 lookup해서 실제 함수 주소를 구하게 된다.
PLT
라는 것도 있는데, Procedure Linkage Table
이라는 일종의 함수 호출을 위한 중간 점프 테이블이다.
좀 더 자세히 설명하자면, 컴파일된 코드에서는 printf
함수의 주소가 없고, 아래와 같이 되어있다.
call printf@PLT
print@PLT 내부로 가면 아래와 같다.
printf@PLT:
jmp *GOT[printf]
push <relocation info>
jmp dynamic linker (ld.so)
위에서 *GOT[printf]
에는 단지 printf@PLT+6
의 주소가 있기 때문에 바로 다음 명령어가 실행되며, 여기서는 ld.so
로 연결된다.
ld.so
는 printf
함수의 실제 주소를 resolve해서 GOT[printf]
에 저장하며, 이에 따라 이후에 다시 printf
함수를 실행할 경우 jmp *GOT[printf]
명령어에 따라 실제 printf
함수를 바로 가리키게 된다. (ld.so
resolve 더이상 불필요)
그래서 최종 코드 실행 흐름은 아래와 같다.
1. 코드에서 특정 함수 (ex: printf) 호출, printf@PLT로 점프
2. PLT는 GOT에서 printf의 실제 주소를 읽음
3. 처음 호출된 경우, GOT에 주소가 없고, 동적 링커(ld.so)가 호출되어 주소를 받아옴
4. 이후에는 GOT에 주소가 저장되고, 동적 링커를 통해서 받아오지 않고 GOT만 lookup하여 빠르게 함수 호출 가능