您的位置:首页 > 其它

Pwnable之[Toddler's Bottle](三)--UAF

2018-03-30 11:42 316 查看

Pwnable之[Toddler’s Bottle]–UAF

UAF,use-after-free

顾名思义,就是释放过内存的重利用。

根据操作系统里的内存分配就知道,当分配给的一个代码释放后,如果再申请的内存大小<=原先内存的时候,内存的指针会优先指向前面被free的内存,即分配原先的内存,从而产生迷途指针。

通过迷途指针进行操作时,会错误地按照释放前的偏移逻辑去访问新内容。

详细可看这个解析:

https://en.wikipedia.org/wiki/Dangling_pointer

查看代码:

#include <fcntl.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;

class Human{//父类Human
private:
virtual void give_shell(){
system("/bin/sh");//虚函数getshell
}
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{//继承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);
//以只读的形式打开第二个参数,并给返回0,即将第二个参数执行完的第一个参数个长度的数据放入标准输入。
cout << "your data is allocated" << endl;
break;
case 3:
delete m;
delete w;
break;
default:
break;
}
}

return 0;
}


查看代码后可以很直观地发现一个UAF漏洞,选择3.free将man与woman释放掉,再选择2.after新开内存,这里触发UAF漏洞,给新开内存写入give_shell()地址,再次调用1就会使这里的内存调用give_shell()的地址,就能成功拿到shell去读flag。

再用IDA分析下具体该怎么利用。



F5打开发现Women和Man分配的空间长度为0x18也就是24。

对应的是这个代码



然后双击man进入man的构造函数。



再跟进0ff_401570.



在这里发现了give_shell()和introduce()。

说明Man继承Human即使是私有的give_shell()虚函数也会被继承。

gdb看一下内存里0x401570的情况



看来地址没有随机化。

调试下看下内存,当执行玩构造函数后。

可以看到m和w对应的虚函数的首地址





发现woman的地址0x40150在内存0xfe1090。



可以清晰地看到,women类对象在内存中按8字节对齐,依次保存了虚表指针(指向类Women的虚函数表0x401550),继承自基类的成员age( 0x15 = 21),继承自积累的成员name(字符串地址为0xfe1078,前往该地址查看内容即为“Jill”)。

那么Man的虚函数表0x4015470也是类似的。

验证了8位后再看这个women的虚函数地址:



在前面分析中我们知道0x40117a代表shell(),0x401376代表introduce()。

那么系统如果要调用introduce()是不是要0x401550+8?

在IDA查看:

当输入为1时的 w->introduce();



发现调用introduce()就是v13+8和v14+8

而v13和v14刚好是前面由Human类开辟的空间。

OK,验证完毕。只要给把这+8去掉就是shell()的地址位置了。

也就是输入的是0x401550-8=0x401548。当被调用introduce()时+8就是shell()的位置了。

或者用man的也行,0x401570-8=0x401568

构造payload:

python -c 'print "\x48\x15\x40\x00\x00\x00\x00\x00"' > /tmp/jaken
#python -c 'print "\x68\x15\x40\x00\x00\x00\x00\x00"' > /tmp/jaken1223


然后这里有个问题,因为它连续delete了m和w。所以2最好新建两次,防止指向NULL报错。

3->2->2->1 :



还是太菜了,一个简单的uaf就写这么多0 0…

涉及知识总结:

1》UAF漏洞的利用:

(1)先搞出来一个迷途指针

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

(3)再次使用该指针,让填充的数据使eip发生跳转。

2》UAF的条件:

(1)用户可以控制该对象的大小

(2)用户空间可以对该对象写入数据

如果碰巧这块问题内存新分配的数据是比如C++中的类,那这块内存堆对上可能散落着各种函数指针,只要用shellcode的地址覆盖其中一个函数指针,就能够达成执行任意指令。


3》malloc函数做了那些事情。

https://blog.csdn.net/qq_32635069/article/details/74838187

https://blog.csdn.net/u011974987/article/details/52290724

//缩小,缩小的那一部分数据会丢失

//扩大,(连续的)

1.如果当前内存段后面有需要的内存空间,直接扩展这段内存空间,realloc返回原指针

2.如果当前内存段后面的空闲字节不够,那么就使用堆中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据库释放掉,返回新的内存地址

3.如果申请失败,返回NULL,原来的指针仍然有效.

这也就是UAF产生的原因。

内存注意细节。

1.不能多次释放;

2.释放完之后(指针仍然有值),给指针置NULL,标志释放完成;

3.内存泄露(p重新赋值之后,再free,并没有真正释放内存);


4》虚函数表的结构

1.虚函数,一旦一个类使用了虚函数,编译器便会为这个类建立一张vtable。子类继承父类vtable中所有项,当子类有同名函数时,修改vtable同名函数地址,改为指向子类的函数地址,子类有新的虚函数时,在vtable中添加。

2.同时,私有函数无法继承,但如果私有函数是虚函数,vtable中会有相应的函数地址,所有子类可以通过手段得到父类的虚私有函数。

3.每一个类只有唯一的一个vtable,不是每个对象都有一个vtable,恰恰是每个同一个类的对象都有一个指针,这个指针指向该类的vtable(当然,前提是这个类包含虚函数)。那么,每个对象只额外增加了一个指针的大小,一般说来是4字节。

4.在类对象的内存布局中,首先是该类的vtable指针,然后才是对象数据。

在通过对象指针调用一个虚函数时,编译器生成的代码将先获取对象类的vtable指针,然后调用vtable中对应的项。

参考文章:

https://www.jianshu.com/p/04e963d7e0bc

http://blog.sina.com.cn/s/blog_e23a215b0102whgy.html

https://www.cnblogs.com/p4nda/p/7149870.html

https://blog.csdn.net/qq_20307987/article/details/51511230
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: