[Heap Exploit] UAF(Use After Free)기법 이론설명

두비니

·

2019. 7. 29. 18:04

 

 

 

Heap Exploit

UAF(Use After Free)기법 이론설명

 

 

당분간은 Heap의 취약점 분석을 할 것인데요, 오늘은 UAF(Use After Free)기법입니다.

 


 

UAF기법을 들어가기 전에, Heap구조가 무엇인지 알아야겠죠? 모른다면, 공부를 조금 하고 다시 돌아오는 것으로 합시다.

 

아무튼 다들 Heap구조를 어느정도 알고 있다는 전제 하에 진행을 하면, 

Heap구조는 컴퓨터 안의 메모리 구조 중 사용자가 임의로 사용하는 메모리 공간으로, 대표적으로 malloc함수를 이용해 선언해주고, free함수를 통해 해제를 해준다는 것을 알 수 있습니다. 본격적으로 설명해봅시다.

 


 

 

1. First-Fit 알고리즘

 

UAF에 대해서 본격적으로 들어가기 전에, First-Fit 알고리즘에 대해서 이해할 필요가 있어서 간단하게 설명하고 넘어가고자 합니다.

 

First-Fit 알고리즘이란 메모리 할당 전략 중 하나로, 리눅스 운영체제는 이 알고리즘을 채택하고 있습니다.

참고로 First-Fit 말고도 Best-Fit, Worst-Fit도 있다는 점은 참고로 알아둡시다.

 

일단 이름만 보면 제일 뭔가 제일 첫 번째 메모리를 할당해주겠다는 얘기같은데.....맞습니다. 자세한 설명은 다음 코드를 보도록 합시다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char *= malloc(20);     // 0xe4b010
char *= malloc(20);     // 0xe4b030
char *= malloc(20);     // 0xe4b050
char *= malloc(20);     // 0xe4b070
 
free(a);
free(b);
free(c);
free(d);
 
= malloc(20);           // 0xe4b070
= malloc(20);           // 0xe4b050
= malloc(20);           // 0xe4b030
= malloc(20);           // 0xe4b010
cs

 

코드를 보면 각각 20바이트씩 heap에 4개의 을 영역할당해주었고, free를 해준 후 다시 4개의 영역을 할당받았습니다.

이때 할당이 되는 과정에서 주목할 점은, LIFO(Last In First Out)이라는 점입니다. 밑의 단계별 구조를 참고합시다.

 

1. 'a' freed.
head -> a -> tail
2. 'b' freed.
head -> b -> a -> tail
3. 'c' freed.
head -> c -> b -> a -> tail
4. 'd' freed.
head -> d -> c -> b -> a -> tail
5. 'malloc' request.
head -> c -> b -> a -> tail [ 'd' is returned ]
6. 'malloc' request.
head -> b -> a -> tail [ 'c' is returned ]
7. 'malloc' request.
head -> a -> tail [ 'b' is returned ]
8. 'malloc' request.
head -> tail [ 'a' is returned ]

 

이정도 과정을 이해할 수 있다면 First-fit 알고리즘은 완벽히 이해했다고 볼 수 있습니다:D

 

 

 


 

2. UAF(Use After Free) 개념 설명

 

 

이제 UAF 취약점의 이론설명으로 넘어가도록 합시다.

UAF취약점은 말 그대로 Use After Free, 메모리를 해제하고 다시 이용할 때 생기는 취약점입니다. 이 또한 아래 예제 코드로 자세히 알아보도록 합시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    int* heap1;
    int* heap2;
    int* heap3;
 
    heap1 = (int*)malloc(256);
    heap2 = (int*)malloc(256);
 
    printf("heap1의 주소 : %p\n", heap1);
    printf("heap2의 주소 : %p\n", heap2);        
 
    *heap2 = 1234;
    printf("heap2 number : %d\n"*heap2);        //1234
 
    free(heap2);
    printf("free heap2\n");
 
    heap3 = (int*)malloc(256);
    printf("new heap의 주소 : %p\n", heap3);
    printf("new heap number: %d\n"*heap3);    //안에있는 값은 초기화됨
    *heap3 = 4321;
    printf("new heap의 내용을 \"%d\"로 바꾸었습니다.\n\n"*heap3);
 
    printf("heap2를 다시 부른다면?: %d\n"*heap2);  //heap3의 값과 
 
    return 0;
}
cs

 

분석을 해봅시다.

10/11. heap1과 heap2에 공간을 할당해주었다.

16. heap2의 값을 1234로 바꾸었다.

19. heap2를 free한 후

22. heap3을 다시 malloc한다. 이때 heap3에는 heap2의 주소가 들어가게 된다. (first-fit, 23에서 확인)

24. heap3의 값을 확인해보면 안에 있는 값은 초기화된 것을 알 수 있다.

25. heap3에 새로운 값을 넣어주고, 

28. heap2의 값을 확인하면 heap3의 값이 나오는 것을 확인 할 수 있다.

 

다음은 결과 화면이다.

이렇게 되면 우리는 문제를 풀 때 어떤 heap영역을 free를 해주는 걸 본다면, 이를 UAF를 이용하여 새로운 heap을 할당해주고, 내가 원하는 값을 입력한 후 기존 heap을 실행시켜서 exploit시킬 수 있습니다. 이게 기본적인 UAF의 개념입니다. 

 

 

 

 


::참고::

https://bpsecblog.wordpress.com/2016/10/06/heap_vuln/

https://heap-exploitation.dhavalkapil.com/attacks/first_fit.html

https://shayete.tistory.com/entry/7-Use-After-Free

https://nroses-taek.tistory.com/156

https://code1018.tistory.com/192