栈溢出漏洞利用原理

栈溢出漏洞利用原理

2013-12-26 21:21 3686

下面的代码引自《shellcoder's handbook》英文版,中文版中没有这一节,可能是漏译,也可能是有意为之。下面的过程是经过本人调试并测试通过的,请不要套用,因为不同的平台,其结果可能也是不同的,至少我调试得到的字节数跟书中作者调试得到的字节数是有出入的,但是思路是相同的。
用例代码
overflow.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
int valid_serial(char *psz)
{
  size_t len=strlen(psz);
  unsigned int total=0;
  size_t i;
  if(len<10)
    return 0;
  for(i=0;i<len;i++)
  {
    if((psz[i]<'0')||(psz[i]>'z'))
      return 0;
    total+=psz[i];
  }
  if(total%853==83)
    return 1;
  return 0;
}
int validate_serial()
{
  char serial[24];
  fscanf(stdin,"%s",serial);
  if(valid_serial(serial))
    return 1;
  else
    return 0;
}
int do_invalid_stuff()
{
  printf("Invalid serial number!\nExiting\n");
  exit(1);
}
int do_valid_stuff()
{
  printf("The serial number is valid!\n");
  exit(0);
}
int main(int argc,char *argv[])
{
  if(validate_serial())
    do_valid_stuff();
  else
    do_invalid_stuff();
  return 0;
}

编译:gcc  -g  overflow.c  -o  overflow
首先使用GDB调试overflow,在主函数处设置断点,如图1

图1
运行程序至断点处,反汇编EIP所指地址处的代码,如图2

图2
从上图,可以看到,do_valid_stuff的函数调用地址为0x08048629,记下这个地址,稍后我们会用到这个地址,改变程序的执行流程。同时,记下call指令的下一条指令的地址,也就是0x08048625,这个值将会在后面遇到。此时,查看一下eax,ebx,ecx,edx,ebp,esp寄存器的内容,如图3

图3
从上图中我们可以看到此时寄存器esp的值是0xbffff3d0,因此在调用validate_serial函数之前,我们看看栈中的内容,如图4

图4
从图中可以看到在调用函数之前,寄存器esp所指的值为0x08048650.
现在来看看validate_serial函数的反汇编结果,如图5

图5
当我们进入函数时,反汇编一下,看看我们的程序运行到何处,如图6

图6
从上图中我们可以看出,目前已经进入到validate_serial函数内,但是该函数的第一条指令还没有执行。此时,我们来看看栈中的情况,如图7

图7
注意看0xbffff3cc地址处的值,其值是0x08048625,这个值是不是有点儿眼熟,看看我们的图1,它是不是call指令的下一个指令的地址,我们要覆盖的值就是它。在图中我们还看到了地址为0xbffff3d0的值是0x08048650,这个值是不是也很眼熟。从这条信息中,我们可以得到一个信息,在进行函数调用时,call指令会将该指令的下一条指令的地址放入到栈中,之后给函数分配栈大小。
当我们多执行几条指令时,如图8

图8
此时,从代码中我们可以看到,系统给该函数分配了0x38个字节,分析一下代码你会发现 -0x20(%ebp)的地址其实就是我们的fscanf将获取到的字符串存储到栈中的地址,我们要覆盖的就是从该处到返回地址之间(包括返回地址)的字节数,也就是0x20+0x4+0x4,第一个4是push  %ebp指令占用的4字节,第二个4就是我们要改写的地址字节数,其值我们改写为do_validate_stuff的地址,也就是0x08048629.因此,因此我们构造的字符串如下:
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDD\x29\x86\x04\x08
当我们执行如下命令时,它就会跳到我们指定的调用地址处,这样我们就可以如愿以偿地改变了程序的执行流程.
printf  “AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDD\x29\x86\x04\x08”|./overflow
如图所示:

图9
当我们输入13个H时,其结果也是如此,如图所示:

图10
有不对之处,还请不吝赐教!

《0day安全 软件漏洞分析技术(第二版)》第三次再版印刷预售开始!

posted @ 2020-10-02 00:04  bonelee  阅读(507)  评论(0编辑  收藏  举报