4.2.2 堆溢出点的定位

“ 第一步、溢出点的定位 。因为这里会出现报错对话框,所以我们可利用它很准确的得到溢出点的位置。如果记不清楚,请复习一下以前的内容,这里大概过一遍。”

“首先改变程序,把mybuf数组填充的方法改变一下,改变的程序为heapvul3.c(光盘有收录)。我们把mybuf数组的填充方法替换为:”

for(i=0; i<240; i++)
{
    mybuf[i] = 100 + i % 10;
}

“重新生成程序并在命令行下执行,这次报错框成了 "0x77fcb3f5"指令引用的"0x69686766"内容,该内存不能为"written" ,如图4-7。”

“我们记下这个数字,看来是‘0x69686766’覆盖到了溢出点。我们把 mybuf[i] = 100 + i % 10 的取余数改为整除,得到程序heapvul4.c(光盘有收录)。”

for(i=0; i<240; i++)
{
    mybuf[i] = 100 + i / 10;
}

“执行heapvul4,这次出现的错误框成了 "0x77fcb3f5"指令引用的"0x79797979"内容,该内存不能为"written" ,如图4-8。”

“我们分析一下这两个过程。第一次是把mybuf数组不停的加上100~109,即十六进制0x64~0x6D的循环;第二次则是以10为一段长度,每段分别以0x64、0x65……来填充mybuf。”

“第一次溢出时,报错值是0x66,此时数组中只有0x64~0x6D不断循环,所以我们可以推出尾数是0x66-0x64 = 2。”

“第二次溢出时,报错的全部是0x79,而此时是从0x64开始,每10个数为一段。0x79-0x64=0x15(十进制的21),即在字符串的第21个段。”

“我们可以计算出出错点的位置了,如下:”

(0x79-0x64)×10+(0x66-0x64)=21×10+2=212

“大家验证一下,指定mybuf第212开始的四个字节是‘BBBB’,其余全部为‘A’。如果我们的计算正确,那么应该是0x42(B的十六进制)覆盖到溢出点。”

for(i=0; i<240; i++)
{
    mybuf[i] = 'A';
}
mybuf[212] = 'B';
mybuf[213] = 'B';
mybuf[214] = 'B';
mybuf[215] = 'B';

“好,这样修改后,执行该程序(heapvul5.c,光盘有收录),大家看!”

“哇!果然弹出的对话框成了 "0x77fcc39e"指令引用的"0x42424242"内容,该内存不能为written 。我们的计算非常正确哦!”大家说。

“我们分配的buf1是200个字节,溢出点却是第212个字节,看起来有点奇怪吧!”老师说。

“是啊,怎么会是这个数字呢?”大家都很奇怪。

“不要紧,分析之后就清楚了。我们还是先按步骤继续吧!”