C++一直都没有深入学习过,以后还是要抽时间看看(尽量不鸽,感觉想学的东西太多了)。就一道pwn题,而且是基于C++,花了一点时间学习 vector
是啥。
We love free
程序提示使用了 Vector
,Vector
是一个动态大小的数组容器,可以根据用户的输入,动态的增大缓存。vector
的扩容规则是1,2,4,8,16,32,依次乘2个元素的时候会先申请新的空间,在把原来的数据拷贝到新申请的空间中,在释放原先的空间,对应申请的堆块大小(加上头部)0x20,0x20,0x30,0x50,0x90…..
Vector有一个结构体:
1 | Vector_struct{ |
程序分析
在 Show
函数中,会先向 Vector
中存入一个 0xAABBCCDD
的值,这个值可能会使Vector
扩容,导致初始时得到的堆块首地址是旧堆块的地址。 存在一个 Edit
功能,使用的是旧堆块的地址,但是size
却是扩容后的新堆块的size
,这就导致了 UAF
漏洞。
利用分析
- 泄露libc地址
先存入 16个数据,此时Vector
大小为 0x90。再调用 Show
函数,会先存入 0xAABBCCDD
的值,导致堆块扩容到 0x110
,原有堆块则会被放入 unsortedbin
中,然后即可将 libc
地址泄露出来。调用 clear
,将所有堆块释放。
unsotedbin attack
先在heap
中布上 0x20 个 one_gadget
地址,随后调用 clear
将所有堆块释放。随后申请 16 个数据,再调用 Show
函数,使用 Edit
功能修改 unsortedbin
的 bk
指针指到 stdin@GLIBC-0x8
的位置,并且修改新申请的 chunk
的 size
,将其改小。这样调用 clear
函数时,我们修改的unsortedbin
就不会被合并。
- 触发FSOP
然后就是再 输入 9个数据,Vector
就会扩容到 0x90
,也就是触发了 unsortedbin attack
。此时 std::cin@GLIBC
的值被改为了一个 Heap
地址,然后再后面在执行 std::cin
时就会触发FSOP
。我们再通过触发 stdin
就能够 getshell
。
EXP
1 | from pwn import * |
- 本文作者: A1ex
- 本文链接: http://yoursite.com/2020/09/25/DDCTF-PWN/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!