01 NX
(1) NX
No-eXecute(NX)는 실행에 사용되는 메모리 영역과 쓰기에 사용되는 메모리 영역을 분리하는 보호 기법
▶ 어떤 메모리 영역에 대해 쓰기 권한과 실행 권한이 함께 있으면 시스템이 취약해지기 쉽다.
- CPU가 NX를 지원하면 컴파일러 옵션을 통해 바이너리에 NX를 적용할 수 있음
- NX가 적용된 바이너리는 실행될 때 각 메모리 영역에 필요한 권한만 부여받음
- NX가 적용된 바이너리에는 코드 영역 외에 실행 권한이 없음
- 반면, NX가 적용되지 않은 바이너리에는 스택 영역([stack])에 실행 권한이 존재하여 rwx 권한을 가지고 있음
📌 NX의 다양한 명칭
NX를 인텔은 XD(eXecute Disable) , AMD는 NX, 윈도우는 DEP(Data Execution Prevention) , ARM에서는 XN(eXecute Never) 라고 칭하고 있다. 명칭만 다를 뿐 모두 비슷한 보호 기법이다.
(2) Return to shellcode w/t NX
이전에 실습한 예제인 r2s에 NX 보호기법 적용 후, 동일한 익스플로잇을 실행했을 때 결과를 확인해보자.
r2s.c에 대해 -zexecstack 옵션 제거 후 컴파일하고나서 checksec으로 확인해보면 NX가 활성화되어 있음을 확인할 수 있다.
이후 해당 바이너리 대상 익스플로잇 코드를 실행하면, 아래와 같이 Segmentation fault가 발생하며 NX가 적용되어 스택 영역에 실행 권한이 사라져 셸 코드가 실행되지 못하고 종료된 것임을 알 수 있다.
02 ASLR
Address Space Layout Randomization(ASLR)은 바이너리가 실행될 때마다 스택, 힙, 공유 라이브러리 등을 임의의 주소에 할당하는 보호 기법
▶ ASLR은 커널에서 지원하는 보호 기법이며, 다음의 명령어로 확인할 수 있다.
$ cat /proc/sys/kernel/randomize_va_space
✅ ASLR이 적용되는 메모리 영역
- No ASLR(0): ASLR을 적용하지 않음
- Conservative Randomization(1): 스택, 힙, 라이브러리, vdso 등
- Conservative Randomization + brk(2): (1)의 영역과 brk로 할당한 영역
예제 코드를 통해 해당 기법에 대해 더욱 자세히 살펴보자.
📌 예제 코드
// 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); // 코드 영역의 함수 주소 }
작성한 예제코드를 gcc로 컴파일 후 실행해보면 다음과 같은 결과를 확인할 수 있다.
위 실행 결과를 통해 스택 영역의 buf_stack, 힙 영역의 buf_heap, 라이브러리 함수 printf, 코드 영역의 함수 main, 그리고 라이브러리 매핑 주소 libc_base가 출력되었습니다. 결과를 살펴보면 다음과 같은 특징이 있음을 알 수 있다.
- 코드 영역의 main함수를 제외한 다른 영역의 주소들은 실행할 때마다 변경됨
- 실행할 때 마다 주소가 변경되기 때문에 바이너리를 실행하기 전에 해당 영역들의 주소를 예측할 수 없음
- 바이너리를 반복해서 실행해도 libc_base 주소 하위 12비트 값과 printf 주소 하위 12비트 값은 변경되지 않음
- libc_base와 printf의 주소 차이는 항상 같다. ASLR이 적용되면, 라이브러리는 임의 주소에 매핑된다. 그러나 라이브러리 파일을 그대로 매핑하는 것이므로 매핑된 주소로부터 라이브러리의 다른 심볼들 까지의 거리(Offset)는 항상 같다.
참고자료 : https://dreamhack.io/lecture/roadmaps/2
'Security > System Hacking' 카테고리의 다른 글
[Bypass NX & ASLR] Return to Library (2) | 2024.10.09 |
---|---|
[Bypass NX & ASLR] Static Link vs. Dynamic Link (1) | 2024.10.09 |
basic_exploitation_000 (0) | 2024.10.09 |
basic_exploitation_001 (0) | 2024.10.09 |
[Bypass NX & ASLR] Return Oriented Programming (0) | 2024.10.09 |