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과 같은 함수 포인터를 조작하는 공격으로 우회가 가능하다.