格式化字符串:

发布于 2024-03-15  83 次阅读


了解:

首先了解一下什么是格式化字符串:

C语言里面有一个经常用于向屏幕输出字符的函数:printf。printf的第一个参数是字符串,被称为格式化字符串

我们在使用的时候经常使用如%d、%s、等占位符,然后printf就会依据这些占位符和其他参数整合出一个完整的字符串输出

其实书画字符串函数不仅仅是printf一个,还有以下几个 :

scnaf

fprintf

vprintf

vfprintf

sprintf......

漏洞的产生:

接下来就来看看漏洞是怎么产生的:

产生的原因主要是因为没有给printf提供变量printf ("........%d\n",a)   //正常的
printf ("........%d\n")   //错误的

那么如果不给变量的话printf还是能打印出数据,那么这个数据是哪里来的呢?

这就得讲到printf的原理了

printyf打印原理:

出现这种问题是因为printf不会检查格式化字符串的占位符是否与所给的参数数目相等。而在printf输出的过程里面,每遇到一个占位符就会到“约定好的位置”获取数据并跟据该占位符的类型解码输出。

那么约定好的位置在那个地方呢?

首先我们来看一下printf是怎么访问到实参的:

当printf访问实参的时候,按照C语言函数调用栈的规则,父函数会将实参倒序压入栈里面,并且第一个参数与子函数的return_address 相邻,因此printf知道第一个的实参为“.......%d\n”的地址,位于:ebp + 2 * sizeof(word);同理,第二个实参(此处第二个实参为整数 10)位于:ebp + 3 * sizeof(word)

再来看一下错误的情况:

在这里插入图片描述

因为没有提供参数a,所以父函数只把第一个参数压入栈,而它的上方就是其他的数据了,到那时printf还是认为 它的父函数会像以前一样把需要的参数压入栈,那么当它想访问第二个参数的时候就会认为 ebp + 3 * sizeof(word) 就是第二个参数,但实际上它是其他的数据

那么当我们传入%x的话,就会通过我们传入的N个%x就会泄露n*8个字节的内存数据,造成数据泄露:


The world's full of lonely people afraid to make the first move.