1.3.3 溢出报错的原因分析

“第一次我们输入的只是‘abcdefgh’。因为要进入main函数,所以系统把之前的EIP和EBP保存在堆栈中,便于以后恢复;然后为‘output[8]’在堆栈中分配8个char,拷贝‘abcdefgh’到其中。要注意的是,Windows下堆栈的分配是高址往低址分配的,其结构如图1-4。”

“这样在执行完main函数后,只要把保存在堆栈中的EBP、EIP恢复回去,就可继续原来的执行过程而没有任何问题。”

同学们点点头:“大概明白了,呵呵!”

“好,那第二次输入‘abcdefghijklmnopqrstuvwxyz’时,output分配的还是8个字节,但却拷了26个字母进来,和前面比较,其结果如图1-5所示。”

“大家注意了!由于拷贝的字母过长,不仅把分配给output的8个字节占据完了,而且还继续往下,把保存的EBP和EIP给占据了。”

“当执行完main函数后,系统要恢复EBP、EIP,而EIP已经被我们覆盖成ponm(即6d6e6f70)了。但系统不知道,就会去执行‘6d6e6f70’位置的东东。而那个位置是不可读的,所以就会出错。”

“乌拉!就是啊!”台下一片欢腾。

“呵呵,现在大家想想,我们可通过覆盖EIP为任意值来让程序运行到一个错误的地方,那如果我们特意把EIP覆盖成我们想去的程序的地方,那会怎么样呢?”

“我想,应该会运行我们‘想要的程序’吧!”一位浓眉大眼的同学说道,他叫宇强。

“很好!”老师以赞许的目光看了一眼宇强,“就是这样的。我们来看看‘想要的程序’的编写吧!”