在具有整页堆的buf = malloc(1)之后,为什么在覆盖buf [16]之前不会抛出保护页异常?

-7 c windows heap windbg pageheap

  1. 代码中的错误

    int main()
    {
        void *ptr = 0;    
        int overrun = 1;
        ptr = malloc(overrun);
        while(overrun++)
        {
            if(!ptr)
                while(1) Sleep(500);
            *((char*)ptr + (overrun+1)) = 'a';
            printf("\n%d\n",overrun);
        }
        return 0;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 从visual studio 2010的项目菜单确保构建为"Release"和"x64"(机器为x64)

  3. 启用FULL PAGE HEAP

    gflags /p /enable test.exe /full
    
    Run Code Online (Sandbox Code Playgroud)
  4. 制作windbg默认调试器

    E:\installed\Debugging Tools for Windows (x64)>windbg -I
    
    Run Code Online (Sandbox Code Playgroud)
  5. cmd没有调试器的情况下将代码作为单独的exe运行

    输出:

    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    Run Code Online (Sandbox Code Playgroud)

    之后看到windbg抓住腐败.而且我认为整页堆可以立即捕获损坏.

    有关为什么整页堆糟透了的任何评论?

Ray*_*hen 30

由于需要对齐堆分配,因此在发生溢出时无法捕获不跨越对齐边界的溢出,因为内存保护是页面粒度,而不是字节粒度.这是硬件限制.释放内存时将检测到溢出,并检查尾部字节是否被篡改.

(顺便说一句,说一些糟糕的事情会使你被指控吸吮的人不太可能会帮助你解决问题.只是一个提示.)

  • +1 @RaymondChen面对拖钓时的耐心. (10认同)
  • Pageheap影响`HeapAllocate`函数,`HeapAllocate`确实具有超出`malloc`的对齐要求. (2认同)

小智 5

扩展雷蒙德的回应.如果你在调试器中查看通过malloc返回的原始指针,你会看到它是从页面末尾开始的16个字节.这是因为x64上的HeapAlloc对齐要求是16字节.因此,它将您要求的1个字节放在尽可能接近页面末尾的位置.一旦走出页面的末尾,你就错了.