【转】缓冲区溢出攻击试验(bufbomb.c)
来源:互联网 发布:手机测视力软件 编辑:程序博客网 时间:2024/05/16 00:59
本文的实验来源于《Computer Systems A Programmer's Perspective》(深入理解计算机系统》一书中第三章的一个实验。
作者给出了一个含有缓冲区溢出的程序bufbomb.c,你需要做的,就是注入给缓冲区些特殊的数据,到底利用缓冲区的目的。
//bufbomb.c
/* Bomb program that is solved using a buffer overflow attack */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char *getxs(char *dest)
{
int c;
int even = 1; /* Have read even number of digits */
int otherd = 0; /* Other hex digit of pair */
char *sp = dest;
while ((c = getchar()) != EOF && c != '/n') {
if (isxdigit(c)) {
int val;
if ('0' <= c && c <= '9')
val = c - '0';
else if ('A' <= c && c <= 'F')
val = c - 'A' + 10;
else
val = c - 'a' + 10;
if (even) {
otherd = val;
even = 0;
} else {
*sp++ = otherd * 16 + val;
even = 1;
}
}
}
*sp++ = '/0';
return dest;
}
/* $begin getbuf-c */
int getbuf()
{
char buf[12];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x/n", val);
}
/* $end getbuf-c */
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) & 0xFFF);
int *space = (int *) alloca(offset);
*space = 0; /* So that don't get complaint of unused variable */
test();
return 0;
}
函数getxs的功能类似于库函数gets的功能,除了它是以十六进制数字对的编码方式读入的字符。例如,要读入字符串“0123”,你得给出输入字符串“30 31 32 33”,这个函数会忽略空格。
分析这个程序,可以得知,正常情况下,这个函数会在getbuf中,调入getxs函数读入数字对,然后不管任何情况下,都会对test函数返回0x1,然后由test中的printf函数打印处getbuf的返回值。
现在你的任务,就是,利用缓冲区溢出的漏洞,输入些特殊的数字,使得屏幕中打印的是0xdeadbeef。
由于这个程序中含有alloca函数,因而要添加#include <new>#include <excpt.h>#include <malloc.h>(这三个是我在网上随便搜的,反正引进之后编译之后不报错)。
我是在WindowsXP,visual c++6.0环境解决这个问题的。
在做这个题目之前,你当然要知道什么是帧栈结构(请参阅《深入理解计算机系统》第三章),了解%ebp和%esp的含义。
题目中已经说了,“分析这个程序,可以得知,正常情况下,这个函数会在getbuf中,调入getxs函数读入数字对,然后不管任何情况下,都会对test函数返回0x1,”那我们该怎么办了?我们马上可以想到在getbuf这个函数里定义的char buf[12]上做手脚,可以看到在getxs函数里的while循环,结束条件只是以回车或者是eof结束符为判断标准,所以,根本没对char输入的数量做判断!这样的话,我们可以输入多于12个的数,从而缓冲区溢出!
在这里还是提一下帧栈结构,如下:
+-------------------------------+高地址
|函数参数 n 个 |
+-------------------------------+
|函数参数第 n-1 个 |
+-------------------------------+
| . . . |
| . . . |
| . . . |
+-------------------------------+
|函数参数第1个 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|local var(局部变量) |
+-------------------------------+
| others |
+-------------------------------+低地址
按照上面说的函数栈的存放情况,在getbuf这个函数里,函数参数没有,我们不管,然后就是return返回地址,然后就是ebp指针,然后就是char buf[12]。
+-------------------------------+低地址
|return 返回地址 |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
| buf[11] |
+-------------------------------+
| buf[10] |
+-------------------------------+
:
:
:
+-------------------------------+
| buf[0] |
+-------------------------------+
| others |
+-------------------------------+高地址
如果我们对buf溢出,能改写ebp和return地址!下面看看,ebp是多少,return地址是多少。
要知道这里的%ebp存的是test函数的%ebp,因而我们在调试的时候就可以在test函数得到%ebp的值,它应该是我们写入的buf[12]-buf[15]的值,而且它要保持原来的值,不然返回之后就乱套了,在我机器上是0x0012efa0。这个很容易,解决了第一步。
下面我们再来看返回地址,先看一段汇编码(不同的机器有所不同):
58: val = getbuf();
004011C5 call @ILT+10(getbuf) (0040100f)
004011CA mov dword ptr [ebp-4],eax
59: printf("getbuf returned 0x%x/n", val);
004011CD mov eax,dword ptr [ebp-4]
004011D0 push eax
004011D1 push offset string "getbuf returned 0x%x/n" (0042001c)
004011D6 call _printf (00401510)
004011DB add esp,8
在getbuf()返回后,肯定会接着执行004011CA ,我们能让它从这执行吗?当然不行!不然就要push eax,那是我们不想看到的,因为eax的值就是1。因而我们会想到能不能跳过这?当然能,改返回地址啊!顺水推舟,我们通过buf数组来覆盖返回地址。此时,我们想要它直接跳到004011D1处,因而可以通过设置buf[16]-buf[19]的值来覆盖返回地址。
到了考虑如何加进deadbeef了,在返回后,将直接执行push offset string "getbuf returned 0x%x/n" (0042001c),没eax怎么行了?不然printf函数就少了参数。再回到帧栈结构一下,printf在调用之前,要压入参数,先压入val,再压入offset string "getbuf returned 0x%x/n",也就是说参数val(等同那个eax)在offset string "getbuf returned 0x%x/n“之上,而且紧挨着。此时我们可以想到,既然返回之后(返回地址及其以下的元素都已弹出,返回地址的上一个字节成了栈顶)就执行push offset string "getbuf returned 0x%x/n" (0042001c)进行压栈,那此时栈顶一定是参数val,而它原来就在返回地址上面,因而我们可以通过设置buf[20]-buf[23]的值来覆盖这个地方。
综上所述,%ebp的值为0x0012efa0,修改后的返回地址为0x004011D1,因而我们可以输入
00000000 00000000 00000000 a0ef1200 d1114000 efbeadde
这24个0可以输入别的,不影响,关键是后面24个数。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/shuaiwang_01/archive/2008/10/26/3149172.aspx
- 缓冲区溢出攻击试验(bufbomb.c)
- 【转】缓冲区溢出攻击试验(bufbomb.c)
- bufbomb关于缓冲区溢出攻击
- cs app lab3 缓冲区溢出攻击 bufbomb
- 缓冲区溢出实验(bufbomb)
- bufbomb-缓冲区溢出实验
- 不错的文章--续--CS:APP bufbomb 缓冲区溢出攻击
- CSAPP实验四----缓冲区溢出实验bufbomb
- 缓冲区溢出试验
- 缓冲区溢出攻击(含示例)
- 缓冲区溢出攻击实验
- 缓冲区溢出*攻击*
- 缓冲区溢出攻击
- 缓冲区溢出攻击原理
- 缓冲区溢出攻击原理
- 缓冲区溢出攻击
- 缓冲区溢出攻击原理
- ret2reg缓冲区溢出攻击
- 纸黄金开户完全指南(最全最新)
- 忘记登录EM的url,怎么办
- 转:WindowsMobile 调用DirectShow进行视频操作
- 现货黄金完全入门
- 一辆奥迪A6L值多少个女大学生?(原创,有图有真相)
- 【转】缓冲区溢出攻击试验(bufbomb.c)
- 谈谈软件的可维护性问题
- 第一篇~
- 金融危机让企业重新审视ERP选型
- 无题
- DRAWITEMSTRUCT
- 如何在自定义数据源组件中限制用户的更改
- Buoy使得简单Java用户界面的编程变得轻而易举
- 那段感情飘到了世界的尽头