PWN学习之格式化字符串漏洞
PWN学习之格式化字符串漏洞
格式化输出函数
可变参数:https://blog.csdn.net/smstong/article/details/50751121 (C语言可变参函数的实现)
首先我们了解格式化字符串漏洞前,需要对格式化输出的函数进行一个了解,在C中格式化输出函数一共有如下:
fprintf() "按照格式字符串将输出写入流中。三个参数分别是流、格式字符串和变参列表。"
printf() "等同于fprintf(),但是它的输出流为stdout。"
sprintf() "等同于fprintf(),但是它的输出不是写入流而是写入数组。在写入的字符串末尾必须添加一个空字符。"
snprintf() "等同于sprintf(),但是它指定了可写入字符的最大值size。超过第size-1的部分会被舍弃,并且会在写入数组的字符串末尾添加一个空字符。"
dprintf() "等同于fprintf(),但是它的输出不是写入流而是一个文件描述符fd。"
"分别与上面的函数对应,但是它们将变参列表换成了va_list类型的参数。"
vfprint()、vprintf()、vsprintf()、vsnprintf()、vdprintf()
格式化字符串漏洞
格式化字符串漏洞从2000年左右开始流行起来,几乎在各种软件中都能见到它的身影,随着技术的发展,软件安全性的提升,如今它在桌面端已经比较少见了,但在物联网设备 IoT
上依然层出不穷。
#include <stdio.h>
void main()
{
printf("%s %d %s %x %x %x %3$s","Hello World!",233,"\n");
}
我们输入的参数只有三个,但是格式化字符串中还有3个%x和一个%3$s,其中3个%x由于没有参数他会泄漏出栈的地址
。
接下来继续来看一个例子,其中fgets来接受用户输入的字符串,但是如果是hack他就会输入控制字符串来泄漏出栈地址,这点感觉和Web中的xss有点像,程序员没有过滤敏感字符导致被攻击。由此可以总结出,格式字符串漏洞发生的条件就是格式字符串
要求的参数和实际提供
的参数不匹配
。
#include <stdio.h>
void main()
{
char buf[50];
if(fgets(buf,sizeof buf,stdin) == NULL)
return;
printf(buf);
}
漏洞利用
对于格式化字符串漏洞的利用主要有:
- 使程序崩溃
- 栈数据泄露
- 任意地址内存泄露
- 栈数据覆盖
- 任意地址内存覆盖
使程序崩溃
造成程序崩溃原因:printf需要在栈中取一个数字视为地址,然后打印出地址所指向的内存,知道出现空白字符;获取的某个数字可能并不是一个地址;获得的数组确实是一个地址,但改地址受保护。
在Linux中,存取无效的指针
会使进程收到SIGSEGV
信号。
printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")
栈数据泄露
#include <stdio.h>
void main()
{
char format[128];
int arg1 = 0x00123456,arg2 = 0x11111111,arg3 = 0x22222222;
char arg4[4] = "ABCD";
scanf("%s",format);
printf(format,arg1,arg2,arg3,arg4);
printf("\n");
}
输入 %p-%p-%p-%p-%p
可以根据泄漏出来的栈的数据,然后挨个的计算出参数的位置,因为栈中的数据一般都是挨着的,可以看到在0xffffd484的下个数据就是字符串ABCD
字符串的地址。
现在我们已经知道了如何按顺序泄露栈数据,那么如果想直接泄露指定的某个数据,则可以使用与下面类似的格式字符串,这里的n
表示位于格式字符串后的第n个数据
。%n$p
%<arg#>$<format>
%n$x
分别获取arg3、arg1、arg2、arg2、arg4 以及栈上经跟参数的两个值
"%3$x-%1$p-%2$p-%2$p-%4$p-%5$p-%6$p"
任意地址内存泄漏
攻击者使用类似%s
的格式规范就可以泄露出参数(指针)所指向内存的数据,程序会将它作为一个ASCII字符串处理,直到遇到一个空字符。所以,如果攻击者能够操纵这个参数的值,那么就可以泄露任意地址的内容。
AAAA-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p
AAAA代表地址
栈数据覆盖
#include <stdio.h>
void main()
{
int i;
char str[] = "hello";
printf("%s %n\n",str,&i);
printf("%d\n",i);
}
这个例子i被赋值成了6,因为遇到转换指示符之前一共写入了6个字符("hello"加上一个空格)。在没有长度修饰符时,默认写入一个int类型的值。有关详细内容可以参考:https://blog.csdn.net/FollowGodSteps/article/details/74115138
以下例子参考文章:c语言中对字段宽度的理解?
/*************************************************************************
> File Name: printf.c
> Author: Mr.Yang
> Purpose:演示printf的用法
> Created Time: 2017年05月21日 星期日 10时07分44秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
float i = 10000.123;
printf("%5f\n",i);
printf("%10f\n",i);
printf("%15f\n",i);
printf("%20f\n",i);
printf("%25f\n",i);
return 0;
}
输出内容:
10000.123047
10000.123047
10000.123047
10000.123047
10000.123047
回到一开始的程序,我们尝试将arg2的值更改为任意值(例如0x00000020,十进制32),于是构造格式字符串\x28\xcd\xff\xff%08x%08x%012d%13$n
,其中\x28\xcd\xff\xff
是arg2的地址,占4字节,“%08x%08x”表示两个8字符宽的十六进制数,占16字节,“%012d”占12字节,三个部分加起来共占4+16+12=32字节,也就是把arg2赋值为0x00000020。格式字符串最后一部分“%13$n”是最重要的一部分,表示格式字符串的第13个参数,即写入0xffffcd28的地方(0xffffcd58),printf()通过该地址找到被覆盖数据。
对比printf()执行前后的栈,可以看到其首先解析“%13$n”,从0xffffcd58找到地址0xffffcd28,然后将其数据覆盖为“0x00000020”。
任意地址内存覆盖
也许已经有人发现了问题,使用上面的方法,值最小只能是4,因为光地址就占去了4个字节,那么怎样覆盖比4小的值呢?利用整数溢出是一个方法,但是在实践中这样做很难成功。再想一下,前面的输入中,地址都位于格式字符串之前,这样做真的有必要吗,能否将地址放在中间呢?我们来试一下,使用格式字符串“AA%15\(nA"+"\x38\xd5\xff\xff”,开头的“AA”占2个字节,即将地址赋值为2,中间“%15\)n”占5个字节(这里不是%13$n,因为地址被放在了后面),是第15个参数,后面跟上一个“A”占用1个字节。于是前半部分总共占用2+5+1=8个字节,刚好是两个参数的宽度,这里的8字节对齐十分重要。最后,输入我们要覆盖的地址“\x38\xd5\xff\xff”,如下所示。
PWN学习之格式化字符串漏洞的更多相关文章
- [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇
目录 [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precisi ...
- Linux pwn入门教程——格式化字符串漏洞
本文作者:Tangerine@SAINTSEC 原文来自:https://bbs.ichunqiu.com/thread-42943-1-1.html 0×00 printf函数中的漏洞printf函 ...
- CTF必备技能丨Linux Pwn入门教程——格式化字符串漏洞
Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...
- 格式化字符串漏洞 format string exploit(一)
本文系原创,转载请说明出处 本文为基于CTF WIKI的PWN学习 0x00 格式化字符串原理 先附一张经典的图,如下 其栈上布局如下: some value 3.14 123456 addr of ...
- Linux pwn入门教程(6)——格式化字符串漏洞
作者:Tangerine@SAINTSEC 0x00 printf函数中的漏洞 printf函数族是一个在C编程中比较常用的函数族.通常来说,我们会使用printf([格式化字符串],参数)的形式来进 ...
- 格式化字符串漏洞利用实战之 0ctf-easyprintf
前言 这是 0ctf 的一道比较简单的格式化串的题目. 正文 逻辑非常简单 do_read 可以打印内存地址的数据,可用来 泄露 got. leave 格式化字符串漏洞. printf(s) 直接调用 ...
- 格式化字符串漏洞利用实战之 njctf-decoder
前言 格式化字符串漏洞也是一种比较常见的漏洞利用技术.ctf 中也经常出现. 本文以 njctf 线下赛的一道题为例进行实战. 题目链接:https://gitee.com/hac425/blog_d ...
- Linux下的格式化字符串漏洞利用姿势
linux最早的漏洞防护机制nx-stack刚刚出现后就有人想出了突破方法.那就是只有栈是不可执行,而除了栈以外的其他地方还是可以执行的,只要把返回地址执行别的地方就可以. 一.格式化字符串漏洞 格式 ...
- 通过格式化字符串漏洞绕过canary
1.1 canary内存保护机制 1.1.1 canary工作原理 canary保护机制类似于/GS保护机制,是Linux下gcc编译器的安全保护机制之一,在栈中的结构如下图所示: 在函数 ...
随机推荐
- PC端利用Xshell连接Android上的Termux
需要准备的工具 Android端:Termux.RE管理器 PC端:Xshell 开始操作 1. 启动Termux,安装openssh pkg install openssh 2. 安装好后,启动ss ...
- js判断移动端跳转
<script type="text/javascript">if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) | ...
- 更改已安装的织梦dedecms系统数据库表前缀
1 修改之前我们先备份下数据,备份的操作过程是:网站后台------系统------数据库备份/还原-------然后按提交.默认保存的数据在data/backupdata目录下. 2 修改目录下da ...
- html jquey的选择器checkbox,select
1 判断checkbox是否选中 用到 jquery的 is方法 jquery: <div id="divId" class="divTable"> ...
- Writing in the Science 01
INTRODUCTION What makes good writing? Good writing communicates an idea clearly and effectively. Goo ...
- WireShark新手使用教程
Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息.常用于开发测试过程各种问题定位.本文主要内容包括: 1.Wireshark软件下载和安装以及Wiresha ...
- Jmeter通过正则表达式提取器提取响应结果数据
Jmeter进行接口测试常常会运到一个问题:就是第二个请求如何接收上一个请求响应中的参数.比如,现在个学生金币充值的接口,得先调用登录接口然后从返回里面复制一下sign的值,放到cookie里这样才能 ...
- CF786C-Till I Collapse【树状数组倍增,优先队列】
正题 题目链接:https://www.luogu.com.cn/problem/CF786C 题目大意 给出一个长度为\(n\)的序列. 对于每个\(k\in[1,n]\)求将\(n\)分成最少的段 ...
- 深入浅出WPF-12.绘图与动画
绘图 1)Brush(画刷) SolidColorBrush实心画刷,直接使用颜色赋值 LinearGradientBrush线性渐变画刷,色彩沿设定的直线方向.按设定的变化点进行渐变 RadialG ...
- mybatis: No enum constant org.apache.ibatis.type.JdbcType."VARCHAR"
mybatis 插入的时候一句sql报错如下. org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ib ...