zoukankan      html  css  js  c++  java
  • 20145236《网络对抗》进阶实验——Return-to-libc攻击

    20145236《网络对抗》进阶实验——Return-to-libc攻击

    基础知识

    • Return-into-libc攻击方式不具有同时写和执行的行为模式,因为其不需要注入新的恶意代码,取而代之的是重用漏洞程序中已有的函数完成攻击,让漏洞程序跳转到已有的代码序列(比如库函数的代码序列)。攻击者在实施攻击时仍然可以用恶意代码的地址(比如libc库中的 system()函数等)来覆盖程序函数调用的返回地址,并传递重新设定好的参数使其能够按攻击者的期望运行。这就是为什么攻击者会采用return-into-libc的方式,并使用程序提供的库函数。这种攻击方式在实现攻击的同时,也避开了数据执行保护策略中对攻击代码的注入和执行进行的防护。

    • 攻击者可以利用栈中的内容实施return-into-libc攻击。这是因为攻击者能够通过缓冲区溢出改写返回地址为一个库函数的地址,并且将此库函数执行时的参数也重新写入栈中。这样当函数调用时获取的是攻击者设定好的参数值,并且结束后返回时就会返回到库函数而不是 main()。而此库函数实际上就帮助攻击者执行了其恶意行为。更复杂的攻击还可以通过 return-into-libc的调用链(一系列库函数的连续调用)来完成。

    实验步骤

    一、配置实验环境

    1. 在自己的虚拟机上输入命令安装一些用于编译32位C程序的东西,输入命令linux32进入32位linux环境,输入/bin/bash使用 bash
    sudo apt-get update
    sudo apt-get install lib32z1 libc6-dev-i386
    sudo apt-get install lib32readline-gplv2-devsudo apt-get install lib32readline-gplv2-dev
    
    1. 这个攻击最终的目标是要获取root权限,因此在做之前,我先另外添加了一个用户:
    2. 进入32位linux环境,将地址随机化关闭sudo sysctl -w kernel.randomize_va_space=0,并且把/bin/sh指向zsh:

    二、漏洞程序

    1. 将漏洞程序保存在/tmp目录下,编译该程序:

    2. 编译该代码,使用–fno-stack-protector来关闭阻止缓冲区溢出的栈保护机制,并设置给该程序的所有者以suid权限,可以像root用户一样操作:

    三、在/tmp文件夹下编写getenvaddrexploit

    1. getenvaddr用来读取环境变量:
    2. 将攻击程序"exploit.c"保存在/tmp目录下:
    3. 在root用户下编译:
    4. 用刚才的getenvaddr程序获得BIN_SH地址:
    5. 利用gdb获得systemexit地址:
    6. 将上述三个地址修改入"exploit.c"文件:
    7. 删除刚才调试编译的exploit程序和badfile文件,重新编译修改后的"exploit.c"文件:(由于exploit文件受保护无法用命令删除,所以在图形化界面tmp文件夹下直接手动删除)

    四、攻击

    • 先运行攻击程序exploit,再运行漏洞程序retlib,攻击成功,获得了root权限:

    五、深入思考

    将/bin/sh 重新指向/bin/bash(或/bin/dash),观察能否攻击成功,能否获得 root 权限。

    • 首先,我们将/bin/sh重新指向/bin/bash,运行漏洞程序:

    • 发现无法获取root权限,因为bash内置了权限降低的机制,虽然我们可以使得bof返回时执行system(“/bin/sh”),但是我们也依旧获取不到root权限。

    • 如果我们要想在/bin/sh指向/bin/bash时获取root权限,那我们就要想办法在调用/bin/bash之前提升正在运行的进程的Set-UID至root权限,那么我们就可以绕过对bash的权限限制。

    • 之后在查资料时发现了Linux下一个setuid()函数,查看其帮助文档:

    • 从帮助文档中可以得知setuid()用来重新设置执行目前进程的用户识别码,不过,要让此函数有作用,其有效的用户识别码必须为0(root)。在Linux 下,当root 使用setuid()来变换成其他用户识别码时,root 权限会被抛弃,完全转换成该用户身份,也就是说,该进程往后将不再具有可setuid()的权利。

    • 因此我们可以利用函数setuid(0)来实现我们的目标,在调用系统函数system(“/bin/sh”)之前,先调用系统函数setuid(0)来提升权限。

    • 我们先要对攻击程序进行修改,在bof的返回地址处(&buf[24])写入setuid()的地址,setuid的地址同样可以通过gdb来获得:

    • setuid的参数0写在与其入口地址相隔一个字节的位置(即buf[32])处(因为setuid()执行完毕之后,会转向存放setuid入口地址的下一个位置,所以这个位置应该放入system函数的入口地址),同理system的参数放入&buf[36]处。

    • 修改完成后,编译运行,发现攻击成功!

  • 相关阅读:
    阅读文献总结笔记11
    阅读文献总结笔记20
    阅读文献总结笔记13
    阅读文献总结笔记19
    阅读文献总结笔记17
    阅读文献总结笔记18
    阅读文献总结笔记15
    java图片以字符串的形式传输
    java与C#对接签名和验签
    SIP代码大全
  • 原文地址:https://www.cnblogs.com/feng886779/p/8618154.html
Copyright © 2011-2022 走看看