Self-Improvement

[pwnable.kr] uaf 풀이 본문

리버싱 기초/pwnable.kr

[pwnable.kr] uaf 풀이

JoGeun 2020. 7. 13. 15:59

 

소스코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <fcntl.h>
#include <iostream> 
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;
 
class Human{
private:
    virtual void give_shell(){
        system("/bin/sh");
    }
protected:
    int age;
    string name;
public:
    virtual void introduce(){
        cout << "My name is " << name << endl;
        cout << "I am " << age << " years old" << endl;
    }
};
 
class Man: public Human{
public:
    Man(string name, int age){
        this->name = name;
        this->age = age;
        }
        virtual void introduce(){
        Human::introduce();
                cout << "I am a nice guy!" << endl;
        }
};
 
class Woman: public Human{
public:
        Woman(string name, int age){
                this->name = name;
                this->age = age;
        }
        virtual void introduce(){
                Human::introduce();
                cout << "I am a cute girl!" << endl;
        }
};
 
int main(int argc, char* argv[]){
    Human* m = new Man("Jack"25);
    Human* w = new Woman("Jill"21);
 
    size_t len;
    char* data;
    unsigned int op;
    while(1){
        cout << "1. use\n2. after\n3. free\n";
        cin >> op;
 
        switch(op){
            case 1:
                m->introduce();
                w->introduce();
                break;
            case 2:
                len = atoi(argv[1]);
                data = new char[len];
                read(open(argv[2], O_RDONLY), data, len);
                cout << "your data is allocated" << endl;
                break;
            case 3:
                delete m;
                delete w;
                break;
            default:
                break;
        }
    }
 
    return 0;    
}
cs

소스코드를 보기 앞서서 UAF에 대해서 정리를 해두었다. heap 영역의 취약점으로 보면 되겠다. https://johyungen.tistory.com/443

 

Heap OverFlow, Use After Free(UAF) gdb 분석

소스코드 출처 : https://bpsecblog.wordpress.com/2016/10/06/heap_vuln/ Heap OverFlow 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include #include int main(void) {     FILE* fd = fopen("secret","r");..

johyungen.tistory.com

소스코드를 분석해보자면 C++로 멤버함수포인터?를 사용하고 있다. 1번을 선택할 시 m, w 객체?를 사용하고 2번 선택 시 인자에서 입력한 파일안의 내용을 읽어서 쓰고 있으며 3번을 선택할 시 delete로 m, w객체를 정리를 해주고 있다. 그리고 친절하게도 give_shell()에서 쉘을 주고 있다.

결론적으로 UAF가 힌트임으로 생각엔 1번 -> 3번 -> 2번(give_shell()) -> 1번 ?? 이런식으로 사용하면 될것같다.

 

풀이

switch 문은 아래와 같이 진행되고 있다.

 

- Case 1

main+286, main+309는 각 introduce() 함수를 수행하는 곳이다.

 

"m->introduce();" 부분을 보자면 

 

main+265의 rbp-0x38의 값을 rax에

 

rax의 값을 rax 주소에

※ 0x0040117a는 give_shell()이다!!!

 

rax 주소에 +0x8을 더한다

 

rax의 값을 rdx 주소에 넣어주며 rdx는 introduce 함수로 되어진다.

이렇게 Case 1번이 이루어지며

 

- Case 3

3번을 수행할 시엔 m, w 객체가 delete가 되어진다. (Case1번에서는 0xf7ac50에는 0x00401570이 있었지만 사라졌다)

 

- Case 2 (case3을 수행한 뒤에 case2를 수행 해본다)

Case2에서는 인자를 2개를 받고 있으면 첫번째 인자는 read함수의 길이, 두번쨰 인자는 읽어들일 파일의 내용이다.

미리 /tmp/ababb에 "AAAA"를 넣고 수행하면 어떻게 되는지 확인해 본다.

 

read함수가 제일 중요함으로 b *main+399로 잡고 read함수로 넘어가는 인자를 확인해본다.

(어디 주소에 써지는지 확인하기 위해)

 

인자는 총 3개로 64bit 환경에서는 스택이 아닌 레지스터로 넘어가게 되어있다.

rsi, rdi, rdx 각 인자를 확인해보자

rsi는 파일의 내용이 쓰여질 주소이다, rdi는 open()함수의 리턴 값으로 fd 값이다, rdx는 인자1(argv[1])이다.

 

read함수를 수행하고 rsi 값을 확인해보면 /tmp/ababb 파일의 내용인 "AAAA"가 쓰여졌다.

※ 처음엔 rbp-0x38 주소에 값이 안쓰여지는거 보고 아닌줄 알았는데 한번더 실행하니 rbp-0x38 에 쓰여지는 걸 확인했다. (재실행을 하여서 case 1에서 본 주소가 다를수 있습니다.)

 

종합

이렇게 되면 파일의 내용엔 give_shell()함수의 주소를 넣어두고 after을 2번 수행 후 case 1을 수행하면 쉘이 떨어질 것이다.

give_shell()을 구하는 방식은 기존에 case 1하면서 알게 되었고 아래와 같이해도 구해진다.

(gdb) disassemble _ZN5Human10give_shellEv

 

0x40117a를 넣으면 될거라고 생각하였지만 case 1을 다시 보면 +0x8을 수행하고 있음으로 0x40117a-0x8의 값을 파일의 내용에 넣으면 될 것이다.

 

실행 순서는 3(free) ---> 2(after) ----> 2(after) ----> 1(use) 이다.

'리버싱 기초 > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] cmd2 풀이  (0) 2020.06.24
[pwnable.kr] cmd1 풀이  (0) 2020.06.24
[pwnable.kr] lotto 풀이  (0) 2020.06.24
[pwnable.kr] blackjack 풀이  (0) 2020.06.24
[pwnable.kr] shellshock 풀이 (쉘숔 CVE-2014-6271)  (0) 2020.06.24