《深入理解计算机系》缓冲区漏洞.pdf
文本预览下载声明
《深入理解计算机系统》3.38 题解——缓冲区溢出攻击实例
1. 问题描述
在这个问题中,你要着手对你自己的程序进行缓冲区溢出攻击。前面我们说过,我们不能原谅用这种或其他形式的攻击来
获得对系统的未被授权的访问,但是通过这个联系,你会学到许多关于机器级编程的知识。
从CS:APP 的网站上下载文件bufbomb.c,编译它创建一个可执行文件。在bufbomb.c 中,你会发现下面的函数。
1 int getbuf()
2 {
3 char buf[12];
4 getxs(buf);
5 return 1;
6 }
7
8 void test()
9 {
10 int val;
11 printf(Type Hex string:);
12 val = getbuf();
13 printf(getbuf returned 0x%x\n, val);
14 }
函数getxs (也在bufbomb.c 中)类似于库函数gets,除了它是以十六进制数字对的编码方式读入字符的以外。比如
说,要给它一个字符串0123,用户应该输入字符串“30 31 32 33”。这个函数会忽略空格字符。回忆一下,十进制数
字x 的ASCII 表示为0x3x。
这个程序的典型执行是这样的:
Unix./bufbomb
Type Hex string: 30 31 32 33
getbuf returned 0x1
看看getbuf 函数的代码,看上去似乎很明显,无论何时被调用,它都会返回值1。看上去就好像调用getxs 没有产生
效果一样。你的任务是,只简单地对提示符输入一个适当的十六进制字符串,就使getbuf 对test 返回-559038737
(0xdeadbeef)。
下面这些建议可能会帮助你解决这个问题:
o 用objdump 创建bufbomb 的一个反汇编版本。仔细研究,确定getbuf 的栈帧是如何组织的,以及溢出
的缓冲区会如何改变保存的程序状态。
o 在gdb 下运行你的程序。在getbuf 中设置一个断点,并运行到该断点。确定像%ebp 的值这样的参数,
以及已保存的当缓冲区溢出时会被覆盖的所有状态的值。
o 手工确定指令序列的字节编码是很枯燥的,而且容易出错。可以用工具来完成这个工作,写一个汇编代码
文件,包含想要放入栈中的指令和数据。用gcc 汇编这个文件,再用objdump 反汇编它,就可以获得要在提示符
处输入的字节序列了。当objdump 试图反汇编你文件中的数据时,它会产生一些看上去非常奇怪的指令,但是十
六进制字节序列应该是正确的。
要记住,你的攻击是非常依赖于机器和编译器的。当运行在不同的机器上或使用不同版本gcc 时,可能需要改变你的字符
串。
笔者注:
o 题目摘自《深入理解计算机系统》(中文版)第200 页。
o bufbomb.c 文件下载地址 /public/ics/code/asm/bufbomb.c
2. 目标分析与题解
看源程序可以发现,好像无论输入什么数据,其返回结果都是1,打印出来的都是0x1,似乎无从下手。另外,我们攻击
的目标只是让其返回0xdeadbeef,不干别的。
实验环境:Winxp + cygwin + gcc(3.4.4)
2.1 修改源程序?
这是题目不允许的。题目的要求是输入一些数据,使其输出为0xdeadbeef。输入什么样的数字串?这就是本题要求解
的。
2.2 如何得到这个数字串?
如果了解程序的编译、链接、执行的过程即可知道,此题不是无解。
由《过程调用与栈帧》一文可知,过程调用时要将参数和返回地址压入栈中,然后进入被调过程执行,待从被调过程返回
时,弹出返回地址,将该地址存入%eip 寄存器,并转到该地址开始执行。入栈和出栈均是对%esp 指向的内存操作,其基
地址为%ebp。
假设,如果我们输入的是机器码,存放于该缓冲区中,注意到程序中的缓冲区只有12 字节,利用缓冲区溢出,将本应存
放test 调用getbuf 的返回地址的内存单元修改为存放可执行的机器码的地址,而这个地址就是我们的缓冲区地址,那
么在调用完getbuf 后会返回到缓冲区地址处执行我们输入的机器码,在机器码中让程序输出oxdeadbeef,并正确返回
继续执行。这样会不会达到目标?
这句话有些拗口,总结来讲,就是将存放test
显示全部