한희수 2024. 5. 23. 21:07

ASLR(Address Space Layout Randomization) : 바이너리가 실행될 때마다 스택, 힙, 공유 라이브러리 등을 임의의 주소에 할당하는 보호 기법

 

ASLR 설정

echo [0|1|2] > /proc/sys/kernel/randomize_va_space
  • 0 : ASLR 해제
  • 1 : 랜덤 스택 & 랜덤 라이브러리 설정
  • 2 : 랜덤 스택 & 랜덤 라이브러리 & 랜덤 힙 설정

 

ASLR 확인

cat /proc/sys/kernel/randomize_va_space

 

Example

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *global = "Lazenca.0x0";

int main(){
    char *heap = malloc(100);
    char *stack[] = {"LAZENCA.0x0"};

    printf("[Heap]  address: %p\n", heap);
    printf("[Stack] address: %p\n", stack);
    printf("[libc]  address: %p\n",**(&stack + 3));
    printf("[.data] address: %p\n",global);
    free(heap);
    return 0;
}
echo 0 > /proc/sys/kernel/randomize_va_space

ASLR이 적용되지 않았을 때, 힙, 스택, 라이브러리, 데이터의 주소가 모두 똑같은 것을 확인할 수 있다.

 

echo 1 > /proc/sys/kernel/randomize_va_space

 

ASLR이 1로 적용됐을 때, 스택, 라이브러리 영역이 달라진 것을 확인할 수 있다.

 

echo 2 > /proc/sys/kernel/randomize_va_space

ASLR이 2로 설정됐을 때, 힙, 스택, 라이브러리 영역이 달라진 것을 확인할 수 있다.

 

ASLR 우회

ASLR이 설정된 문제일 경우, 힙, 스택, 라이브러리 영역의 주소가 달라지는 것을 유의해야 한다.

하지만 ASLR 환경에서도 라이브러리의 base 주소가 바뀔 뿐, 라이브러리 내부 함수들의 offset은 고정되어 있다. 이를 활용하면 특정 라이브러리 함수의 주소를 알아낼 수 있다. 

 

Example

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    printf("stdout: %p\n", stdout);
    return 0;
}

위는 stdout의 주소를 출력해주는 코드이다.

 

해당 코드를 실행할 때마다, stdout의 주소가 바뀌는 것을 확인할 수 있다.

 

gdb를 통해 라이브러리의 base 주소와 stdout의 주소의 차이를 빼서 offset 주소를 구할 수 있다.

 

이를 통해 구한 offset으로 출력해주는 stdout의 주소를 빼면 라이브러리의 base 주소를 구할 수 있다. 해당 라이브러리의 base 주소에 원하는 함수의 offset을 더하여 ASLR이 적용된 문제를 해결할 수 있다.