- 论坛徽章:
- 0
|
在阅读本节之前,建议先阅读系列文章 堆和栈,关于函数调用栈那部分内容,并确保正确理解了。看下面的程序
//
// overflow.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <stdlib.h>
void attacker()
{
printf("Attacker is running.\n"
exit(0);
}
void leak_func(char *str)
{
char local[4];
int i;
for (i = 0; str[i] !=0; i++)
{
local[i] = str[i];
}
}
int attack_data[10];
int main(int argc, char* argv[])
{
attack_data[0] = 0x41424344;
attack_data[1] = 0x41424344;
attack_data[2] = (int)attacker;
leak_func((char *)attack_data);
return 0;
}
稍微学过几天C的人都知道,leak_func 的 local 变量溢出了,通常情况下,这个溢出会导致程序崩溃。但是举这个例子很明显,猜也能猜到程序会执行 attacker 这个函数。
我们常说,程序攻击者会传给有漏洞的程序一个 “精心计算的”字节流,来达到非法获取控制权的目的。
在这个例子中 leak_func 中的局部变量过小,而且未检查攻击字符串的长度遍进行拷贝。这就是多所谓的“漏洞”。
那么因为变量 local 是从栈上分配的,而同时栈上同时有 该函数的返回地址,也就是 main 函数调用 leak_func 的下一条汇编指令的地址。但是溢出导致这个地址被恰好被 attacker 的地址覆盖了,所以 leak_func 执行到 ret 指令的时候,并未返回到调用者,而是走差道了,去了 attacker。
这就是所谓的“精细计算”的字节流。
实际进行攻击的时候,还会涉及到其它技术以及“更精心的计算”,但是本节就到这里了,毕竟这是是告诉大家如何不要写出有漏洞的程序,而不是黑客攻防演练。
另外手头没有编译器,不同的编译器会造成不同的结果,大家需要根据自己的编译器重新精心计算一下。 |
|