buffer overflows如何用于利用计算机?
我知道程序存储器的某些部分被覆盖了,但是我不知道这会导致一个人执行自己的代码。此外,第三方的恶意代码必须用目标处理器汇编语言编写吗?
答案 0 :(得分:16)
这是有关该主题的最广为人知的文件:Smashing the Stack for Fun and Profit
但是,“堆栈溢出”与缓冲区溢出无关。堆栈溢出通常只是坏代码中的错误情况,不能用于崩溃之外的任何事情(DoS)。
编辑:您还询问了堆溢出问题。这是一个关于这个主题的好文件:http://www.w00w00.org/files/articles/heaptut.txt
答案 1 :(得分:8)
当您跳转到子例程时,堆栈包含数据和返回地址。如果您设法将特定地址放在返回地址所在的堆栈上,则可以强制CPU跳转到特定的内存位置,即您自己的代码所在的位置。这是缓冲区溢出。堆溢出有点不同,更难以利用。
堆栈溢出只是表明你的堆栈空间不足(通常更有限,特别是在内核中)。
答案 2 :(得分:7)
想象一下街上有两栋房子。一个是你朋友的房子,一个是他邪恶的偏执邻居的房子三个门。邪恶的偏执邻居永远不会进入或离开,他的地方被锁紧。
现在,你的朋友是一个如此善于信任的朋友,他会让你在他的位置存放任何东西,一个接一个地放下盒子,从一面墙开始。事实上,他是一个很好的朋友,他会一个接一个地放下盒子,没有检查他是否撞到了墙上,直到他们继续在半空中,最后穿过街道上的另外两个房子进入邪恶的偏执邻居的房子。但是你的朋友相信你不会这样做,因为他喜欢你(而且他有点幼稚)。
所以你有机会利用你这位善良信任的朋友,把一些东西放进邪恶的偏执邻居家里。
替换以下术语,您将看到缓冲区溢出攻击的类比:
只有当有人知道内存的安全区域在哪里,并且必须作为参数传递给所讨论的程序时才会成功,这将最终进入安全区域,以获得所需的效果。 (无论是数据还是导致执行者代码执行的代码)
答案 3 :(得分:5)
几乎所有现代处理器在调用子程序时,都会将返回地址推送到与本地数据(堆栈)相同的区域。对于不检查变量上限的例程(特别是strcpy函数),可能会发生指令地址重定向(缓冲区溢出)。
void make(char *me)
{
char sandwich[4]; // local data, this is in stack. the buffer for data is too small
strcpy(sandwich, me);
puts(sandwich);
// implicit "return;" the return instruction(RET on Intel) instructs the processor to implicitly pop an address from stack then resume execution on that address
}
void main()
{
// calling a subroutine (CALL on Intel) implicitly instructs the processor to push the next instruction's address(getchar line) on stack before jumping to make.
make("Love Not War");
getchar();
puts("This will not execute. The address to next instruction(getchar) gets overwritten with Not War");
}
“此外,第三方的恶意代码必须用目标处理器汇编语言编写吗?”的是
堆栈溢出可能发生在正常运行的程序中,例如递归例程(调用自身的函数),具有忽略的终止条件。堆栈区域将填充堆栈上的大量局部变量以及返回的地址。
答案 4 :(得分:1)
通常的做法是在内存中存在恶意代码。然后你创建一个缓冲区溢出:这里的魔法不是让它只是溢出,而是正如你已经提到的那样,程序存储器的某些部分会被覆盖。由于堆栈不仅包含变量,而且当函数被称为返回地址时,会尝试使用恶意代码的地址覆盖此变量。当具有缓冲区溢出的函数返回其调用者时,该函数不会返回其原始调用者,而是返回恶意子例程。由于现在执行的代码通常具有调用代码的特权,因此尝试在代码中查找/创建此溢出,该代码具有比恶意代码更高的权限(否则您可以通过直接调用邪恶例程来执行此操作)。