安全中国首页 > 文章中心 > 安全防护
 
安全中国网友投稿专用上传FTP空间:
Ftp服务器:download.anqn.com
Ftp端口:21
用户名:anqn
密 码:anqn.com
 

4.3.1 返回地址与程序流程(图)

更新时间:2008-8-27 0:27:13
责任编辑:池天
热 点:

4.3 修改函数返回地址

4.3.1 返回地址与程序流程

上节实验介绍的改写邻接变量的方法是很有用的,但这种漏洞利用对代码环境的要求相对比较苛刻。更通用、更强大的攻击通过缓冲区溢出改写的目标往往不是某一个变量,而是瞄准栈帧最下方的EBP和函数返回地址等栈帧状态值。

回顾上节实验中输入7个‘q’程序正常运行时的栈状态,如表4-3-1所示。
表4-3-1 栈帧数据

局部变量名

偏移3处的值

偏移2处的值

偏移1处的值

偏移0处的值

buffer

0x0012FB18

0x71 (‘q’)

0x71 (‘q’)

0x71 (‘q’)

0x71 (‘q’)

 

0x0012FB1C

NULL

0x71 (‘q’)

0x71 (‘q’)

0x71 (‘q’)

authenticated

0x0012FB20

0x00

0x00

0x00

0x01

前栈帧EBP

0x0012FB24

0x00

0x12

0xFF

0x80

返回地址

0x0012FB28

0x00

0x40

0x10

0xEB

如果继续增加输入的字符,那么超出buffer[8]边界的字符将依次淹没authenticated、前栈帧EBP、返回地址。也就是说,控制好字符串的长度就可以让字符串中相应位置字符的ASCII码覆盖掉这些栈帧状态值。

按照上面对栈帧的分析,不难得出下面的结论。
(1)输入11个‘q’,第9~11个字符连同NULL结束符将authenticated冲刷为0x00717171。
(2)输入15个‘q’,第9~12个字符将authenticated冲刷为0x71717171;第13~15个字符连同NULL结束符将前栈帧EBP冲刷为0x00717171。
(3)输入19个‘q’,第9~12个字符将authenticated冲刷为0x71717171;第13~16个字将前栈帧EBP冲刷为0x71717171;第17~19个字符连同NULL结束符将返回地址冲刷为0x00717171。

这里用19个字符作为输入,看看淹没返回地址会对程序产生什么影响。出于双字对齐的目的,我们输入的字符串按照“4321”为一个单元进行组织,最后输入的字符串为“4321432143214321432”,运行情况如图4.3.1所示。

 
图4.3.1 栈溢出导致程序崩溃

用OllyDbg加载程序,在字符串拷贝函数调用结束后观察栈状态,如图4.3.2所示。

 
图4.3.2 溢出前栈中的布局

实际的内存状况和我们分析的结论一致,此时的栈状态如表4-3-2所示。

表4-3-2 栈帧数据

局部变量名

偏移3处的值

偏移2字节

偏移1字节

偏移0字节

buffer[0~3]

0x0012FB18

0x31 (‘1’)

0x32 (‘2’)

0x33 (‘3’)

0x34 (‘4’)

buffer[4~7]

0x0012FB18

0x31 (‘1’)

0x32 (‘2’)

0x33 (‘3’)

0x34 (‘4’)

authenticated(被覆盖前)

0x0012FB20

0x00

0x00

0x00

0x01

authenticated(被覆盖后)

0x0012FB20

0x31 (‘1’)

0x32 (‘2’)

0x33 (‘3’)

0x34 (‘4’)

前栈帧EBP(被覆盖前)

0x0012FB24

0x00

0x12

0xFF

0x80

前栈帧EBP(被覆盖后)

0x0012FB24

0x31 (‘1’)

0x32 (‘2’)

0x33 (‘3’)

0x34 (‘4’)

返回地址(被覆盖前)

0x0012FB28

0x00

0x40

0x10

0xEB

返回地址(被覆盖后)

0x0012FB28

0x00(NULL)

0x32 (‘2’)

0x33 (‘3’)

0x34 (‘4’)

前面已经说过,返回地址用于在当前函数返回时重定向程序的代码。在函数返回的 “retn” 指令执行时,栈顶元素恰好是这个返回地址。“retn”指令会把这个返回地址弹入EIP寄存器,之后跳转到这个地址去执行。

在这个例子中,返回地址本来是0x004010EB,对应的是main函数代码区的指令,如图4.3.3所示。

 
图4.3.3 正常情况下函数返回后的指令

现在我们已经把这个地址用字符的ASCII码覆盖成了0x00333231,函数返回时的状态如图4.3.4所示。

 
图4.3.4 溢出后程序返回到无效地址0x00323334

我们可以从调试器中的显示看出计算机中发生的事件。
(1)函数返回时将返回地址装入EIP寄存器。
(2)处理器按照EIP寄存器的地址0x00323334取指。
(3)内存0x00323334处并没有合法的指令,处理器不知道该如何处理,报错。

由于0x00323334是一个无效的指令地址,所以处理器在取指的时候发生了错误使程序崩溃。但如果这里我们给出一个有效的指令地址,就可以让处理器跳转到任意指令区去执行(比如直接跳转到程序验证通过的部分),也就是说,我们可以通过淹没返回地址而控制程序的执行流程。以上就是通过淹没栈帧状态值控制程序流程的原理,也是本节实验要做的事。

·上一篇: 4.2.2 突破密码验证程序(图)
·下一篇: 暂时空缺
 
相关文章
一日一文章
 
一日一软件
一日一动画