格式化字符串漏洞

前提知识储备:

概念

格式化字符串函数可以接受可变数量的参数,并将第一个参数作为格式化字符串,根据其来解析之后的参数。一般来说,格式化字符串在利用的时候主要分为三个部分

  • 格式化字符串函数
  • 格式化字符串
  • 后续参数,就是下图中逗号后的变量(可以不要)

上述可转为该图:

将相关正式概念代入图片更好理解

相关函数

输入:

  • scanf

输出函数

函数 基本介绍
printf 输出到stdout
fprintf 输出到指定FILE流
vprintf 根据参数列表格式化输出到 stdout
vfprintf 根据参数列表格式化输出到指定FILE流
sprintf 输出到字符串
snprintf 输出指定字节数到字符串
vsprintf 根据参数列表格式化输出到字符串
vsnprintf 根据参数列表格式化输出指定字节到字符串
setproctitle 设置argv
syslog 输出日志
err, verr, warn, vwarn等 。。。
  • printf函数的字符串漏洞

    此漏洞如(来自攻防世界的CGfsb):

在格式化字符串函数中%n,作用是把在%n前输出的字符个数赋值给对应的整型指针参数所指的变量

%hh的作用是限定输出格式为8位,即一个字节;

%h的作用是限定输出格式为16位,即两个字节;

%l的作用是限定输出格式为32位,即四个字节;

%ll的作用是限定输出格式为64位,即八个字节;

%L的作用是输出实数,支持long double类型;

  • sprintf原型int sprintf(char *string, char *format [,argument,…])

    • string– 这是指向一个字符数组的指针,该数组存储了 C 字符串。

    • format– 这是字符串,包含了要被写入到字符串 str 的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。format 标签属性是**%[flags] (width)[.precision] (length)specifier**

    • **[argument]…**:根据不同的 format 字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了 format 参数中指定的每个 % 标签。参数的个数应与 % 标签的个数相同。

把格式化的数据写入某个字符串缓冲区。如果成功,则返回写入的字符总数(不包括’\0’),不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。

原理

x86系统下:

以printf为例

假设printf函数将以图中方式进行输出。那么作为一个函数,首先就是将参数入栈,又按照从右到左的方式。那么将按以下的情况入栈:

1
2
3
4
3.14
123456
addr of "red"
addr of format string: Color %s,Number %d,Float %4.2f

执行printf函数后,函数会获取第一个参数,也就是格式化字符串。函数将会一个个的读取字符串中的字符,有以下情况:

  • 当前字符不是%,直接输出到相应标准输出。
  • 当前字符是%, 继续读取下一个字符
    • 如果没有字符,报错
    • 如果下一个字符是%,输出%;否则根据相应字符对应的数据类型,获取相应的参数,将其输出

那么漏洞将会发生在哪呢?

假设我们将程序写成这样

1
printf("Color %s, Number %d, Float %4.2f");

我们并没有提供printf函数中%后对应的参数,此时程序并不会报错停止,而是继续执行,会在栈中存储着格式化字符串地址上面的三个高地址变量解析,作为输出:

  • %s则解析其地址对应的字符串

  • %d解析内容对应的整型值

  • %f解析内容对应的浮点值

    第一个,注意!解析地址!如果是一个无法访问的地址比如0,那么程序将崩溃,这也是我们利用的点,比如注入不限量个%s,总有一个能让程序崩溃的。而其余两个我们也可以借此而使得栈上的内容泄露出来

    这里补充一点:我们是可以获取栈中被视为第n+1个参数的值方法为:

    1
    %n$p

    n代表该格式化字符串对应的第n个输出参数,那相对于输出函数来说,就是第n+1个参数了。

    x64系统下:

    原理与x86并无不同,唯一需要注意的就是x64系统下,函数的前六位参数是使用寄存器存放的,顺序为RDI,RSI,RDX,RCX,R8,R9对应前六位参数,所以在gdb中相对偏移时,要把栈上的偏移加上相差寄存器的数量的才是n的值

参考:

ctf-wiki格式化字符串漏洞

查看评论