格式化字符串漏洞


格式化字符串漏洞

格式化字符串漏洞是PWN题常见的考察点,仅次于栈溢出漏洞。漏洞原因:程序使用了格式化字符串作为参数,并且格式化字符串为用户可控。其中触发格式化字符串漏洞函数主要是printfsprintffprintfprin等C库中print家族的函数

0x01 格式化字符串介绍

printf("格式化字符串",参数...)

printf函数的第一个参数是由格式化说明符与字符串组成,用来规定参数用什么格式输出内容。

格式化说明符:

%d - 十进制 - 输出十进制整数
%s - 字符串 - 从内存中读取字符串
%x - 十六进制 - 输出十六进制数
%c - 字符 - 输出字符
%p - 指针 - 指针地址
%n - 到目前为止所写的字符数

例如:

#include <stdio.h>
int main(void){
    printf("My name is %s","Ezreal");
    return 0;
}

调用以后会显示:

My name is Ezreal

特别要注意的是%n这个格式化字符串,它的功能是将%n之前打印出来的字符个数,赋值给一个变量。例如:

#include <stdio.h>

int main(void)
{
    int c = 0; 
    printf("the use of %n", &c);sss
    printf("%d\n", c);
    return 0;
}

调用以后会显示:

the use of 11

0x02 漏洞形成原因

1、函数用法:

正常的printf用法:

#include <stdio.h>
int main()
{
  char str[100];
  scanf("%s",str);
  printf("%s",str);
  return 0;
}

写程序时要规定字符串的格式化说明符,规定参数的输出类型

错误的printf写法:

#include <stdio.h>
int main()
{
  char str[100];
  scanf("%s",str);
  printf(str);
  return 0;
}

漏洞形成原因:程序将格式化字符串的输入权交给用户,printf函数并不知道参数个数,它的内部有个指针,用来索检格式化字符串。对于特定类型%,就去取相应参数的值,直到索检到格式化字符串结束。所以没有参数,代码也会将format string 后面的内存当做参数以16进制输出。这样就会造成内存泄露。示例程序:

#include <stdio.h>

int main(void)
{
    char a[100];
    scanf("%s",a);
    printf(a);
    return 0;
}

假设我们的输入为:

AAAA%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x

程序的输出为:

AAAA61fe4c,61ffcc,76e4d250,70734fbf,fffffffe,76e473da,41414141,252c7825,78252c78,2c78252c,252c7825

成功打印出地址

0x03 漏洞利用

对于格式化字符串漏洞的主要利用有:使程序崩溃、栈数据泄露、任意地址内存泄露、栈数据覆盖、任意地址内存覆盖。


文章作者: Pr0b1em
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Pr0b1em !
  目录