PLT & GOT

c0wb3ll ㅣ 2020. 5. 5. 18:14

PLT & GOT

ROP라는 기법에서 그냥 흘러가는 지식으로 대충 감만 잡고 있었는데 RELRO라는 보호기법에 대해 공부하다가 Lazy Binding? 에서 다시 나오길래 이번에 정리하려고 한다.

PLT

PLT란 Procedure Linkage Table의 약자로 외부 프로시저를 연결해주는 테이블이다.

PLT는 실제 호출 코드를 담고 있는 테이블로써 이 내용 참조를 통해 _dl_runtime_resolve가 수행되고, 실제 시스템 라이브러리 호출이 이뤄지게 된다.

GOT

GOT란 Global Offset Table의 약자로 PLT가 참조하는 테이블이다. 프로시저들의 주소가 들어있다.

GOT는 프로시저들의 주소를 가지고 있다. PLT가 어떤 외부 프로시저를 호출하면 이 GOT를 참조하여 해당 주소로 점프하게 된다.


단 PLT와 GOT는 Dynamic Link 방식으로 컴파일 했을때 사용되는데 그 이유는 Static Link 방식으로 컴파일 하면 라이브러리가 프로그램 내부에 있어서 함수의 주소를 알아오는 과정이 필요치 않지만 Dynamic Link 방식으로 컴파일 하면 라이브러리가 프로그램 외부에 있어서 함수의 주소를 알아오는 과정이 필요하다.

이 때 GOT를 처음 호출할 때와 아닐 때 동작과정의 차이가 있다.

image

맨 처음 putchar@plt 의 위치를 보면 0x1030이다.

r 을 눌러 실행하고 난 뒤 putchar@plt의 주소를 확인해보자.

0x7ffff7e6cbc0 으로 바뀐 것을 알 수 있다.

이 처럼 got 호출이 처음일 때는

  1. func() 호출
  2. @plt로 이동
  3. @got 참조
  4. @plt로 이동
  5. _dl_runtime_resolve
  6. @got 저장 후 실제 함수 실행

순으로 동작한다.

반면 got 호출이 처음이 아닐 때는

  1. func() 호출
  2. @plt로 이동
  3. @got 참조
  4. func() 로 점프

에 동작과정이 일어난다.

이러한 이유는 _dl_runtime_resolve를 통해 외부에 있는 라이브러리를 가져와야하는 과정에 차이다 처음 호출 했을 때는 라이브러리를 가져와 저장해야 하지만 저장한 후에는 got에 실제 함수 주소가 들어있기 때문에 바로 함수 사용이 가능하게 된다.

 


Reference

https://hackstoryadmin.tistory.com/61