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。”