我一直在Windows XP Pro 64位下使用Visual Studio 2005进行C和C ++项目。我在调试器中不时使用的一个流行技巧是记住程序之前调试运行的数字指针值(比如0x00000000FFAB8938
),将其添加到监视窗口并进行适当的类型转换(比如说,((MyObject *) 0x00000000FFAB8938)->data_field
)然后在下一次调试运行期间观察对象占用的内存。在许多情况下,这是一个非常方便和有用的事情,因为只要代码保持不变,就可以预期分配的内存布局也将保持不变。简而言之,它有效。
然而,最近我开始在64位Windows Vista(家庭高级版)的笔记本电脑上使用相同版本的Visual Studio。奇怪的是,在该设置中使用这个技巧要困难得多。实际的存储器地址似乎经常在运行之间改变而没有明显的原因,即使程序的代码根本没有改变。看起来实际的地址并没有完全随机地改变,它只是从一组固定的或多或少的稳定值中选择一个值,但无论如何它使得这种类型的内存观察变得更加困难。
有没有人知道Windows Vista中此行为的原因?是什么导致内存布局的变化?是否有一些外部入侵进程的地址空间来自其他[系统]进程?或者是Vista下的Heap API实现的一些怪异/特征?有什么办法可以防止这种情况发生吗?
答案 0 :(得分:30)
Windows Vista实施address space layout randomization, heap randomization, and stack randomization。这是一种安全机制,试图防止依赖于每条代码和数据在内存中的位置的缓冲区溢出攻击。
可以通过设置MoveImages注册表值来关闭ASLR。我找不到禁用堆随机化的方法,但是一些微软人建议计算相对于_crtheap
的地址。即使堆移动,相对地址也可能保持稳定。