what is different between .got & .got.plt

실행 파일 구조에는 .got 와 .got.plt 가 존재한다. 이 둘의 차이점은 뭘까?

우리가 흔히 말하는 got overwrite에서 got는 .got.plt 을 의미한다. plt함수에서 실제 libc상의 함수

.got 영역은 전역변수들의 주소를 저장한다.

전역변수들이 .data 영역에 존재하는데 왜 .got ? 라고 말할 수도 있다.

하지만, 다른 라이브러리에 있는 전역 변수를 사용한다면, 로더가 재배치를 하여야 해당 전역변수의 실제 위치를 알 수 있다. 이럴때 사용되는게 .got 영역이다.

C
 22 .got          00000008  0000000000601ff8  0000000000601ff8  00001ff8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 23 .got.plt      00000080  0000000000602000  0000000000602000  00002000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 24 .data         00000010  0000000000602080  0000000000602080  00002080  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 25 .bss          00000030  00000000006020a0  00000000006020a0  00002090  2**5
                  ALLOC
                 
C

(pwn) amemoyoi ~$ objdump -R Notepad

Notepad:     file format elf64-x86-64

DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE
0000000000601ff8 R_X86_64_GLOB_DAT  __gmon_start__
00000000006020a0 R_X86_64_COPY     stdout@GLIBC_2.2.5
00000000006020b0 R_X86_64_COPY     stdin@GLIBC_2.2.5
00000000006020c0 R_X86_64_COPY     stderr@GLIBC_2.2.5
0000000000602018 R_X86_64_JUMP_SLOT  remove@GLIBC_2.2.5
0000000000602020 R_X86_64_JUMP_SLOT  puts@GLIBC_2.2.5
0000000000602028 R_X86_64_JUMP_SLOT  fclose@GLIBC_2.2.5
0000000000602030 R_X86_64_JUMP_SLOT  system@GLIBC_2.2.5
0000000000602038 R_X86_64_JUMP_SLOT  strchr@GLIBC_2.2.5
0000000000602040 R_X86_64_JUMP_SLOT  read@GLIBC_2.2.5
0000000000602048 R_X86_64_JUMP_SLOT  __libc_start_main@GLIBC_2.2.5
0000000000602050 R_X86_64_JUMP_SLOT  ftell@GLIBC_2.2.5
0000000000602058 R_X86_64_JUMP_SLOT  fseek@GLIBC_2.2.5
0000000000602060 R_X86_64_JUMP_SLOT  setvbuf@GLIBC_2.2.5
0000000000602068 R_X86_64_JUMP_SLOT  fopen@GLIBC_2.2.5
0000000000602070 R_X86_64_JUMP_SLOT  sprintf@GLIBC_2.2.5
0000000000602078 R_X86_64_JUMP_SLOT  strstr@GLIBC_2.2.5

objdump -h 명령어로 섹션을 살펴보고

objdump -R 명령어로 재배치 되야할 항목들에 대해 살펴보면, 여러가지가 나온다. 그중 타입이

R_X86_64_JUMP_SLOT 인 얘들이 보인다. 얘내들은 딱봐도 .got.plt 인것을 알 수 있을 것이다.

0000000000601ff8 R_X86_64_GLOB_DAT __gmon_start__

그리고 섹션상으로 얘가 .got 영역인것을 알 수 있다.

C
00000000006020a0 R_X86_64_COPY     stdout@GLIBC_2.2.5
00000000006020b0 R_X86_64_COPY     stdin@GLIBC_2.2.5
00000000006020c0 R_X86_64_COPY     stderr@GLIBC_2.2.5

R_X86_64_COPY 타입인 얘내들은 전역변수의 값이 외부에 정의되어 있고 그 값을 로더가 복사해 오는 얘들이다. 주소 bss 섹션을 쓴다.

좀 더 깊숙하게 따지자면, .got 은 never resolved lazily 하다. 그에 반해

.got.plt 은 resolved lazily 하다. 그리고 RELRO와 같은 보안 기법으로 보호되는 공간은 .got.plt 뿐이다.