PLT, GOT 정리(bpsecblog)
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)
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를 사용해서 공유 라이브러리 내의 함수 호출
첫번째 실행시:
출처)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업뎃] -->아래 자세히
출처: 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한 곳으로 조작 하면 원하는 함수 호출 가능