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编译器的安全保护机制之一,在栈中的结构如下图所示: 在函数 ...
随机推荐
- Android——菜单(Menu)
菜单的运用在Android中很常见,今天就两节体育课,闲下来也想认真的学一学,正好项目中也会有应用.我是跟着菜鸟教程进行学习的,我相应的粘了一些我自己认为比较重要的,以供方便记录学习. 本章给大家带来 ...
- ecshop调用商品原图的方法
一.在列表页可以用{$goods.goods_thumb} {$goods.goods_img}调用缩略图和商品图片 就是没有调用原图的下面是修改category.php 总sql语句处替换成下面 ...
- ecshop调用指定栏目下的文章的方法
打开 index.php 添加 fun函数一个,需放在<php与?>中间. /** * 获得指定栏目的文章列表. * @param int $cid 栏目ID * @param int $ ...
- Jmeter系列(18)- 八大组件
说明 取样器(Sampler):不与其他元件发⽣交互的作⽤的元件 逻辑控制器(Logic Controller):只对其⼦节点的sampler有效,⽽其他元件需要与sampler等元件交互 前置处理器 ...
- modern php closure 闭包
* 在array_map()函数中使用闭包 <?php $numbersPlusOne = array_map(function($number) { return $number + 1; } ...
- python并发与futures模块
非并发程序(用于对比) 从网上下载20个国家的国旗图像: import os import time import sys import requests # 导入requests库 POP20_CC ...
- 整理常用的 vim 命令
vim 是一款功能强大的文本编辑器,它是Linux下常用的编辑器之一,对于熟练掌握了 vim 的人来说,用它编辑文件,方便又快捷,能极大的提高工作效率 vim 功能强大,对应的命令也非常的多,对于初学 ...
- P5325-[模板]Min_25筛
正题 题目链接:https://www.luogu.com.cn/problem/P5325 题目大意 定义一个积性函数满足\(f(p^k)=p^k(p^k-1)\) 求\(\sum_{i=1}^nf ...
- Python3入门系列之-----range和xrange的区别详解,你明白了吗?
前言 range()是Python的内置函数,用于创建整数的列表,可以生成递增或者递减的数列. xrange也有相同的功能, 今天来看下它们之间的不同. range 函数说明:range([start ...
- Spring,AOP实现功能级别权限验证
1. 首先是问题出现的原因 对于一个我的一个个人博客网站,我希望游客可以浏览我的博客,但是评论功能是需要登录才能使用 这就需要对某个功能进行权限验证 对于过滤器,拦截器,AOP的区别日后再讨论,现在是 ...