컴퓨터 시스템에서, 프로그램들이 함수나 변수를 공유해서 사용할 수 있다.
대부분의 컴파일 언어들은 자주 사용되는 함수들의 정의를 묶어서
하나의 라이브러리 파일로 만들고, 여러 프로그램이 공유해서 사용할 수 있도록 지원하고 있다.
libc - C언어의 표준 라이브러리/lib/x86_64-linux-gnu/libc-2.27.so
프로그램에서 어떤 라이브러리의 함수를 사용하면,
호출된 함수와 실제 라이브러리 함수가 링크 과정에서 연결된다.
- 연결되지 않은 모습 (실행 불가능)
- libc에서 puts의 정의를 찾아 연결한 모습
libc가 있는/lib/x64_64-linux-gnu/
가 표준 라이브러리 경로에 포함되어 있어서
libc를 같이 컴파일하지 않았음에도 libc에서 해당 심볼을 탐색할 수 있다.링크의 종류
- 동적 링크
동적 링크된 바이너리를 실행하면 동적 라이브러리가 프로세스의 메모리에 매핑된다.
실행 중에 라이브러리 함수를 호출하면 매핑된 라이브러리에서 호출할 함수의 주소를 찾고,
그 함수를 실행한다.
puts
의 plt 주소를 호출한다.
plt : 함수의 주소를 라이브러리에서 찾기 위해 사용되는 테이블- 정적 링크
바이너리에 정적 라이브러리의 모든 함수가 포함된다. (용량 낭비)
puts
가 있는 주소를 직접 호출한다.실제로 용량이 거의 무슨 80배 차이가 난다.
라이브러리에서 동적 링크된 심볼의 주소를 찾을 때 사용하는 테이블
함수의 정의를 매번 탐색하면 비효율적이므로,
GOT
라는 테이블을 두고, resolve 된 함수의 주소를 해당 테이블에 저장한다.
나중에 다시 해당 함수를 호출하면 저장된 주소를 꺼내서 사용한다.처음 상태
resolve 되기 전이므로 plt 주소가 적혀 있다.puts가 호출될 때
우선 PLT는puts
의 GOT인rip+0x2f75
에 쓰인 값으로 실행 흐름을 옮긴다.
현재 GOT에는puts@plt
의 주소가 쓰여 있으므로, 바로 다음줄의 코드를 실행하게 된다.
코드를 조금 더 실행시키면,dl_runtime_resolve_xsavec
라는 함수가 실행되어
puts
의 주소가 구해지고 GOT에 주소가 써진다.
이후에는 GOT에puts
의 주소가 쓰여 있어서 바로puts
가 실행된다.
GOT Overwrite
→ GOT의 값을 검증하지 않아, 공격자가 값을 임의로 바꾸면 원하는 코드가 실행되게 할 수 있다.