System Software

PLT 와 GOT

부산대보금자리 2021. 7. 21. 19:28

PLT와 GOT에 대해서 흘려 들었던 적은 많으나 제대로 정리가 안 돼있어서 찾아보고 나름대로 정리를 해두려고 한다.

  • PLT (Procedure Linkage Table) : 외부 프로시저를 연결해주는 테이블. 
  • GOT (Global Offset Table) : PLT가 참조하는 테이블. 프로시저들의 주소가 들어있다.

이까지 보면 무슨 소리인지 감이 잘 잡히지 않는다.

PLT와 GOT를 왜 사용하는지에 대해서는 링커 개념때문이다. 

 

나의 소스 파일이 .c ->. s ->. o까지 왔다면 이후에는 링커 과정을 거쳐서 라이브러리 파일을 연결시켜줘야 실행 파일로 바뀔 수 있다.

이런 과정에는 static linking과 dynamic linking이 있다.

 

Static linking의 경우 프로그램이 필요로 하는 부분을 라이브러리에서 찾아 실행파일에다가 바로 복사한다. 

실행파일에 다 들어가기 때문에 라이브러리가 필요 없고 컴파일 시간도 단축된다. 또한 직접 구현한 코드를 라이브러리화 시켜서 기술 유출 방지로 사용할 수도 있다.

하지만 실행 파일 내에 라이브러리 코드가 저장되기 때문에 메모리를 많이 잡아먹는다. 

이는 다중유저 시스템에선 더 치명적일 수 있다. 

 

따라서 쓰이는 것이 Dynamic linking이다.

이는 라이브러리를 공용으로 사용한다는 것으로 메모리에 하나만 올린다. 

그리고 이 프로그램이 해당 라이브러리의 함수를 호출할 때 메모리에 있는 곳으로 간 후 실행한 다음에 다시 돌아오는 것이다. 

 

이러한 Dynamic linking에서 PLT와 GOT를 사용하게 된다. 

라이브러리가 프로그램 외부에 있기 때문에 함수의 주소를 알아오는 과정이 필요하다.

이는 함수를 호출할때 plt를 참조하게 되고 plt에서는 got로 점프를 한다. 

만약 첫번째 호출이 아니라면 got에는 해당 함수의 주소가 쓰여있고 그곳으로 점프하고

첫 번째 호출이라면 got에 실제 함수의 주소가 쓰여 있지 않으므로 linker가 dl_resolve라는 함수를 사용해 필요한 함수의 주소를 알아오고, got에 그 주소를 써준 후 해당 함수를 호출한다.

 

예제를 한번 만들어 보았다. 

printf를 호출하는 상황을 보려고 한다. 

 

printf를 취해 plt로 간다. 

 

printf 의 got로 이동한다. 

 

이후에 진행되는 것은 link_map구조체 포인터, 라이브러리의 정보를 push 하고 dl_runtime_resolve로 점프하여 해당 함수의 주소를 구하게 된다.

위에서 push 했던 값은 roloc_offset값이고 link_map 값을 push하면 

 

 

이러한 구조가 나오고 eax,ecx,edx는 dl_runtime_resolve에서 push 한다. 

그리고 이러한 값들을 이용해서  dl_fixup함수가 사용하는 함수를 찾아 사용하게 된다. 

뒷부분은 https://bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/

 

PLT와 GOT 자세히 알기 2 (with ‘yocto’)

이번 편에서는 Codegate 2015 본선 문제 였던 pwnable 분야의 ‘yocto’ 를 통해 PLT 와 GOT에 대해 자세히 알아보겠습니다. 과정이 조금 복잡하기 때문에, 보시면서 따라 해 보는 것이 이해 하는 데 조금

bpsecblog.wordpress.com

이 블로그에서 참고하여 이해할수가 있다.