浅谈格式化字符串漏洞

<–more–>
开始接触漏洞利用了,这算是Chu师傅带我进Pwn的门阿 太黑客了。
这篇文章是我自己理解以及加以整理的,可能有偏误之类的欢迎大家指正。

#序
格式化字符串,是一个比较常见,简单的漏洞类型。我算是从这里开始入门CTF的pwn的。它看起来就简单,但是危害却不小。

#基础知识

##栈
在讲正文前先提一个简单的东西,为了更好了解漏洞先提一下栈。
栈内存在进程的作用如下:

  1. 暂时保存函数内的局部变量
  2. 调用函数时传递参数
  3. 保存函数返回后的地址
    栈其实是一种数据结构,它按照FILO(后进先出)的原则存储数据。
    ##栈的特征
    栈内存的结构一般如图


简单了解几个知识

  1. PUSH 入栈
  2. POP 出栈
  3. ESP 栈顶指针

    一个进程中,栈顶指针(ESP)初始状态指向栈顶端。执行PUSH命令将数据压入栈时,栈顶指针就会上移到栈顶端。执行POP命令从栈中弹出数据时,若栈是空的,则栈顶指针重新移动到栈低端。
    简单的讲,栈是一种由高地址向低地址扩展的数据结构。就像砌墙一样,向栈中压入数据的时候,数据就像砖墙,没砌上一层,墙就高一点。(PS:栈底是高地址,栈顶是低地址)

#漏洞简介
会触发格式化字符漏洞的函数有pirntfsprintffprintf,但不局于这些的c库中的printf家族函数。

##什么是格式化字符串
从是什么入手吧:
一个格式化字符串也就是一个ASCII字符串,其中包括了文本和格式参数。我们从简单的printf入手。

1
printf ("What is your name: %s","Summer")

这种样子的printf函数第一个参数就是简单的格式化字符串,作用是什么呢,作用是告诉一个程序如何进行格式化的输出的说明符号。简单的讲,他就是告诉机器,等等你要输出的内容是什么格式的,该怎么输出。
在C语言中我们有许多格式化字符的说明符号。

1
2
3
4
5
6
%d -十进制  输出的是整数型的十进制整数
%s - 字符串 输出的内容是字符串
%c - 字符 输出的内容是字符
%p - 指针 指针地址
%n - 输出的是字符的个数
......省略号

例如以上的不同的数据类型。而存在格式化字符串漏洞的函数就是上文提到的printf等等不局限于此的函数。
一般情况下我们使用printf这个函数的形式为

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
char a[100];
scanf("%s",a);
printf(“%s",a);
return 0;
}

但是如果程序员一偷懒就变成了

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
char a[100];
scanf("%s");
printf(a);
return 0;
}

这样问题就来了,也正是因为程序员对用户(黑客)的输入没有进行良好的过滤,限制,造成了这个漏洞的出现。因此千万不要将printf中的format字符串的操作权交给用户(黑客)。

直接拿一个题来做演示

题目地址:https://pan.baidu.com/s/1nuLAAgh