c++ - 是否可以保护内存区域免受 WinAPI 的影响?

标签 c++ winapi memory-management heap-corruption

已阅读this interesting article在概述调试堆损坏的技术时,我开始想知道如何根据自己的需要调整它。基本思想是提供一个自定义的 malloc() 来分配整页内存,然后为这些页面启用一些内存保护位,以便程序在写入时崩溃,并且可以在行为中捕获有问题的写指令.示例代码是Linux下的C(mprotect()用于开启保护),我很好奇如何将其应用于原生C++和Windows。 VirtualAlloc() 和/或 VirtualProtect() 看起来很有前途,但我不确定使用场景会是什么样子。

Fred *p = new Fred[100];
ProtectBuffer(p);
p[10] = Fred(); // like this to crash please

我知道在 Windows 中存在用于调试内存损坏的专门工具,但我仍然很好奇是否可以使用这种方法“手动”执行此操作。

编辑:此外,这在 Windows 下是个好主意,还是只是一种有趣的智力练习?

最佳答案

是的,您可以使用 VirtualAlloc 和 VirtualProtect 设置内存部分以防止读/写操作。

您将不得不重新实现 operator newoperator delete(以及它们的 [] 亲戚),以便您的内存分配由您的代码控制。

请记住,它只会以每页为基础,每次分配您将使用(至少)三页值(value)的虚拟内存 - 在 64 位系统上不是一个大问题,但可能如果您在 32 位系统中有很多分配,则会导致问题。

大致需要做的事情(您实际上应该找到构建 Windows 的页面大小 - 我太懒了,所以我将使用 4096 和 4095 来表示页面大小和页面大小-1 - 你还需要比这段代码做更多的错误检查!!!):

void *operator new(size_t size)
{
    Round size up to size in pages + 2 pages extra.
    size_t bigsize = (size + 2*4096 + 4095) & ~4095; 

    // Make a reservation of "size" bytes. 
    void *addr = VirtualAlloc(NULL, bigsize, PAGE_NOACCESS, MEM_RESERVE);

    addr = reinterpret_cast<void *>(reinterpret_cast<char *>(addr) + 4096);

    void *new_addr = VirtualAlloc(addr, size, PAGE_READWRITE, MEM_COMMIT); 

    return new_addr;
}

void operator delete(void *ptr)
{
    char *tmp = reinterpret_cast<char *>(ptr) - 4096;

    VirtualFree(reinterpret_cast<void*>(tmp)); 
}

正如我所说的那样——我没有尝试编译这段代码,因为我只有一个 Windows 虚拟机,而且我懒得下载编译器并查看它是否真的编译。 [我知道这个原理是有效的,因为我们在几年前的工作中做过类似的事情]。

关于c++ - 是否可以保护内存区域免受 WinAPI 的影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14595989/

相关文章:

c++ - 如何在 GUI 窗口中使用 WinApi (GDI) 在 C++ 中设置鼠标单击像素?

iphone - 使用对象引用的 NSArray,我是显式释放数组中的所有对象还是仅释放数组本身?

c++ - 在不使用外部库的情况下替换字符串列表中的整个单词

c++ - YouCompleteMe conf文件,用于检查库头文件而不报告库错误

c++ - 如何在 RichEdit 控件中查找粗体文本?

c# - 如何在 Windows 7 中模拟内存不足的情况

java - 谁杀死了我的 Java 无限循环线程?

c++ - 在 C++ 中存储一个对象或不存储对象的首选方法是什么?

python - Python 3 PyType_Ready 中的段错误

c++ - 在 WinAPI 中枚举音频适配器