c – 是否可以保护WinAPI的内存区域?
作者:互联网
阅读了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 new和operator delete(以及它们的[]亲属),以便您的内存分配由您的代码控制.
请记住,它只会在每页的基础上,并且每个分配您将使用(至少)三页虚拟内存 – 这在64位系统上不是一个大问题,但如果是你在32位系统中有很多分配.
大概你需要做什么(你应该找到构建Windows的页面大小 – 我太懒了,所以我会用4096和4095来表示pagesize和pagesize-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 VM,我不能打扰下载编译器并查看它是否实际编译. [我知道这个原则是有效的,因为我们在几年前的工作中做了类似的事情].
标签:heap-corruption,c,memory-management,winapi 来源: https://codeday.me/bug/20190729/1569231.html