
上QQ阅读APP看书,第一时间看更新
3.2 函数指针
虽然栈溢出(连同很多基于堆的攻击)不可能发生于数据段(data segment)中,但是覆写函数指针在任何内存段中都会发生。
例3.2包含了一个有漏洞的程序,其BSS段中的一个函数指针可以被覆写。第3行声明的静态字符数组buff和第4行声明的静态函数指针funcPtr都是未初始化的,并且存储于BSS段中。第6行对strncpy()的调用是对有界字符串复制函数的非安全调用的演示。当argv[1]的长度大于BUFFSIZE的时候,就会发生缓冲区溢出。这个缓冲区溢出漏洞可以被利用来将函数指针值覆写为外壳代码的地址,从而将程序的控制权转移到任意的代码。当程序执行到第7行、执行由funcPtr标识的函数时,外壳代码将会取代good_function()得以执行。
例3.2 BSS段中导致缓冲区溢出的程序漏洞
1 void good_function(const char *str) {...} 2 int main(int argc, char *argv[]) { 3 static char buff[BUFFSIZE]; 4 static void (*funcPtr)(const char *str); 5 funcPtr = &good_function; 6 strncpy(buff, argv[1], strlen(argv[1])); 7 (void)(*funcPtr)(argv[2]); 8 }
有一个朴素的缓冲区溢出缓解策略是将栈缓冲区重新声明为全局静态变量或局部静态变量,以降低栈溢出攻击的可能性。然而,将缓冲区重新声明为全局变量并不是一个完备的解决方案,因为我们已经看到,数据段内同样可能出现可利用的缓冲区溢出漏洞。