缓冲区溢出如何用于利用计算机?
如何通过简单地导致堆栈或堆溢出来执行任意代码?
我理解程序存储器的某些部分是被覆盖的,但是我不知道这会导致一个人执行自己的代码.此外,第三方的恶意代码必须用目标处理器汇编语言编写吗?
这是关于这个主题的最广为人知的文件:粉碎堆栈的乐趣和利润
但是,"堆栈溢出"与缓冲区溢出无关.堆栈溢出通常只是坏代码中的错误情况,不能用于崩溃之外的任何事情(DoS).
编辑:您还询问了堆溢出.这是一个关于这个主题的好文件:http://www.w00w00.org/files/articles/heaptut.txt
跳转到子程序时,堆栈包含数据和返回地址.如果您设法将特定地址放在返回地址所在的堆栈上,则可以强制CPU跳转到特定的内存位置,即您自己的代码所在的位置.这是缓冲区溢出.堆溢出有点不同,更难以利用.
堆栈溢出只是表明你已经耗尽了堆栈空间(通常更有限,特别是在内核中).
想象一下街上的两栋房子.一个是你朋友的房子,一个是他邪恶的偏执邻居的房子三个门.邪恶的偏执邻居永远不会进入或离开,他的地方被锁紧.
现在,你的朋友是一个如此善于信任的朋友,他会让你在他的位置存放任何东西,一个接一个地放下盒子,从一面墙开始.事实上,他是一个很好的朋友,他会一个接一个地放下盒子,没有检查他是否撞到了墙上,直到他们继续在半空中行进,最后穿过街道上的另外两个房子进入邪恶的偏执邻居的房子.但是你的朋友相信你不会这样做,因为他喜欢你(而且他有点幼稚).
因此,你有机会通过利用你信任的好朋友把一些东西放进邪恶的偏执邻居的家里.
替换以下术语,您将看到类似于缓冲区溢出攻击:
"你朋友的家" - >"不检查缓冲区溢出的程序的一部分"
"他邪恶的偏执邻居的房子" - >"一个应该是安全的程序的另一部分"
"boxes" - >"程序的参数/参数,不检查缓冲区溢出"
只有当有人弄清楚内存的安全区域在哪里,并且必须作为参数传递给所讨论的程序时才会成功,这将最终进入安全区域,以获得所需的效果.(无论是数据,还是导致执行者代码执行的代码)
几乎所有现代处理器在调用子程序时,都会将返回地址推送到与本地数据(堆栈)相同的区域.对于不检查变量上限的例程(特别是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"); }
"此外,第三方的恶意代码必须用目标处理器汇编语言编写吗?" 是
堆栈溢出可能发生在正常运行的程序中,例如递归例程(调用自身的函数),具有忽略的终止条件.堆栈区域将填充堆栈上的大量局部变量以及返回的地址.