• 逆向进阶


    20175314 2020-3 《网络对抗技术》Exp1Plus 逆向进阶 Week3

    一、实践内容

    Task1 (5-10分)

    • 自己编写一个64位shellcode(参考shellcode指导)。
    • 自己编写一个有漏洞的64位C程序,功能类似我们实验1中的样例pwn1。使用自己编写的shellcode进行注入。

    Task 2 (5-10分)

    • 进一步学习并做ret2lib及rop的实践,以绕过“堆栈执行保护”(参考ROP)。

    Task 3 (5-25分)

    • 可研究实践任何绕过前面预设条件的攻击方法;可研究Windows平台的类似技术实践。
    • 或任何自己想弄明白的相关问题。包括非编程实践,如:我们当前的程序还有这样的漏洞吗?

    二、基础知识

    安装必要软件包

    • root用户权限下
    apt-get install gcc-multilib//安装gcc-multilib(生成多平台代码)
    apt-get install wxhexeditor//安装wxhexeditor(16进制文本编辑器)
    

    预备知识

    • Linux X86和X64的区别

    • 在开始前学习并实践Shellcode基础

    • 非常好用的Shellcode生成器

    • ROP全称为Retrun-oriented Programmming(面向返回的编程)是一种新型的基于代码复用技术的攻击,攻击者从已有的库或可执行文件中提取指令片段,构建恶意代码,ROP攻击同缓冲区溢出攻击,格式化字符串漏洞攻击不同,是一种全新的攻击方式,它利用代码复用技术。不同于return-to-libc攻击(攻击者不需要可执行的栈,甚至不需要shellcode,通过将程序的控制权跳转到系统自己的可执行代码),R0P攻击攻击之处在于以ret指令结尾的函数代码片段,而不是整个函数本身去完成预定的操作。

      • 从广义角度讲,return-to-libc攻击ROP攻击的特例。
      • 最初ROP攻击实现在x86体系结构下,随后扩展到各种体系结构。
      • 与以往攻击技术不同的是,ROP恶意代码不包含任何指令,将自己的恶意代码隐藏在正常代码中。因而,它可以绕过W⊕X的防御技术。

    实践原理

    • Linux下ELF格式

    • 重写shellcode汇编代码:shellcode要将字符串/bin/sh作为参数传递,shellcode被写入缓冲区后,代码的位置是不固定的,因为call指令执行的第一个动作就是将下一条指令的地址压栈,所以利用call指令能够得到/bin/sh这个字符串,我们把字符串安排在call指令后,目的就是要把它压入栈中。

    • ROP的核心思想:

      • 攻击者扫描已有的动态链接库和可执行文件,提取出可以利用的指令片段gadget,这些指令片段均以ret指令结尾,即用ret指令实现指令片段执行流的衔接。
      • 操作系统通过栈来进行函数的调用和返回,函数的调用和返回就是通过压栈和出栈来实现的。每个程序都会维护一个程序运行栈,栈为所有函数共享,每次函数调用,系统会分配一个栈桢给当前被调用函数,用于参数的传递、局部变量的维护、返回地址的填入等。栈帧是程序运行栈的一部分,在Linux中 ,通过%esp%ebp寄存器维护栈顶指针和栈帧的起始地址,%eip是程序计数器寄存器。
      • 而ROP攻击则是利用以ret结尾的程序片段 ,操作这些栈相关寄存器,控制程的流程,执行相应的gadget,实施攻击者预设目标。

    二、实验步骤

    1、Task1

    • 1、使用vim编写shellcode.c

    • 2、gcc -o shellcode shellcode.c编译生成可执行文件,执行查看效果

    • 3、objdump -d shellcode > shellcode.s 生成反汇编代码,找到main函数

    • 4、参照上面的反汇编代码使用vim重新编写scode.s

    as -o scode.o scode.s      //编译
    ld -o scode scode.o        //连接
    ./scode                    //运行
    
    以上汇编代码的解释
    jmp   cl                   #跳到cl标签处,即call pp
    call  pp                   #将字符串压栈,同时返回到上面pp标签处
    popq  %rcx                 #将字符串/bin/sh的地址存入rcx(通用寄存器,也可以选择其他寄存器)
    pushq %rbp                 #本条指令及以下两条指令都是在建立一个新的栈空间
    mov   %rsp, %rbp           #真正注入的shellcode代码可以不用创建这个栈
    subq  $0x20, %rsp          #但是bin/sh字符串是放在了代码段里不允许修改的空间
    movq  %rcx, -0x10(%rbp)    #将字符串复制到栈
    movq  $0x0,-0x8(%rbp)     #创建调用exec时的参数name[1],将它置0
    lea   -0x10(%rbp), %rsi    #这是execve第二个参数,它需要**类型,所以用lea传送地址给rsi
    mov   -0x10(%rbp), %rdi    #mov将字符串传给rdi,这是execve第一个参数
    mov   $59, %rax            #59是execve的系统调用号,在/usr/include/asm/unistd_64.h里可以查询到
    syscall                #系统调用,可以取代int 0x80
    
    • 5、objdump反汇编scode(这里使用可以直接输出shellcode的命令)

    • 6、在C语言程序中测试

    因为64位系统地址宽度是64位的,所以要使用long类型
    ret作为main的第一个局部变量,必定是存储在main的栈空间内
    其中long * ret 这条指令占据了一个64位, 当ret地址加1(64位)时,ret就到到达栈的基址位置(rbp)
    main函数的返回地址还在栈基址之上的高地址中,距离rbp还有64位宽度,所以ret需要加上2(64位),才能到达main的返回地址的保存位置
    (*ret) = (long)code,用code的地址将main返回地址覆盖
    

    三、遇到的问题

    问题:汇编报错nasm:fatal:unable to open output file

    • 解决方案:路径中包含_/+/-等符号,重新设置路径即可编译通过

    问题:C语言程序测试Shellcode段错误

    • 解决方案:GDB调试看main函数的调用,Shellcode是以全局字符数组变量的形式存储在进程堆栈中的数据段中,数据段是没有可执行权限的,所以一旦PC寄存器进入到这里面,那么程序就会报错。用命令将要运行的程序用execstack解除可执行栈的保护

    四、参考资料

  • 相关阅读:
    未能加载文件或程序集“Oracle.DataAccess”或它的某一个依赖项。试图加载格式不正确的程序。
    SQLServer2008/2012 删除所有表视图存储过程
    u盘启动盘制作工具
    华硕笔记本怎么设置u盘启动(两种方法)
    java listener实现定时任务
    Highcharts简介
    重温css系列01
    webstom 如何获取github上面的项目工程
    js高程 第 4章 变量、作用域和内存问题 【笔记】
    ionic 安装教程
  • 原文地址:https://www.cnblogs.com/SANFENs/p/12452195.html
Copyright © 2020-2023  润新知