메모리 보호 기법

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 섹션 전체가 읽기 전용