首页 > 其他 > 详细

简单栈溢出

时间:2021-06-01 00:39:16      阅读:16      评论:0      收藏:0      [点我收藏+]
  1. 声明:这篇文章从国外一篇博客翻译、修改而来。原文网址:https://dhavalkapil.com/blogs/Buffer-Overflow-Exploit
  2. 简易程序

    #include<stdio.h>
    void secretFunction(){
    printf("Congratulations!\n");
    printf("You have entered in the secret function!\n");
    }
    void echo()
    {
       char buffer[20];
       printf("Enter some text:\n");
       scanf("%s",buffer);
       printf("You entered:%s\n",buffer);
    }
    int main(){
       echo();
       return 0;
    }
  3. 进程运行时的内存

    high address command-line arguments and environment variables
      stack  
      heap  
      uninitalized data(bss) initialized to zero by exec
      initialized data read from program file by exec
    low address text read from program file by exec

    command-line arguments and environment variables:

    在程序运行前传递给程序,环境变量也在此处存储

    stack:

    存储函数的参数、返回地址和函数的局部变量,从高地址向低地址延伸。

    heap:所有动态分配的内存划分于此。任何时候使用malloc都会从heap分配。heap从低地址向高地址生长

    uninitialized data(BSS segment):

    所有未初始化的数据存放于此,包括没有初始化的全局变量和静态变量。

    内核默认将它们置为0.

    initialized data(Data segement)

    存放所有经过初始化的数据。

    text:

    存放可执行代码。loader指令从这里取出指令并运行。只读。

  4. 常用寄存器

    1. %eip: 指令指针寄存器,存放下一条指令的地址。每次执行完后根据指令的大小自增

    2. %esp:堆栈指针寄存器,存放栈顶指针。

    3. %ebp:基址指针寄存器。函数开始时与esp相等。

  5. 内存管理

    假设有以下程序:

    void func(int a,int b)
    {
    int c;
    int d;
    //some code
    }
    void main()
    {
    func(1,2);
    //next instruction
    }

    假设eip指向了main函数中的func调用,则接下来:

    1. 发现函数调用,从右向左将参数压入堆栈

    2. 需要知道完成后返回的地址。因此将下一条指令的地址压入堆栈。

    3. 找到要调用的参数的地址。将eip设为那个值。现在执行func函数。

    4. 我们现在在一个新函数中,因此要改变ebp的值。在改变之前,我们将它保存到栈中,这样返回时可以回到main函数

    5. 将ebp的值设为与esp相同。

    6. 将局部变量(不是参数)推入,改变栈顶指针esp的值

    7. func执行完后,要回到原来栈。首先使esp等于ebp;从栈中弹出之前保存的ebp的值,重新赋给ebp。现在基底指针指向了之前在main中指向的位置。

    8. 弹出返回地址,赋值给指令指针eip。于是控制流又到了main函数。

      执行func时栈的样子:

      局部变量desp
      局部变量c  
      ebp在main中指向的地址 ebp
      返回地址  
      1  
      2  
      1. 缓冲区溢出漏洞

      目的:访问分配给缓冲区内存之外的空间并进行读写

      通过修改返回地址控制程序运行

      以开头的程序为例:

      32位系统编译:

      gcc vuln.c -o vuln -fno-stack-protector

      64位系统编译

      gcc vuln.c -0 vuln -fno-stack-protector -m32

       

      (gcc安装32位编译libc文件:

      apt-get update

      apt-get purge libc6-dev

      apt-get install libc6-dev

      apt-get install libc6-dev-i386

      )

      对程序进行反汇编:

      objdump -d vuln

       

      技术分享图片

secret地址:000011b9

说明:

这里汇编语言格式为AT&T。特点:寄存器前要加%;立即数前要加$;目标操作数在源操作数数右边。

push ebp //保存ebp的值

mov esp,ebp //将esp赋给ebp

sub $0x24, %esp //esp减少24H,其中的空间属于局部变量

lea (load effective address),取有效地址。用法:把源操作数的地址偏移量传送目的操作数。只与地址有关!

lea -0x1c(%ebp) %eax // ebp前1cH字节

总之。。。现在缓冲区中共有28字节(1cH),正好位于ebp之前;之后的4字节就是ebp所指向的ebp在main中的值;再往后4字节时返回地址,即指令指针eip所要获得的地址。

构造payload:前28+4个字节随便填,后4个字节填secretFunction的地址。这里肯定是000011b9!

根据机器是大头位序还是小头位序填写。

这里是小头位序,所以是b9110000

。。。。。。

好吧这边没有关PIE,得到的地址都是错的。需要对文件进行重新编译。新增参数:

关闭PIE:

-no-pie

关闭NX:

-z noexecstack

关闭canary:

-fno-stack-protector

新的小头位序:82910408

再次尝试成功了。

技术分享图片

  1. 存在漏洞的C函数:

    gets,scanf,sprintf,strcpy

简单栈溢出

原文:https://www.cnblogs.com/Moon-on-Flat/p/14833547.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!