1. ASLR (Address Space Layout Randomization)
- ASLR은 운영체제가 프로세스의 메모리 주소 공간을 무작위로 배치하는 기법
- 프로그램이 실행될 때마다 스택, 힙, 라이브러리 주소를 랜덤화
- 데이터의 주소가 매번 바뀌므로, 공격자가 특정 주소를 이용해 익스폴로잇하는 것을 어렵게 함
- 리눅스에서 ASLR 동작 방식 전역 설정
// ASLR 비활성화
# echo 0 > /proc/sys/kernel/randomize_va_space
// 경미한 무작위화 (스택, 힙 공유 라이브러리)
# echo 1 > /proc/sys/kernel/randomize_va_space
// 강화된 무작위화 (실행 파일, 스택, 힙, 공유 라이브러리)
# echo 2 > /proc/sys/kernel/randomize_va_space
- ASLR 테스트
#include <stdio.h>
#include <stdlib.h>
int main() {
int stack;
void *heap = malloc(0x10);
printf("stack @ %016p\n", &stack);
printf("heap @ %016p\n", heap);
printf("library @ %016p\n", printf);
free(heap);
return 0;
}
$ ./aslr
stack @ 0x007ffe40399384
heap @ 0x0055bd1db792a0
library @ 0x007f3a99c675b0
$ ./aslr
stack @ 0x007ffd7ca88cd4
heap @ 0x005650216752a0
library @ 0x007f1c7d2115b0
$ ./aslr
stack @ 0x007ffeff6ac284
heap @ 0x0055f759eed2a0
library @ 0x007fd40346d5b0
2. PIE (Position Independent Executable)
- PIE는 바이너리 파일을 주소에 의존하지 않도록 설계하여, 프로그램이 임의의 메모리 주소에서 실행될 수 있도록 함
- 전역변수, 함수 등의 주소가 매번 바뀌므로 특정 실행 파일의 메모리 주소를 알고 공격하는 것을 방지
- PIE로 컴파일된 실행 파일은 기본적으로 상대 주소를 사용하여 코드와 데이터를 참조
- PIE는 ALSR과 경합하여 동작
3. NX (No-eXecute) / DEP (Data Execution Prevention)
- 리눅스에서는 NX, 윈도우에서는 DEP로 표현
- 메모리의 스택이나 힙 영역에서 코드의 실행 권한을 제한
- 스택 버퍼에 ShellCode를 삽입하고 해당 주소를 복귀 주소로 덮어 쓰는 공격이 불가능
- 스택에 실행권한이 없으므로, Shellcode는 실행 코드가 아닌 단순 데이터가 되기 때문
- 이를 우회하기 위해서는 RTL, ROP 공격 기법을 사용
- NX 활성화 전
- NX 활성화 후
4. Stack Canary
- Stack canary는 스택 버퍼 오버플로우 공격을 방지하기 위한 기법
- 함수 프롤로그에서 지역변수와 SFP 사이에 검증 값을 삽입하고, 에필로그에서 해당 값이 변조되었는지 확인
- 값이 변조되었다면, 메모리가 오염되었다고 판단하고 프로그램을 종료
5. RELRO (RELocation Read-Only)
- ELF 바이너리의 GOT 세션을 읽기 전용으로 만들어 보호하는 기법
- Partial RELRO : GOT 섹션의 non-PLT 부분만 읽기 전용, .got.plt는 쓰기 가능
- Full RELRO : GOT 섹션 전체가 읽기 전용