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)....