pwn入门之二:缓冲溢出

时间:2024-03-18 17:02:46

pwn入门二:缓冲溢出

 

 

环境:cenos6.5 64位,安装了 gcc的32位编译库,cenos运行于文本模式,搭建方法见博文《pwn入门之一:搭建64位centos6.5虚拟机 》。

 

一、建立 test1.c,内容如下:

#include <stdio.h>

main()

{

  char a='a';

  char b[10];

  gets(b);

  if (a=='a')

    printf("Try again.\n");

   else

    printf("You've pwned it.\n");

}

可以不必去理解这段代码的含义,只要无误的输入就可以了,理解了代码反而不利于理解PWN技术。

二、编译生成可执行文件test1

用以下命令

gcc -m32 -o test1 test1.c

可生成test1文件。

三、运行test1

用./test1命令运行之,程序要求键盘输入,输入一些字符后回车,可发现当输的内容的长度大于10,且第11个字符 不为‘a’时,提示成功信息,否则提示失败信息。

四、用gdb分析test1

运行gdb test1命令,出现(gdb)提示符,输入disas main命令,显示main函数的汇编代码,如下图所示:

pwn入门之二:缓冲溢出

代码中有两处出现[email protected],这是输出的语句,我们两来看看这两个语句前放入栈顶的是什么,

输入 x /s 0x80484f4 命令,显示“Try again.”如下图:

pwn入门之二:缓冲溢出

可知,如攻击不成功时会执行第11条语句 即

 movl $804841f4,(%esp)

输入 x /s 0x80484ff 命令,显示“You've pwned it.”如下图:

pwn入门之二:缓冲溢出

可知,如果攻击成功,一定会执行第14条语句即

movl $804841ff,(%esp)

再看第10条语句,当0x1f(%esp)不等于0x61时就会执行第14条语句。

但在第5条语句,已将0x61赋值给了0x1f(%esp)了。

再看第6、7,8条语句,将这个地址放入栈顶,然后再调用[email protected],这说明此时的输入的内容将被放入0x15(%esp)及以后的内存单元中,但0x15(%esp)刚好在0x1f(%esp)前面10个单元的位置上,所以当输入的字符数为10个时,0x1f(%esp)将为置为‘0x00’,0x1f(%esp)r的值就不等于0x61了,这时攻击就成功了,另外,当输入的字符数大于10个时,第11个字符就会覆盖0x1f(%esp),当这个字符不是‘a’时,0x1f(%esp)r的值也就不等于0x61了,这时攻击就成功了。

来验证一下。

我们在第7个语句后设置一个断点,然后运行程序,到达断点后逐条运行,观察用键盘输入一些字符后0x15(%esp)到0x1f(esp)的内存单元的值的变化。如下图:

pwn入门之二:缓冲溢出

如其中的标示,在输入10个a字符之前,$esp+0x15至$esp+0x1e的值分别为0x83,0x04,0x08,0x4b,0x84,0x04,0x08,0xf4,0x0f,0x7a,而$esp+0x1f的值为0x61.

输入10个a字符之后,$esp+0x15至$esp+0x1e的值均为0x61,而$esp+0x1f的值变为了0x00,

依上法,我们重新做一次实验,这次我们输入10个a和1个b,情况如下:

pwn入门之二:缓冲溢出

这次我们发现$esp+0x1f的值变为了0x62,再而$esp+0x20的值则变成为0x00.

这就验证了我们的想法,由此设计攻击的方法,如下:

pwn入门之二:缓冲溢出

但当输入的第10个字为a时,失败,如下图:

pwn入门之二:缓冲溢出

 

以上就是一种缓冲溢出攻击的过程,攻击的原理读者可自行揣摩,涉及的命令的用法和意见请读者百度,此处不再详述。