原理介绍

格式化字符串函数可以接受可变数量的参数,并将第一个参数作为格式化字符串,根据其来解析之后的参数。

格式化字符串在利用时主要分为三个部分

  • 格式化字符串函数
  • 格式化字符串
  • 后续参数

常见的格式化字符串函数有:

  • scanf:输入
  • printf:输出到stdout
  • fprintf:输出到指定FILE流
  • vprintf:根据参数列表输出到指定FILE流
  • sprintf:输出到字符串
  • snprintf:输出指定字节数到字符串
  • vsnprintf:根据参数列表格式化输出指定字节到字符串
  • setproctitle:设置argv
  • syslog:输出日志

格式化字符串基本格式:

%[parameter][flags][field width][.precision][length]type
  • parameter:n$,获取格式化字符串中的指定参数
  • flag
  • field width:输出的最小宽度
  • precision:输出的最大长度
  • length:输出的长度,hh输出一个字节,h输出一个双字节
  • type:d/i有符号整数;u无符号整数;x/X16进制unsigned int;o8进制unsigned int;s,字符串;c,字符;p,void*,用地址格式输出对应变量的值;n,把已经成功输出的字符个数写入对应的整形指针参数所指的变量

漏洞原理

以printf为例,其不会检查格式化字符串中的占位符是否与所给的参数数目相等,而在printf输出的过程中,每遇到一个占位符,就会到约定好的位置获取数据并根据该占位符的类型解码并输出。因此适当修改就可以泄漏一些地址或一些其他东西,以及向目标地址写入数据。

使用fmtstr_payload(,{:})更方便