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

https://bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/ 정리

프로그램 생성과정

.c [pre-compiler] .i [compiler] .s [assembler] .o [linker] executable [loader] 실행


linker에서 링킹, 필요한 오브젝트(라이브러리)등을 연결시키는 작업이 링킹(linking)

1. static: 라이브러리 내용을 포함해서.. (gcc -o 실행파일 소스파일 -static)

2. dynamic: 라이브러리를 하나의 메모리 공간에 매핑 후 여러 프로그램이 사용. (default)


file 명령어로 확인 가능


PLT (Procedure Linkage Table)

GOT (Global Offset Table)


dynamic linking 시에 PLT를 이용하여 1) 처음 접근할 때에는 GOT에 가서 해당 함수를 불러들이고 2) 그 이후부터는 PLT선에서 해결


사실 1)에서도 추가적인 과정이 필요 (Linker 가 dl_resolve를 사용하여 함수의 주소를 알아오고 GOT에 쓰고 호출)


Static compile)

호출 전과 후 안바뀜, 계속 putchar의 주소는 text 영역에 있음


Dynamic compile)

gdb에서 p putchar를 하면 putchar@plt 로 뜸 

한번 실행후에 주소바뀌고 putchar로 뜸

Lazy Binding: Dynamic linking 방식으로 컴파일된 경우 GOT PLT를 사용해서 공유 라이브러리 내의 함수 호출


첫번째 실행시:


메모리보호기법2-01.png

출처)https://bpsecblog.wordpress.com/2016/05/18/memory_protect_linux_2/


puts호출할 경우
puts@plt를 호출하고 [PLT]

이때 jmp를 통해 puts@got.plt[addr1 이라하자]의 값을 참조해서이를 주소로서[GOT]

다시 puts@plt+6으로 이동(아까 실행한 inst다음주소)[PLT]

여기서 push n(reloc_offset)을 해주고 dl_runtime_resolve 함수로,

그 후에 _dl_fixup 함수로 이동하여 GOT[addr1]에 주소 업데이트[GOT업뎃] -->아래 자세히


got와plt-2-그림L

출처: https://bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/


reloc_offset을 push한 이후 _dl_runtime_resolve를 호출하고 이 내부에서는 link_map구조체 포인터를 push한 후 

_di_fixup을 호출한다. link_map 구조체는 ld loader가 참조하는 링크 지도, 

_di_fixup에서는 이 구조체를 이용해서 문자열 테이블(STRTAB)을 참고하고 재배치 테이블(JMPREL)을 참조,

reloc_offset을 이용해서 DYNSYM 해석 Symbol Table Pointer를 통해 실제 주소를 담아서 GOT에 기록


puts@got.plt가 더이상 puts@plt+6을 가르키지 않으며 이제 실제 주소로 이동 할 수 있다.


추가)

readelf -S 파일명: section headers 확인, .dynsym 의 주소를 알 수 있다.


추가)

함수 이름이 STRTAB테이블 내에 있지만 writable 하지 않다. STRTAB을 가르키는 포인터를 writable한 곳으로 조작 하면 원하는 함수 호출 가능