Plt, got

 

PLT와 GOT란?

  • PLT (Procedure Linkage Table) : 일종의 실제 호출 코드를 담고 있는 테이블로써 PLT를 통해 다른 라이브러리에 있는 프로시저를 호출해 사용할 수 있습니다.
    함수는 리턴값이 있고, 프로시저는 없습니다. 프로시저도 리턴값을 패러미터로 받을 순 있습니다. C언어에서의 call by reference정도로 생각할 수 있습니다.
  • GOT (Global Offset Table) : PLT가 참조하는 테이블로써 프로시저의 주소를 가지고 있습니다. PLT가 어떤 외부 프로시저를 호출할 때 이 GOT 를 참조해서 해당 주소로 점프하게 됩니다.
    • printf 함수 호출이 처음일 때 : [printf 함수 호출] —> [PLT로 이동] —> [GOT 참조] —> [다시 PLT로 이동] —> [_dl_runtime_resolve] —> [GOT 저장 후, 실제 함수 주소로 점프]

      enter image description here

    • printf 함수 호출이 처음이 아닐 때 : [printf 함수 호출] —> [PLT로 이동] —> [GOT 참조] ===> printf 함수로 점프

      enter image description here

    • 위와 같이 한 번 호출한 함수는 GOT 참조를 통해서 _dll_runtime_resolve를 거치지 않고 빠르게 수행할 수 있습니다.

Linker

라이브러리 등 필요한 오브젝트 파일들을 연결시키는 작업을 링킹(Linking) 이라고 합니다.

만약 Static Link 방식으로 컴파일을 한다면 라이브러리가 프로그램 내부에 있기 때문에 함수의 주소를 알아오는 과정이 필요하지 않지만, Dynamic Link 방식으로 컴파일 하면 라이브러리가 프로그램의 외부에 있기 때문에 함수의 주소를 알아오는 과정이 필요합니다.

To check the structure (Print one)

  • 첫번째 pritnf의 구조를 알기 위해 간단하게 printf 두 번을 하는 프로그램을 만들어 봅니다

    enter image description here

  • GDB를 이용하여 disas main을 해보면 0x400400 (put@plt 영역)에 call 하는 것을 볼 수 있습니다.

    enter image description here

  • 0x400400 부분 (plt 부분)을 보면 puts에 대해서 3단계로 구성되어 있는데, 첫번째 jmp는 당연히 got 영역이 됩니다.

    enter image description here

  • got 부분을 보면 plt의 두번 째 부분을 다시 가르키고 있습니다.

    enter image description here enter image description here

To check the structure (Print two)

이번에는 두번째 printf의 구조를 알아보겠습니다.

  • 두번째 printf에서 멈추기 위해 breakpoint를 걸어줍니다.

    enter image description here

  • 실행을 하고 다시 got영역을 확인해 보겠습니다.

    enter image description here

  • 위와 같이 0x601018의 값이 바뀐 것을 볼 수 있습니다.