问题描述
最近我在 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。
解决方法
我可以重现观察结果。确实有两种行为案例:
- 损坏的返回地址被加载到 RIP 中,段错误发生在损坏的指令指针处。
- 在加载到 RIP 之前检测到损坏的返回地址,并且段错误发生在
retq
指令指针处。
我仍然需要深入研究处理器文档,但似乎错误返回地址的早期检测取决于它的“错误程度” - 当只有一些 LSB 错误时,返回被采用,而当只有一个 MSB 保持正确,不返回。