ELF는GOT를 활용하여 반복되는 라이브러리 함수의 호출 비용을 줄인다.
Lazy Binding : 함수가 처음 호출될 때 함수의 주소를 구하고, 이를GOT에 적는 것
→GOT에 쓰기 권한 부여 → 바이너리가 취약해짐
ELF의 데이터 세그먼트에는 프로세스의 초기화 및 종료와 관련된
.init_array,.fini_array가 있다.
→ 여기에 공격자가 임의로 값을 쓸 수 있다면, 프로세스의 실행 흐름이 조작될 수 있다.
RELocation Read-Only
쓰기 권한이 불필요한 데이터 세그먼트에 쓰기 권한을 제거
- Partial RELRO : RELRO의 부분적 적용
- Full RELRO : 가장 넓은 영역에 RELRO를 적용
예제 코드
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { FILE *fp; char ch; fp = fopen("/proc/self/maps", "r"); while (1) { ch = fgetc(fp); if (ch == EOF) break; putchar(ch); } return 0; }
Partial RELRO가 적용되어 있다.
00404000~00405000에 쓰기 권한이 있다.
.got.plt,.data,.bss,.comment가 할당되어 있다.
.init_array와.fini_array는 다른 영역에 할당되어 있다.
.got: 전역 변수 중에서 실행되는 시점에 바인딩 되는 변수들이 위치 (쓰기 권한 제거).got.plt: Lazy Binding 되는 변수들 (쓰기 권한 부여)GOT Overwrite와 같은 공격으로 우회가 가능하다.
GOT에도 쓰기 권한을 제거한다.
Lazy Binding을 사용하지 않으며,
라이브러리 함수들의 주소는 바이너리가 로드되는 시점에 바인딩된다.
libc의 malloc hook, free hook과 같은 함수 포인터를 조작하는 공격으로 우회가 가능하다.