zoukankan      html  css  js  c++  java
  • buflab实验

    一:准备工作

    1,三个二进制文件

    bufbomb:一个有缓冲区溢出漏洞的程序

    makecookie:可以根据用户不同的userid生成的唯一的cookieuserid不同,cookie不同,所要解决的方法就不同。

    hex2raw:使编写的缓冲区利用代码的转换为一个字符串的格式,只有经过转换以后才可以输入到getbuf

    2,生成cookie的方法

    3bufbomb函数原型及介绍

    getbuf函数类似于gets函数,它是读入一段字符串,字符串以 或者eof表示结束,并把存储起来,但是getbuf提供的缓冲区只有32个字符大小,但是getbuf本身又对输入的字符是否超过缓冲区大小进行安全检查,从而带来了缓冲区溢出漏洞。

    使用方法:

     

    参数:

    -u,确保不同的userid用不同的cookie

    -n为了level4,栈基址随机化模式的时候使用。

    -s上传到服务器进行打分

    4,提交方式

     

    5,提示

     

    二:实验

    Level 0

    实验描述:

    test函数调用getbuf函数,调用完以后还返回test函数,现在我们要做的是调用getbuf函数后,通过输入我们的exploit,使得调用完以后不返回test函数了而是执行smoke函数。

    test函数:

     

    解决方法:

    反汇编:

     

    在反汇编结果中找到getbuf函数,smoke函数:

    Getbuf函数:

     

    画出test函数调用getbuf函数的栈帧结构:

     

    由反汇编结果可知,给输入的字符串分配的空间是从%ebp-0x28开始的,换为10进制就是40个字节,而返回地址是在%ebp+0x4处,push %ebp本身又占了四个字节,所以结构为:

    返回地址

    4字节

    Getbuf的,从%ebp到输入字符串的空间为44个字节

    Smoke函数:

     

    由反汇编可得smoke函数的入口地址为0x08048e0a

    综上,我们需要做的就是把上面的44个字节随意填满(不要填换行),然后把原来的返回地址改为smoke函数的入口地址。0x0a是换行 ASCII值,所以不可以输入,那么我们就输入0x8048e0b来代替。

     

    Level1

    实验描述:

    test函数调用getbuf函数,调用完getbuf以后不返回getbuf的调用者test而是去执行fizz函数。fizz函数要求传入参数,参数必须是cookie

    fizz函数:

     

    解决方法:

    反汇编bufbomb找到fizz函数:

     

    level0类似,通过上一题已经知道了栈帧结构,所以我们需要做的还是把那44个字节填满,然后再填写fizz函数的入口地址(0x08048daf)用来覆盖原来的返回地址。

    关键:找到fizz函数的参数从栈中的什么地方传入的,然后我们把我们的cookie写进这个fizz会获取参数的地方。实参只在主调函数中有效,形参只在被调函数中有效,我们要做的就是修改实参,它的位置就是在返回地址的上面4个单位。而返回地址已经被我们破坏,会默认它上面四个字节为返回地址,然后再向上4个字节来取参数。

     

                                               执行leave

    所以答案如下:

    Level2

    实验描述:

    执行完getbuf()后,不返回到test,而是去执行函数bang,但是区别是bang也要传入参数,且参数是是一个全局变量。

    bang函数:

     

    解决方法:

    反汇编:

     

    bang函数的反汇编代码

     

    可以看到,bang、函数的入口地址为0x08048d52.

    接下来要做的就是改变全局变量global_value的值,使他的值为cookie

    由汇编代码,第四行 mov 0x804d10c,%eax 可以知道,global_value存放的位置是0x804d10c

    由此写下汇编代码:

    首先把我们的cookie写到全局变量的地址中,然后在把bang的入口地址入栈,通过ret指令来执行bang函数

     

    然后把.s文件变成字节码:

    利用gdb调试找到我们的exploit的地址了,用我们的地址来覆盖返回地址,从而执行我们的代码。

     

    所以答案如下:

     

    Level3:

    修改getbuf()函数的返回值(正常状态为0x1)为你的cookie,然后让函数正常返回到test.

    解决方法:

    函数调用栈,函数调用结束以后,栈被释放,而返回结果会放在eax寄存器中。test不需知道调用的getbuf是怎么执行的,只需要到eax寄存器中去取返回值,所以可以在getbuf执行完以后,再把eax寄存器中的值动手脚修改为cookie

    有关栈的恢复:需要两个部分,一个是ebp一个是eip的地址,一个是恢复poptest的原ebp,所以在破坏之前,用gdb调试出来test的原ebp是多少记录下来,恢复的时候在赋值给它。

    gdb来调试得到ebp的值:

     

    testebp0x556839f0

    eip的地址,就是返回地址,也就是test中在callgetbuf函数的下一条指令的地址:

     

    call的下一条指令的地址是0x8048e50

    所以.s代码:

     

    %eax的值改为cookie

    %ebp的恢复,改成0x556839f0

    把下一条指令地址0x8048e50压入

    返回

    .s文件变成字节码:

     

    所以答案是:

     

    第一句 第三句 ret

    填充0

    %ebp恢复

    自己的返回地址

     

    Level4

    调用getbufn函数,

    其缓冲区大小为512个字节, 且每次栈的位置都会变化

    nop只是执行eip自加1不进行其他的操作。在无法猜测的时候,只需要找到最大的地址。

    解决方法:

    反汇编,查看getbufn反汇编结果。

     

    buf的首地址为-0x208%ebp)为十进制520个字节大小。

    每次运行testnebp都不同,所以每次getbufn里面保存的testebp也是随机的,但是栈顶的esp是不变的,我们就要找到每次随机的ebpesp之间的关系来恢复ebp。我们先通过调试来看一下getbuf里面保存的ebp的值的随机范围为多少。

    ebp的值              减去0x208buf的首地址

    0x556839c0             0x556837b8

    0x556839f0             0x556837e8

    0x55683970             0x55683768

    0x556839f0             0x556837e8

    0x55683950             0x55683748

    testn的反汇编代码:

     

    call getbufn的下一条指令的地址为0x8048ce2

    此外,还可以看到,mov  %esp,%ebp 此时espebp相等

    push  %ebx  此时ebp=esp+0x4

    sub   $0x24,%esp 这个时候执行完后,ebp=esp+0x28,这就是espebp每次的变化关系,通过esp来恢复我们的每次的ebp

    由此写出以下汇编代码:

     

    .s文件变成字节码:

    509nop

    15个字节码,覆盖篡改保存ebp

    Buf首地址覆盖返回地址,是可能的最大的首地址

    三:总结

    要想做明白这个实验,就需要弄懂缓冲区溢出原理,以及堆栈的过程,函数调用的实现过程,函数传参的底层实现等问题。并且,光理解原理也还远远不够,还需要会应用。本次实验的几个level是逐步跟进的,一点一点的深入。Level0只需要理解原理,进行覆盖地址,level1是修改参数,level2是修改全局变量,level3是恢复栈结构,level4是在level3第基础上实现随机化。在实验的过程中还需要注意避免输入换行对应的数字码等等。

    另外,在做本次实验的过程中还遇到一个比较特别的问题,这个问题很隐蔽,难以发现,花费了很久才找到。在将自己写的code4.s汇编的过程中,出现了机器码生成错误的问题,mov指令对应的机器码应该是b8,而在我的机器中,level4,却生成了a1,至今还不知道为什么会出现这个问题。在与其他同学交流的过程中,发现其他同学也有过这种情况,是push指令对应的机器码发生了错误。

    截图如下:

  • 相关阅读:
    SQLServer字符串与数字拼接
    今天踩了一个低级坑
    DataTable Linq Group Count where写法
    红米note7几个问题处理
    Svn CleanUp failed解决方案
    VisualSVN 新版本终于支持一个解决方案下多workcopy了,并解决了上个版本一个重要BUG
    UML类图
    EXT.net 1.x TreePanel的一个坑
    AntDesign vue学习笔记(九)自定义文件上传
    C# Convert.ChangeType()
  • 原文地址:https://www.cnblogs.com/tianxiesiwuxie/p/6882915.html
Copyright © 2011-2022 走看看