<返回更多

如何读懂栈溢出攻击,从这五点入手

2022-03-29    linux上的码农
加入收藏

什么是栈

 

如何读懂栈溢出攻击,从这五点入手

 

 

 

 

如何读懂栈溢出攻击,从这五点入手

 

 

 

如何读懂栈溢出攻击,从这五点入手

 

更多linux内核视频教程文档资料免费领取后台私信【内核】自行获取.

如何读懂栈溢出攻击,从这五点入手

 

Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂

栈帧

 

如何读懂栈溢出攻击,从这五点入手

 

 

  1. 调用者 需要知道在哪里获取 被调用者 返回的值(一般存放到 %eax 寄存器)。
  2. 被调用者 需要知道传入的参数在哪里和调用完后的返回地址在哪里。
  3. 我们需要保证在 被调用者 返回后,%ebp 和 %esp 寄存器的值应该和调用前一致。

函数调用

// stack.c

int add_func(int a, int b)
{
    int c, d;

    c = a;
    d = b;

    return c + d;
}

int main(int argc, char *argv[])
{
    int total;

    total = add_func(1, 2);

    return 0;
}

add_func:
    pushl   %ebp                // 保存ebp寄存器到栈
    movl    %esp, %ebp          // 把ebp进程设置为esp的值
    subl    $16, %esp           // 为局部变量申请空间
    movl    8(%ebp), %eax       // 把参数a保存到eax寄存器中
    movl    %eax, -8(%ebp)      // 把eax寄存器的值保存到局部变量c中(c = a)
    movl    12(%ebp), %eax      // 把参数b保存到eax寄存器中
    movl    %eax, -4(%ebp)      // 把eax寄存器到值保存到局部变量d中(d = b)
    movl    -8(%ebp), %edx      // 把d的值保存到edx寄存器中
    movl    -4(%ebp), %eax      // 把c的值保存到eax寄存器中
    addl    %edx, %eax          // 将eax寄存器与edx寄存器的值相加,保存到eax中(返回值)
    leave
    ret                         // 函数返回
    ...

 

如何读懂栈溢出攻击,从这五点入手

 

 

  1. 在 main() 函数调用 add_func() 函数前,先将调用 add_func() 函数的参数压栈。
  2. 在调用 add_func() 函数时,会将 返回地址 压栈,接着进入 add_func() 函数。
  3. add_func() 函数执行时,会将原来的 ebp寄存器 的值压栈,然后把 ebp寄存器 的设置为 esp寄存器 的值。
  4. 接着 add_func() 函数会为局部变量申请空间,也就是将 esp寄存器 向下移动。
  5. 然后把局部变量 c 设置为参数 a 的值,局部变量 d 设置为 参数 b 的值。
  6. 最后将局部变量 c 和 d 的值相加,放置到 eax寄存器 中(C语言规定以 eax寄存器 传递返回值),然后调用 ret 指令返回到 main() 函数。

函数返回

movl %ebp, %esp
popl %ebp

 

如何读懂栈溢出攻击,从这五点入手

 

 

栈溢出攻击

 

如何读懂栈溢出攻击,从这五点入手

 

 

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>

#define PTR_SIZE 8   // 指针的大小
#define EBP_SIZE 8   // ebp寄存器的大小

void inject_callback()
{
    printf("inject_callback called...n");
    exit(0);
}

void func_call(char *addr, int len)
{
    char tmpBuf[16] = {0xff};

    memcpy(tmpBuf + 16 + EBP_SIZE, addr, len);

    printf("func_call called...n");
}

int main(int argc, char** argv)
{
    uint64_t injectPtr = (uint64_t)&inject_callback;

    func_call(&injectPtr, PTR_SIZE);

    printf("main exited...n");

    return 0;
}

$ gcc stack-overflow.c -fno-stack-protector -o stack-overflow
$ ./stack-overflow
func_call called...
inject_callback called...

在编译上面程序时,一定要加上 -fno-stack-protector 参数,否则将会触发栈溢出保护,导致执行失败。

 

如何读懂栈溢出攻击,从这五点入手

 

 

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>