Address Space Layout Randomiazation
바이너리가 실행될 때마다 스택, 힙, 공유 라이브러리 등을 임의의 주소에 할당하는,
커널에서 지원하는 보호 기법
예시 코드// Name: addr.c // Compile: gcc addr.c -o addr -ldl -no-pie -fno-PIE #include <dlfcn.h> #include <stdio.h> #include <stdlib.h> int main() { char buf_stack[0x10]; // 스택 버퍼 char *buf_heap = (char *)malloc(0x10); // 힙 버퍼 printf("buf_stack addr: %p\n", buf_stack); printf("buf_heap addr: %p\n", buf_heap); printf("libc_base addr: %p\n", *(void **)dlopen("libc.so.6", RTLD_LAZY)); // 라이브러리 주소 printf("printf addr: %p\n", dlsym(dlopen("libc.so.6", RTLD_LAZY), "printf")); // 라이브러리 함수의 주소 printf("main addr: %p\n", main); // 코드 영역의 함수 주소 }
스택 영역, 힙 영역, 라이브러리 함수, 코드 영역 함수, 라이브러리 매핑 주소를 출력
- ASLR 기법이 적용되어
main
함수를 제외한 다른 영역들의 주소가 실행마다 변경된다.printf
주소의 하위 12비트값(3자리)는 변경되지 않는다.libc_base
와printf
주소 차이는 항상 같다. (라이브러리 파일을 그대로 매핑하므로)
No-eXecute
실행에 사용되는 메모리 영역과 쓰기에 사용되는 메모리 영역을 분리하는 보호 기법
- 코드 영역에 쓰기 권한이 있으면 공격자가 코드룰 수정하여 원하는 코드가 실행되게 할 수 있다.
- 스택/데이터 영역에 실행 권한이 있으면
Return to Shellcode
와 같은 공격을 시도할 수 있다.NX가 적용된 바이너리는 실행될 때 각 메모리 영역에 "필요한" 권한만 부여받는다.
→ 스택, 힙, 데이터 영역에는 실행권한이 제거된다.NX의 다양한 명칭 (명칭만 다를 뿐 모두 비슷한 보호 기법)
- 인텔은 XD(eXecute Disable)
- AMD는 NX(No-eXecute)
- 윈도우는 DEP(Data Execution Prevention)
- ARM은 XN(eXecute Never)
- RTL(Return-to-Libc)
- ROP(Return Oriented Programming)