VS 用 CCCCCCCC 填充栈内存是设置软中断?

来源:互联网 发布:免费level2行情软件 编辑:程序博客网 时间:2024/06/06 07:32
在一些书里,或是论坛里,总会看到有作者把 CC 认定为是 x86 软中断(int 3)。但见作者除了发挥联想和照抄之外,似乎都不给出这个说法的确切依据。

这个说法明显很说不通。

微软使用如下常见的填充值:
ABABABAB
BAADF00D
CCCCCCCC
CDCDCDCD
DDDDDDDD
DEADDEAD
FDFDFDFD
FEEEFEEE

只看1个字节的话,这里唯独 CC 刚好与x86的某条特殊指令,即 int 3 指令的字节码相同。按此理解,填充 0xCCCCCCCC,相当于连续设置了4个断点。

问题是,这里设置断点有什么用处呢?栈内存默认是不可执行的,即便指令指针 EIP 不慎指向了栈内存,结果将是访问违规,根本用不上断点!

如果说是为了防范程序不慎先将栈内存设置为可执行的,再跳到栈内存执行,那么不妨先回答三个问题:
1,这还算是不慎吗?
2,为何不也用 0xCC 填充其它内存呢?
3,有听说谁真的经历过这种软中断吗?

另一方面,微软似乎从未声称这里的 CC 是软中断。

/GZ VC6的编译选项:用 0xCC 填充未显式初始化的局部变量的内存。
MSDN链接

这里也指出了不用 0x00 填充的理由。因为先判断指针是否等于 NULL 然后再用,在程序里是很常见的。用 0xCCCCCCCC 做为会引起访问违规的非 NULL 指针值,则更容易暴露程序里指针未初始化的问题。暴露问题恰恰是调试的目的。

但 CC 仍然特别。它的确就是软中断的字节码,只是,把填充和软中断在功能上联系起来,没有依据,难以说通。

VS2003起,/GZ被/RTC取代
MSDN链接

/RTC 编译选项的作用之一是,插入代码,使得在程序退出时,检查某些局部变量所在栈内存的前面4字节和后面4字节是否均为 0xCCCCCCCC(可能是填充时留下,一直未变的。也可能是被改写过多次但最终被赋以此值,看似没变过的),以此判断是否有越界。关闭这一选项,CC 填充就没有了。

这里的“某些”,是指编译器认为有必要检查的那些。具体不展开谈。

显然,这种栈帧检查的能力有限。但无论如何,栈帧检查的机理清楚明了,没有其它东西了。总之,没有依据把 CC 与软中断在功能上联系起来。






原创粉丝点击