缓冲区溢出-printf格式化输出漏洞
0x00本文视频:
如果文字过于枯燥可观看在线视频:https://edu.51cto.com/sd/16514
0x01基础知识:
在c语言中printf的使用方法为printf(format,<参量表>),printf是c语言中少见的可变参数的库函数,printf在调用前无法知道传入的参数到底有多少个(在32位汇编中参数都是压入栈中,也就是说printf不知到有多少个参数入栈了),例如printf("My name is %s,%s"),这里format指定了要传递2个参数,但我们并没有传,这时候printf就会去栈中高地址四字节数据来填充%s,也就是:format+4,format+8的值进行填充。
下面举个例子:
编译:gcc -m32 -O0 base.c -o ./base 编译为32位。
这是我们的测试代码,在printf里没有给printf传递%s对应的值,我们一起来看下执行效果:
你会发现,我们没有传递str变量,但还是打印了,我们使用GDB来调试下,看是否和我们前面说的使用format+4地址来填充.
汇编代码执行到printf的时候我们暂停,看看栈中的数据:
format数据是0x8048580,对应在栈空间的位置:0xffffd5c0,按照之前的计算format+4对应的值为Margin,这样我们便验证成功了。
利用这个思路,我们可以考虑下,既然可以使用%s来打印栈空间的内容,那是不是所有栈空间的内容都可以打印,我使用%s时打印的是format+4,那我使用两个%s%s打印的是不是format+4,format+8的内容,以此类推我们可以将栈空间所有值都可以打印出来。接下来我们用一个实验来验证下我们的想法。
下面我们要做的是使用printf的格式化漏洞来泄漏canary的值来达到绕过的目的。
第一步:我们先分析下c语言代码
代码中的func函数是有一个printf函数,存在格式化字符串漏洞,正常写法应该是printf("My name is %s",name)。
编译:gcc -fstack-protector -m32 -o0 c.c -o ./c
第二步:确认canary的位置(偏移量)
思路是:先找到我们输入内容的位置x,在找到canary位置y,然后x-y得到偏移量
在printf位置打断点:b printf
在gdb里执行r运行程序,然后输入aaaa(这里随意写,写aaaa的意义在于在栈空间里好找,都是61616161)
1.打印ebp的值,在函数运行时要保存ebp的值,所以,我们只要在函数运行的时候找到即可。执行命令disass func查看func函数汇编代码,在0x080484ea的位置打断点,因为gs:0x14的值就是Canary的值。
打断点:b *0x080484ea,执行到此处,在输入两次n,执行完mov dword ptr [ebp-0xc],eax后canary的值就在eax中了
可以看到canary的值为0xb26f7f00
我们在打断点b printf,然后执行c,执行到该断点(中间我们输入margin)
1.找到canary在栈中的位置:p $ebp (因为canary在ebp附近)
在栈中找到ebp的位置,执行:stack 0x28(意思是要看四十行栈数据)
我们知道在栈帧空间中布局如下:
可以看到canary在0xffffd5ec的位置,我们输入的margin字符串在0xffffd5b0位置,但是指向的是0xffffd5cc,所以我们可以计算我们输入的margin字符串距离canary:0xffffd5ec - 0xffffd5cc = 32,所以,我们如果要覆盖canary需要32个字符。
第三部:动态获取canary
现在我们知道了canary的偏移量,但是我们还不知道canary的动态值,这里我们就需要用到printf函数的格式化漏洞(回忆下前面讲的format+4),上面截图我们可以看到printf第一个参数距离canary有15所以我们可以输入%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x来得到canary的值(最后8位是canary),或者简化写法%15$08x.
第四步:获取shell
在程序中我们已经知道了有一个exploit函数可以让我们直接获取shell,所以我们就把func函数的返回地址直接覆盖为exploit即可
从上面步骤截图中我们可以看到canary到ebp是12,所以payload为:
'a' * 32 + canary + 'a' * 12 + exploit地址
python代码为:
转载于:https://blog.51cto.com/11797152/2379731
缓冲区溢出-printf格式化输出漏洞相关推荐
- C语言 printf格式化输出,参数详解
有关输出对齐 int main(int argc, char* argv[]) { char insertTime[20] = {"1234567890"}; double i ...
- C语言scanf()函数格式化输入和printf()格式化输出。
scanf函数格式化输入和printf格式化输出 要实现的功能如下 完整源代码实现如下 要实现的功能如下 scanf函数格式化输入字符串和字符,printf格式化输出字符串和字符. 完整源代码实现如下 ...
- c++ 输出二进制_C语言 printf 格式化输出的详细示例
printf 是C语言非常有用的一个函数,也是我们入门学习C语言的第一个函数.掌握 printf 的格式化输出,对后续的学习非常有帮助. 在程序中要使用 printf,必须要包含头文件 stdio.h ...
- 【C/C++】printf格式化输出-科学计数法形式的浮点数
C语言printf格式化输出修饰符 printf()的格式符 转换说明 输出 %a, %A 浮点数.十六进制数和p-计数法(C99) %c 一个字符 %d 有符号十进制数 %e, %E 浮点数,e计数 ...
- matlab printf格式化输出,Shell printf格式化输出命令
printf 是 awk 的重要格式化输出命令,本节我们先介绍一下 printf 命令如何使用. 需要注意,在 awk 中可以识别 print 输出动作和 printf 输出动作(区别是:print ...
- Shell printf格式化输出命令
printf 是 awk 的重要格式化输出命令,本节我们先介绍一下 printf 命令如何使用. 需要注意,在 awk 中可以识别 print 输出动作和 printf 输出动作(区别是:print ...
- golang printf 格式化输出
Printf 格式化输出 通用占位符: v 值的默认格式. %+v 添加字段名(如结构体) %#v 相应值的Go语法表示 %T 相应值的类型的Go语法表示 %% 字面上的百分号,并非值的占位符 布尔值 ...
- Go语言基础--Printf格式化输出、Scanf格式化输入详解
几种输出方式的区别 Print.Println .Printf .Sprintf .Fprintf都是fmt 包中的公共方法,在需要打印信息时需要用到这些函数,那么这些函数有什么区别呢? Print: ...
- 什么是缓冲区溢出以及如何利用漏洞?
在信息安全和编程中,缓冲区溢出是一种异常,其中程序在将数据写入缓冲区时会超出缓冲区边界并覆盖相邻的内存位置.缓冲区是留出的用于存储数据的内存区域,通常是在将数据从程序的一个部分移动到另一部分或在程序之 ...
最新文章
- 报告 | 从20世纪70年代至今,自动驾驶汽车的发展经历了哪些历史性的变革?
- 怎么使用oracle的加权平均数_GPA不足,怎么短期有效提升?快来收获100%录取的秘诀!...
- mysql1045_win10系统登录mysql时报错1045的解决方案
- 重磅 | 262亿收购LinkedIn,微软甘当接盘侠?
- Mongodb知识总结
- 查看模拟器使用端口_为什么我们仍然使用模拟音频端口?
- c++导出标准win32格式的dll
- 关于jacob 无法创建ActiveXCompnent对象的几种可能性
- 正运动控制器忘记地址怎么办?
- 逃离北上广:你以为回到小城市就非常幸福了吗?
- 基于ESP32测温湿度上传到OneNET并通过微信小程序控制,查看,下发指令
- 数学基础 - 第十八章 平行四边形
- 图像超分辨率论文笔记
- C语言指针(函数指针数组,二级指针)
- 打印Service运行时间与Aspect相关注解使用
- C# winfrom NPOI导出Excel 添加视频、音频文件
- CUDA out of memory怎么解决
- MySQL创建数据库、创建数据表
- 教你如何用手机下载视频号[微信小程序]中的视频
- linux apache ip配置,linux apache虚拟主机配置(基于ip,端口,域名)