4.4.1 有问题的程序

“好了,我们继续上课吧!”老师说道。

“大家都清楚了堆溢出利用的实质吧!就是写任意4个byte的数据到任意的内存地址中,即前面强调的what→where。除了刚才再分配时,我们能实现what→where外,我们也可覆盖已分配的管理结构,使它在释放时被我们利用!”

“哦?还可以这样啊?真是想不到,怎么利用啊?”同学们纷纷问道。

“看来大家兴趣都很高,不错,有兴趣才能钻研嘛!先看另一个有堆溢出问题的程序heapvul2.cpp。如下:”

#include <string.h> 
#include <stdio.h> 
#include <windows.h> 
#include <malloc.h> 
int main (int argc, char *argv[]) 
{ 
    HANDLE hHeap; 
    char *buf1, *buf2; 
    //一个38字节的缓冲区 
    char mybuf[] = "11112222333344445555666677778888\x03\x00\x05\x00\x00\x09";
    //我们自己建立一个HEAP 
    hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 0x10000, 0xfffff); 
    //分配两块32字节内存 
    buf1 = (char *)HeapAlloc(hHeap, 0, 32); 
    buf2 = (char *)HeapAlloc(hHeap, 0, 32); 
    //把38字节的‘mybuf’拷贝到32字节的‘buf1’里
    memcpy(buf1, mybuf, 32+6); 
    //释放内存 
    HeapFree(hHeap, 0, buf1); 
    //这里会出错 
    HeapFree(hHeap, 0, buf2); 
    return 0; 
}

“和上面那个heapvul2.cpp程序不一样,”老师说道,“这里 buf1=(char )HeapAlloc(hHeap, 0, 32); 和 buf2=(char )HeapAlloc(hHeap, 0, 32); 一来就动态分配好了‘buf1’和‘buf2’的空间,如图4-41。”

“然后 memcpy(buf1, mybuf, 32+6); 就是把‘mybuf’数组拷贝到‘buf1’里。拷贝了38字节,‘buf1’只有32字节。这样过长的字符串拷给‘buf1’,不仅覆盖了其32字节的空间,还覆盖了‘buf2‘的管理结构,如图4-42。”

“最后执行 HeapFree(hHeap, 0, buf2) 释放‘buf2’时就会出错。”老师说道。“我们测试一下,编译、执行!弹出出错对话框: ‘0x77fccfe8’指令应用的‘0x34343434’内存,该内存不能为‘written’ ,如图4-43。”