zoukankan      html  css  js  c++  java
  • 二进制入门-打造Linux shellcode基础篇

    0x01 前言

     
    本文的目的不是为了介绍如何进行恶意的破坏性活动,而是为了教会你如何去防御此类破坏性活动,以帮助你扩大知识范围,完善自己的技能,如有读者运用本文所学技术从事破坏性活动,本人概不负责。
     

    0x02 什么是Shellcode

     
    shellcode是用作利用软件漏洞的有效载荷的一小段代码,因为它通常启动一个命令shell,攻击者可以从中控制受攻击的机器,所以称他为shellcode。但是任何执行类似任务的代码都可以称为shellcode。 因为有效载荷的功能不仅限于一个shell。
    shellcode基本的编写方式有以下三种
     
    • 直接编写十六进制操作码。
    • 使用c语言编写程序,然后进行编译,最后进行反汇编来获取汇编指令和十六进制操作码。
    • 编写汇编程序,将该程序汇编,然后从二进制中提取十六进制操作码。
     
    第一种方法很极端,直接编写十六进制操作码是一件非常难得事情。下面我将带大家一步步去编写自己的shellcode。


    0x03 execve系统调用

     
    在Linux系统上执行程序的方式有多种,但是其中使用最广泛的一种方式就是通过借助execve系统调用。我们首先来看看execve的使用方法。


     

     
    说明看起来很复杂,其实很简单。我们先使用c语言来实现它。


    c语言实现execve系统调用创建shell

     
    我们首先来新建一个文件:
     

     

     
    我们使用vim来编写代码:
     
    看完上面的介绍,使用c语言来实现就很简单了。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <unistd.h>
     
    int main()
    {
        char * shell[2];
        shell[0]="/bin/sh";
        shell[1]=NULL;
        execve(shell[0],shell,NULL);
    }
     
    然后我们使用gcc编译器来编译一下:
     

    gcc test.c -o test.o

     
    运行看看:
     

     

     
    成功执行创建一个shell。


    转向汇编语言

     
    前面我们已经使用c语言来实现了,现在我们就需要用汇编语言来重写execve系统调用,其实很简单。我们先来查看一下execve系统调用号:11

     

    汇编代码重写:
     
    首先我们将寄存器eax清零。
     

    xor eax,eax

     
    然后我们将寄存器eax进行入栈操作,其实就是将字符串末尾的空字符值入栈:
     

    push eax

    然后将//sh入栈(由于需要对齐,因此这里用了四个字节)


    push 0x68732f2f

     
    最后将/bin入栈。


    push 0x6e69622f

     
    现在栈上已经有了全部所需数据,现在就是设置execve系统调用了。


    [AppleScript] 纯文本查看 复制代码
    1
    2
    3
    4
    5
    6
    7
    mov ebx,esp
    push eax
    push ebx
    mov ecx,esp
    xor edx,edx
    mov al,0xb  ;0xb表示其系统调用号的十六进制,execve的系统调用号为11
    int 0x80



    完整代码如下:


     
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    section .text
    global _start
     
    _start:
    xor eax,eax
    push eax
    push 0x68732f2f
    push 0x6e69622f
    mov ebx,esp
    push eax
    push ebx
    mov ecx,esp
    xor edx,edx
    mov al,0xb
    int 0x80



    汇编链接测试

     
    首先使用nasm进行汇编



    root@kali:~/demo# nasm -f elf test.asm

     
    然后使用ld链接


    root@kali:~/demo# ld -o test test.o

     
    运行测试看看

    root@kali:~/demo# ./test
    #

     

    0x04 提取十六进制操作码并测试Shellcode

     
    获得十六进制操作码很简单,我们只需要使用objdump工具的-d选项来进行反汇编即可:
     

     

     
    最后我们检查一下有没有出现空字符(x00)。


    测试shellcode

     
    首先我们将十六进制操作码放入一个名为shellcode[]的缓冲区中。


     
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdio.h>
     
    char shellcode[]=
    "x31xc0"
    "x50"
    "x68x2fx2fx73x68"
    "x68x2fx62x69x6e"
    "x89xe3"
    "x50"
    "x53"
    "x89xe1"
    "x31xd2"
    "xb0x0b"
    "xcdx80";
     
    int main()
    {
        void (*fp) (void);
        fp=(void *)shellcode;
        fp();
    }



    然后我们分配一个名为fp的函数指针,然后将这个函数指针设置为shellcode[]的起始地址。最后我们执行这个函数。
    现在我们编译一下,这里注意一下,编译成功后我们还是不能成功执行的,会出现段错误的提示,这是因为系统本身有数据区执行保护机制,导致在全局数据段的shellcode不能被运行,即出现段错误。
     

     

     
    这里我们先安装一下execstack。


    sudo apt-get install execstack

     
    然后针对编译后的程序使用execstack


    execstack -s 程序名

     
    之后执行就OK了
     

     

    总结

     
    现在我们已经知道一个shellcode编写流程了,别走开,这只是基础篇,我们实现的这个shellcode缺乏实战,下一篇教程我们继续完善这个shellcode。
     
    参考:
    《汇编语言(第3版) 》王爽
    《[科普]浅入浅出Liunx Shellcode》pr0cess
  • 相关阅读:
    python连接集群mongodb,封装增删改查
    selenium截屏操作(也支持截长图)
    ant生成jmeter测试报告没有数据【已解决】
    论自动化如何提高测试工作效率
    研究显示情商高的人比智商高的可怕多了
    提高程序员职场价值的10大技巧
    革命就是请客吃饭(案例分析吧)
    开发者应该了解的API技术清单!
    陈天:如何快速掌握一门技术
    程序员如何参与创业
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/7273935.html
Copyright © 2011-2022 走看看