Security 需要一些关于转炉的高级解释吗

Security 需要一些关于转炉的高级解释吗,security,buffer-overflow,Security,Buffer Overflow,因此,我使用以下代码跟踪了一个关于缓冲区溢出的消息: #include <stdlib.h> #include <unistd.h> #include <stdio.h> int main(int argc, char **argv) { volatile int modified; char buffer[64]; modified = 0; gets(buffer); if(modified != 0) { printf

因此,我使用以下代码跟踪了一个关于缓冲区溢出的消息:

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

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

 modified = 0;
  gets(buffer);

  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");
  } else {
      printf("Try again?\n");
  }
}
-g允许在gdb('list main')中进行调试
-z execstack-fno堆栈保护器用于移除堆栈保护

然后执行它:

python -c 'print "A"*76' | ./protostar
再试一次

python -c 'print "A"*77' | ./protostar
您已更改“已修改”变量


所以我不明白为什么缓冲区溢出发生在77,而它本应该是65,所以它产生了12位的差异(3字节)。我想知道为什么有人有一个明确的解释

从77岁到87岁,情况依然如此:

python -c 'print "A"*87' | ./protostar
you have changed the 'modified' variable
从88开始,它添加了一个segfault:

python -c 'print "A"*88' | ./protostar
you have changed the 'modified' variable
Segmentation fault (core dumped)

关于

要完全理解正在发生的事情,首先要注意程序是如何布置内存的

从您的评论中可以看出,对于这个特定的运行,
buffer
的内存从
0x7fffffdf10
开始,然后
modified
0x7fffffffdf5c
开始(虽然
随机化空间
可能会在运行期间保持一致,但我不太确定)

所以你有这样的东西:

0x7fffffffdf10            0x7fffffffdf50      0x7fffffffdf5c
↓                         ↓                   ↓
(64 byte buffer)..........(some 12 bytes).....(modified)....
基本上,您有64个字符的缓冲区,当缓冲区结束时,有12个字节用于其他堆栈变量(可能有4个字节
argc
,8个字节用于
argv
),然后进行修改,在缓冲区启动后精确地开始64+12=76字节

因此,当您在64字节缓冲区中写入65到76个字符时,它会经过并开始写入缓冲区和
修改的
之间的12个字节。当您开始写入第77个字符时,它开始覆盖
modified
中的内容,这会导致您看到“
您已更改'modified'变量”
”消息

您还问“如果我升到87,然后在88出现segfault,为什么它会工作?答案是,因为它是未定义的行为,一旦您开始写入无效内存,内核识别出它,它就会立即终止您的进程,因为您正在尝试读取/写入您无权访问的内存


请注意,在实践中几乎不应该使用
get
,这是一个很大的原因,因为您不知道要读取多少字节,所以有可能会被覆盖。还要注意,您看到的行为与我运行计算机时在我的计算机上看到的行为不同。这是正常的,因为它是未定义的未定义的行为。无法保证运行时会发生什么。在我的机器上,
modified
实际上位于内存中的
buffer
之前,因此我从未看到
modified
变量被覆盖。我认为这是一个很好的学习示例,可以理解为什么这样的未定义行为如此不可预测。

“所以我不明白为什么77会发生缓冲区溢出,而它应该是65”-值的实际变化不需要发生在n+1字节(容量=n)。这只是可能的。它是来自内存对齐吗?很可能。这是未定义的行为,但出于学习目的,最好了解实际发生的情况。在
char buffer[64];
行之后添加以下内容:
printf(“修改的:%p\n”,&Modified);printf(“缓冲区:%p\n”,buffer)
,重新运行并查看输出结果。从那里我们可以准确地知道发生了什么。
修改:0x7fffffffdf5c
缓冲区:0x7fffffffdf10
如果我将其减为76ah!我将发布一个解释发生了什么的答案。谢谢!您使用的是哪个版本的gcc?我使用的是7.3.0 gcc--version@AntoninGAVREL你不客气!我使用的是7.4.0,但这可能不是因为版本不同。因为C规范对这些变量在内存中的排列方式没有规定要求,即使使用不同的计算机也会导致类似的小差异。这就是为什么未定义的行为通常很难解释的原因。您总是希望运行你的代码有一个漏洞检查器,比如valgrind,它通常会捕获这些类型的问题,然后你可以修复它们。
0x7fffffffdf10            0x7fffffffdf50      0x7fffffffdf5c
↓                         ↓                   ↓
(64 byte buffer)..........(some 12 bytes).....(modified)....