CPU阿甘之缓冲区溢出

开发 开发工具
最早的时候我认为程序都是顺序执行的,后来发现并不是这样,经常会出现一条跳转指令,让我到另外一个内存地址处去下一条指令去执行。

[[218450]]

我是大家的老朋友CPU阿甘, 每天你一开机,我就忙得不亦乐乎,从内存中读取一条条的指令,挨个执行。

最早的时候我认为程序都是顺序执行的,后来发现并不是这样,经常会出现一条跳转指令,让我到另外一个内存地址处去下一条指令去执行。

时间久了我就明白这是人类代码中的if ... else ,或者for ,while等循环导致的。

这样跳来跳去,让我觉得有点头晕,不过没有办法,这是人类做出的规定。

后来我发现,有些指令经常会出现重复,尤其是下面这几个:

  • pushl    %ebp
  • movl     %esp %ebp
  • call  xxxx
  • ret

正当我疑惑的时候,内存炫耀地说:这些指令是为了函数调用,建立栈帧所所必需的啊。

“函数调用?这是什么鬼?”

“函数调用你都不知道? 我告诉你吧,现在的计算机语言,甭管你是面向对象还是函数式、动态还是静态、解释还是编译,只要想在我们冯诺依曼体系结构下运行,最终都得变成顺序、循环、分支,以及函数调用!”

内存说着给我举了一个例子:

这个例子非常简单,一看就明白。

“但是栈帧是什么?”

“阿甘你知道栈是什么意思吧?”

“不就是一个先进后出的数据结构吗?”

“对,通俗来说:一个栈帧就是这个栈中的一个元素,表示了一个函数在运行时的结构。” 内存继续给我科普:

“你这种画法好古怪,怎么倒过来了,栈底在上方,栈顶反而在下方!”

“这也是人类规定的,一个进程的虚拟内存中有个区域,就是栈,这个栈就是从高地址向低地址发展的啊。”

“奥,原来我执行的代码在一个叫做代码区的地方存放着啊,执行的时候会操作你的栈,对不对?”

“没错,我再给你看看那个栈帧的内部结构吧!”

这张图看起来很复杂,但是和代码一对应,还是比较清楚的。

我心中模拟了一下这个执行过程,hello()函数正在被执行,当要调用add函数的时候,需要准备参数,即x = 10, y=20 。

还要记录下返回地址,即printf(....)这个指令在内存的地址。当add函数调用完成以后,就可以返回到这里执行了。

真正开始执行add函数的时候,也需要给它建立一个栈帧(其中要记录下上个函数栈帧的开始地址),还有这个函数的参数,在栈帧也会分配内存空间,例如sum, buf等。

等到执行结束,add函数的栈帧就废弃了(相当于从栈中弹出),找到返回地址,继续执行printf指令。

hello函数执行完毕,也会废弃掉,回到上一个函数的栈帧,继续执行,如此持续下去....

我对内存说:“明白了,我已经迫不及待地想执行一下这个函数,看看效果了。”

内存说:“真的明白了?正好,操作系统老大已经发出指令,让我们运行了,开始吧!”

建立hello函数的栈帧,调用add函数,建立add栈帧,执行add函数的代码, 一切都很顺利。

add函数中调用了scanf ,要求用户输入一些数据,人类是超级慢的,我耐心等待。

用户输入了8个字符A,我把他们都放到了buf所在的内存中:

但是人类还在输入,接下里是一些很奇怪的数据,其长度远远超过了char buf[8]中的8个字节。

可是我还得把数据给放到内存中啊,于是函数栈帧就变成了这个样子。

(注:用户输入的数据是从低地址向高地址存放的。)

我觉得特别古怪的是,这个返回地址也被冲掉了,被改写了。

这个用户到底要干啥?

add函数执行完毕,要返回到hello函数了, 我明明知道返回地址已经被改掉, 可是我没有选择,还得把那个新的(用户输入的)返回地址给取出来, 老老实实地去那个地址取出下一条指令去执行。

完了,这根本就不是原来的prinf函数,而是一段恶意代码的入口!

分割线

与此同时....

黑客三兄弟中的老三大叫: 大哥二哥,我的这次缓冲区溢出攻击实验成功了!

“不错啊,你是怎么搞的?” 老大问道。

“正如二哥说的,那个scanf函数没有边界检查,我成功地把代码注入到了栈帧中,并且修改了返回地址!于是程序就跳到我指定的地方执行了。”

【本文为51CTO专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】

戳这里,看该作者更多好文

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2019-02-27 13:58:29

漏洞缓冲区溢出系统安全

2017-01-09 17:03:34

2014-07-30 11:21:46

2009-09-24 18:16:40

2010-12-27 10:21:21

2010-10-09 14:45:48

2015-03-06 17:09:10

2020-08-10 08:37:32

漏洞安全数据

2022-05-07 08:27:42

缓冲区溢出堆栈

2011-03-23 12:39:44

2018-11-01 08:31:05

2010-09-08 15:43:18

2022-08-09 08:31:40

C -gets函数漏洞

2011-11-15 16:00:42

2010-09-29 15:10:58

2019-01-11 09:00:00

2011-03-23 11:35:00

2015-09-02 09:01:03

2009-05-13 09:21:48

2012-09-27 09:25:50

点赞
收藏

51CTO技术栈公众号