Address Space Layout Randomization(ASLR)은 바이너리가 실행될 때마다 스택, 힙, 공유 라이브러리 등을 임의의 주소에 할당하는 보호 기법입니다.
*ASLR 확인 명령어*
$ cat /proc/sys/kernel/randomize_va_space
2
0 : ASLR 적용X
1 : 스택, 힙, 라이브러리, vdso등
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); // 코드 영역의 함수 주소
}
$ ./addr
buf_stack addr: 0x7fff01ae4750
buf_heap addr: 0x1225260
libc_base addr: 0x7fb7ded48000
printf addr: 0x7fb7dedace40
main addr: 0x400667
$ ./addr
buf_stack addr: 0x7ffe38cde4a0
buf_heap addr: 0xa14260
libc_base addr: 0x7fe0f9ba0000
printf addr: 0x7fe0f9c04e40
main addr: 0x400667
$ ./addr
buf_stack addr: 0x7ffd118277e0
buf_heap addr: 0x78f260
libc_base addr: 0x7efced151000
printf addr: 0x7efced1b5e40
main addr: 0x400667
main
함수를 제외한 다른 영역의 주소는 모두 실행할 때마다 변경됩니다.printf
주소의 하위 12비트 값은 변경되지 않는데, ASLR이 적용될 때 파일을 페이지 단위로 임의 주소에 매핑하기 때문입니다.libc_base
와 printf
의 주소 차는 항상 같습니다.No-Execute(NX)는 실행에 사용되는 메모리 영역과 쓰기에 사용되는 메모리 영역을 분리하는 보호 기법입니다.
// NX 적용
gdb-peda$ vmmap
Start End Perm Name
0x00400000 0x00401000 r-xp /home/ion/dreamhack/ASLR_NX/addr
0x00600000 0x00601000 r--p /home/ion/dreamhack/ASLR_NX/addr
0x00601000 0x00602000 rw-p /home/ion/dreamhack/ASLR_NX/addr
0x00007ffff77de000 0x00007ffff79c5000 r-xp /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff79c5000 0x00007ffff7bc5000 ---p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bc5000 0x00007ffff7bc9000 r--p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bc9000 0x00007ffff7bcb000 rw-p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bcb000 0x00007ffff7bcf000 rw-p mapped
0x00007ffff7bcf000 0x00007ffff7bd2000 r-xp /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7bd2000 0x00007ffff7dd1000 ---p /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7dd1000 0x00007ffff7dd2000 r--p /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7dd2000 0x00007ffff7dd3000 rw-p /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7dd3000 0x00007ffff7dfc000 r-xp /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7fe8000 0x00007ffff7fed000 rw-p mapped
0x00007ffff7ff7000 0x00007ffff7ffb000 r--p [vvar]
0x00007ffff7ffb000 0x00007ffff7ffc000 r-xp [vdso]
0x00007ffff7ffc000 0x00007ffff7ffd000 r--p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffd000 0x00007ffff7ffe000 rw-p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffe000 0x00007ffff7fff000 rw-p mapped
0x00007ffffffde000 0x00007ffffffff000 rw-p [stack]
// NX 해제
gdb-peda$ vmmap
Start End Perm Name
0x00400000 0x00401000 r-xp /home/ion/dreamhack/ASLR_NX/addr2
0x00600000 0x00601000 r--p /home/ion/dreamhack/ASLR_NX/addr2
0x00601000 0x00602000 rw-p /home/ion/dreamhack/ASLR_NX/addr2
0x00007ffff77de000 0x00007ffff79c5000 r-xp /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff79c5000 0x00007ffff7bc5000 ---p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bc5000 0x00007ffff7bc9000 r--p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bc9000 0x00007ffff7bcb000 rw-p /lib/x86_64-linux-gnu/libc-2.27.so
0x00007ffff7bcb000 0x00007ffff7bcf000 rw-p mapped
0x00007ffff7bcf000 0x00007ffff7bd2000 r-xp /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7bd2000 0x00007ffff7dd1000 ---p /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7dd1000 0x00007ffff7dd2000 r--p /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7dd2000 0x00007ffff7dd3000 rw-p /lib/x86_64-linux-gnu/libdl-2.27.so
0x00007ffff7dd3000 0x00007ffff7dfc000 r-xp /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7fe8000 0x00007ffff7fed000 rw-p mapped
0x00007ffff7ff7000 0x00007ffff7ffb000 r--p [vvar]
0x00007ffff7ffb000 0x00007ffff7ffc000 r-xp [vdso]
0x00007ffff7ffc000 0x00007ffff7ffd000 r--p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffd000 0x00007ffff7ffe000 rw-p /lib/x86_64-linux-gnu/ld-2.27.so
0x00007ffff7ffe000 0x00007ffff7fff000 rw-p mapped
0x00007ffffffde000 0x00007ffffffff000 rwxp [stack]
NX 보호 기법을 활성화 한 경우랑 안 한 경우를 비교해보면 NX 보호 기법이 활성화되었을 때 stack에 실행 권한이 사라져서 Return to Shellcode 같은 공격을 할 수 없게 되었습니다.
checksec로 Nx 확인
$ checksec addr
[*] '/home/ion/dreamhack/ASLR_NX/addr'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)