为什么太多数据无法覆盖指令指针?

问题描述

最近我在 opensecuritytraining 的漏洞利用类 1 中显示一个简单的 c 代码上尝试缓冲区溢出。这是代码

#include<stdio.h>
char *secret ="hello";
void go_shell()
{
        printf("This is go_shell\n");
}
int authorize()
{
        char password[64];
        printf("Enter the password: ");
        gets(password);
        if(!strcmp(password,secret))
        {
                return 1;
        }
        else
                return 0;
}
int main ()
{
        if (authorize())
        {
                printf("Login ok!\n");
                go_shell();
        }
        else
                printf("Incorrect\n");
}

在这个中,当我输入超过 72 个 'A' 然后它开始覆盖堆栈的 rip 部分。 This is the stack when i enter 73 'A'。其中 rip 保存在 0x7ffffffee308 并被覆盖。 This is the result on the overflow。但问题是当我输入超过 78 'A' This is the stack when i give 78 'A' as input。这是Successfully overwritten rip This is when 79 'A' are given as input。虽然堆栈被成功覆盖但 rip 指向正确的位置。为什么会这样? 我在 wsl 中使用 ubuntu。

解决方法

我可以重现观察结果。确实有两种行为案例:

  1. 损坏的返回地址被加载到 RIP 中,段错误发生在损坏的指令指针处。
  2. 在加载到 RIP 之前检测到损坏的返回地址,并且段错误发生在 retq 指令指针处。

我仍然需要深入研究处理器文档,但似乎错误返回地址的早期检测取决于它的“错误程度” - 当只有一些 LSB 错误时,返回被采用,而当只有一个 MSB 保持正确,不返回。