修复缓冲区溢出问题
2009-03-07 20:02:33 来源:WEB开发网下面我们来看一个示例。
以下代码有什么错误?
void CopyData(char *szData) {
char cDest[32];
strcpy(cDest,szData);
// 使用 cDest
...
}
令人惊讶的是,这段代码可能没有什么错误!这完全取决于 CopyData() 的调用方式。例如,以下代码是安全的:
char *szNames[] = {"Michael","Cheryl","Blake"};
CopyData(szName[1]);
这段代码是安全的,因为名字是硬编码的,并且知道每个字符串在长度上不超过 32 个字符,因此调用 strcpy 永远是安全的。然而,如果 CopyData 和 szData 的唯一参数来自不可靠的源(如套接字或文件),则 strcpy 将复制该数据,直到碰到空字符为止;如果此数据的长度大于 32 个字符,则 cDest 缓冲区将溢出,并且在内存中该缓冲区以外的任何数据将遭到破坏。不幸的是,在这里,遭到破坏的数据是来自 CopyData 的返回地址,这意味着当 CopyData 完成时,它仍然在由攻击者指定的位置继续执行。这真糟糕!
其他数据结构也同样敏感。假设某个 C++ 类的 V 表遭到破坏,如下面这段代码:
void CopyData(char *szData) {
char cDest[32];
CFoo foo;
strcpy(cDest,szData);
foo.Init();
}
此示例假定 CFoo 类具有虚方法,以及一个 V 表或该类方法的地址列表(与所有 C++ 类一样)。如果由于 cDest 缓冲区被覆盖而破坏了 V 表,则该类的任何虚方法(在此例中是 Init() )都可能调用攻击者指定的地址,而不是 Init() 的地址。顺便说一句,如果认为您的代码不调用任何 C++ 方法就安全了,那就错了,因为有一个方法始终会被调用,即该类的虚析构函数!当然,如果某个类不调用任何方法,就应该想想它存在的必要了。
更多精彩
赞助商链接