티스토리 뷰

Security

plt got

on1ystar 2019. 2. 3. 12:58
728x90
반응형

PLT & GOT


 

PLT (Procedure Linkage Table) :외부 프로시저를 연결해주는 테이블. PLT를 통해 다른 라이브러리에 있는 프로시저를 호출해 사용할 수 있습니다.

 

GOT (Global Offset Table) :PLT가 참조하는 테이블.프로시저들의 주소가 들어있습니다.


※프로시저(procedure) : C언어에서 함수와 비슷한 개념으로, 차이점은 함수는 리턴 값을 남기지만 프로시저는 리턴 값을 남기지 않습니다. 쉽게 말해서 함수는 수학적으로도 생각해보면 input값에 의한 output(반환 값)이 반드시 있어야 정의됩니다. 프로시저는 그렇지 않아도 된다는 말이죠.

하지만 요즘은 함수에서 void라는 반환형을 사용하여 리턴 값을 남기지 않도록 사용하기 때문에 딱히 구별하지 않기도 한다고합니다.

참고로 윈도우 프로시저(WndProc)는 콜백 함수로 운영체제가 호출하는 함수의 의미로 사용됩니다.자세한 부분은 더 찾아봐야겠습니다.

 

이를 정리해보면 우리가 C언어에서 printf와 같은 (외부)라이브러리 함수를 사용하기위해PLT가호출되면,PLT는 다시 외부 프로시저(다른 라이브러리에 있는 함수들(printf, scanf… )를 호출하기 위해 프로시저들의 주소가 들어있는 GOT를 참조하게 됩니다.

사용자 함수의 경우 같은 파일안에직접구현하기 때문에 이러한 PLT호출이 필요 없게 되는 것입니다.

이를 컴파일과 링크 과정을 함께 설명한 글을 보니까 컴파일 과정도 쉽게 이해되고 좋은거 같아서 같이 한번 보겠습니다. (https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/)


컴파일과 링크


예를 들어 우리가 작성한 소스 코드에

1

2

3

4

#include <stdio.h> 

printf(…);

cs

이런 식으로 헤더파일을 include 해주고 printf함수를 사용했습니다.

그런 다음 컴파일을 해주면 컴파일러는 이 소스파일을 .o라는 오브젝트 파일을 생성해 줍니다.하지만 이 오브젝트 파일은 당장 실행을 할 수가 없습니다.

왜냐하면 우리가 작성한 소스 코드는 우리가 정의하고 구현한 사용자 함수는 몰라도, printf 함수의 경우는 선언이 들어있는 stdio.h헤더만 include 해준 것이므로 구현코드를 모르기 때문입니다.

그렇다면 이 printf의 구현 코드는 어디에 있느냐. printf를 구현한 오브젝트 파일에 있겠죠? 그리고 이렇게 미리 다양한 함수들을 구현해 놓고, 컴파일한 오브젝트 파일들을 모아 놓은 곳라이브러리(Library)라고 합니다.

우리가 주로 사용하는 함수들은 이런 외부 라이브러리에서 미리 정의되고 구현된 함수들을 사용하는 것입니다.

그리고 이러한 라이브러리들을 우리의 소스 코드 오브젝트 파일과 연결시키는 작업을 링킹(Linking)이라고 합니다.



이렇게 링크과정까지 마치면 드디어 실행할 수 있는 실행파일 .exe가 만들어 집니다.


Static Link & Dynamic Link


<Static Link 방식>은 파일 생성시에 라이브러리 내용을 포함한 실행 파일을 만듭니다.

흔히 gcc를 이용해 컴파일 할 때

$ gcc -o 파일명 파일명.c -static    이렇게 static옵션을 줍니다.

이렇게 정적 링크방식을 이용하면 실행 파일 안에 라이브러리 동작 코드가 포함되기 때문에 별도의 추가 작업 없이,실행 바이너리만으로 라이브러리 함수들을 사용할 수 있게 됩니다.

이럴 경우 필요한 라이브러리를 따로 관리하지 않아도 되기 때문에 편리하지만파일의 크기는 당연히 커질 수 밖에 없게 되고,만약에 같은 라이브러리를 여러 실행파일이 필요한 경우에 이들을 다 정적 링크 해버리면 그만큼 메모리를 잡아 먹으니까 효율이 떨어집니다.

 

<Dynamic Link 방식>은 라이브러리를 실행 파일에 포함시키는 것이 아니라 라이브러리를 하나의 메모리 공간에 매핑하고 이를 여러 프로그램이 공유해서 사용하게 됩니다.

gcc로 컴파일 하는 경우에는

$ gcc -o 파일명 파일명.c    처럼 아무런 옵션이 없으면 디폴트로 Dynamic 방식으로 컴파일 합니다.

동적 링크방식을 사용할 경우 해당 프로그램을 실행하기 위한 실행파일 뿐 아니라 꼭 (공유)라이브러리 파일(.dll .so)이 함께 있어야 합니다.

단 라이브러리 코드를 포함하지 않기 때문에 파일의 크기가 훨씬 작아지고,적은 메모리를 먹습니다.게다가 라이브러리를 따로 업데이트하거나 다른 프로그램들을 추가할 때 공유 라이브러리와 링킹 작업을 해주면 되기 때문에 유지보수가 좋고 효율적입니다.

그리고 이 Dynamic Link 방식으로 컴파일 할 때 PLTGOT가 사용됩니다.


일단 간략하게 정리해보면,

Static Link ->라이브러리가 프로그램 내부에 존재 ->프로시저의 주소를 알고 있음

Dynamic Link ->라이브러리가 프로그램 외부에 존재 ->프로시저의 주소를 모름-> PLT 호출 -> GOT로 점프 -> GOT에 있는 실제 프로시저 주소 호출

여기서 PLT GOT에서 일어나는 일을 좀 더 살펴보면 두 가지 경우로 나눌 수 있습니다.


<1> 해당 프로시저( 공유 라이브러리 내의 함수)가 최초로 호출될 때

<2> 한 번 이상 호출되었을 때

간단한 예제를 하나 작성해서 동작하는 것을 보며 알아보겠습니다.

 

 

PLT & GOT 호출 과정

text.c

1

2

3

4

5

6

7

8

9

#include <stdio.h>

 

int main(){

 

    printf("AAAAAAA");

    printf("aaaaaaaaa");

 

    return 0;

}

cs

이를 작성하고 당연히 동적 링크 방법으로 컴파일 해 준 뒤 GDB로 열어보겠습니다.


동적 링크 방법으로 컴파일 한 후 공유 라이브러리 함수의 printf를 사용했기 떄문에 printf@plt가 두 번 호출되는 것을 확인한 수 있습니다.

<1> 먼저 첫 번째 printf@plt가 실행된 다음을 브레이크 포인트로 걸어 준 후 열어보겠습니다.

 


처음에 어떤 주소로 점프를 하고 있습니다. 이 주소로 들어가 보면,


이런 메세지가 뜨는데... 원래는


이런 그림을 보여드리고 싶었지만... 안열리네요. (rip instruction pointer라서 실제 주소가 저기가 아닌 거 같은데, 이에 대한 개념이 부족한 거 같습니다.)

일단 만약 열렸다면 이런 식으로 GOT가 바로 <printf@plt+6>으로 바로 점프하는 것을 확인할 수 있습니다.

그 다음 어떤 값을 push 해 준 다음 다시 0x4003f0으로 점프합니다. (여기서 push 해주는 값은 reloc_offset 인데, 이 부분은 다음에 더 공부해보겠습니다.)

이 점프하는 곳을 열어보면



또 다시 어떤 값을 push 해 준 다음 다시 점프합니다. (push 값은 link_map 이라는 구조체 주소입니다. 이 역시 다음에..)

이 점프하는 주소에 있는 함수가 바로 _dl_runtime_resolve라는 함수의 주소입니다.

이 함수가 하는 일을 간단히 요약해보면 호출하고자 하는 함수의 실제 주소를 GOT에 저장한 후 해당 주소로 점프 합니다.

따라서 printf 함수가 실행이 되고 이 printf 함수의 실제 주소가 GOT에 저장이 됩니다. (GOT는 테이블이니까)

<2> 그럼 이제 printf 함수가 두 번째 호출될 경우 어떻게 동작할까요 ?



PLT -> GOT 호출 -> GOT가 이번에는 PLT 다음 주소가 아닌 실제 printf 함수 주소로 점프 -> printf 함수 실행

이런 식으로 동작하게 됩니다. 이를 그려보면,

 


이렇게 되겠습니다.

사실 설명하면서 생략한 _dl_runtime_resolve 함수의 실행 과정을 더 자세히 알게 되면 시스템 해킹을 할 때 매우 큰 도움이 될 수 있을 것 같습니다.

(https://d4m0n.tistory.com/78 이 글을 보면서 공부하면 도움될 것 같습니다.)


참조 :    https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/

           https://expointer.tistory.com/13


728x90
반응형

'Security' 카테고리의 다른 글

어셈블리로 구구단 짜기(nasm)  (1) 2019.04.02
RTL (Return to Libc)  (0) 2019.02.05
리버싱 실습(Easy_ELF)  (0) 2019.01.24
버퍼오버플로우 실습  (0) 2019.01.23
취약점(vulnerability)  (0) 2019.01.20
댓글