在Linux机器上创建并测试x86-64 ELF可执行shellcode

时间:2015-01-12 10:46:09

标签: linux nasm x86-64 elf shellcode

我正在创建有关缓冲区溢出和堆栈/堆攻击的培训。我正在使用Ubuntu 12.04 x86_64 计算机,并希望展示一些示例错误程序以及利用这些漏洞的方法。

我试图从目前为止找到的最基本的shellcode开始,简单的退出调用,它应该退出程序溢出。

特此是 exitcall.asm

;exitcall.asm

[SECTION .text]

global _start

_start:
    xor ebx,ebx     ; zero out ebx, same function as mov ebx,0
    mov al, 1       ; exit command to kernel
    int 0x80

我已经从其他教程获得了这个asm文件,但是为 i386 架构编写。接下来要做的是生成一个目标文件并使其成为二进制可执行文件:

# nasm -f elf64 exitcall.asm

# ld -o exitcall exitcall.o 

# file exitcall

        exitcall: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), statically linked, not stripped

# strace ./exitcall

        execve("./exitcall", ["./exitcall"], [/* 73 vars */]) = 0
        write(0, NULL, 0 <unfinished ...>
        +++ exited with 0 +++

# objdump -d exitcall

        exitcall:     file format elf64-x86-64


        Disassembly of section .text:

        0000000000400080 <_start>:
          400080:   31 db                   xor    %ebx,%ebx
          400082:   b0 01                   mov    $0x1,%al
          400084:   cd 80                   int    $0x80

正如您所看到的,二进制结果执行良好(使用strace验证退出0),以某种方式让我确信asm文件也是正确的。所以我现在应该做的是从它创建一个shellcode字符数组,所以我可以测试下面的示例shellprogram.c executor。我刚刚从 objdump 中取出了HEX值并开始从左到右,从上到下阅读,导致以下测试:

char code[] = "\x31\xdb\xb0\x01\xcd\x80";

int main(int argc, char **argv) {

    int (*exeshell)();
    exeshell = (int (*)()) code;
    (int)(*exeshell)();

}

当我编译此文件并执行它时,我得到分段错误,但是:

# gcc shellprogram.c -o shellprogram

# file shellprogram
        shellprogram: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=765bdf6201099b9784b63a0111dc16c1115118bb, not stripped

# strace ./shellprogram 
        execve("./shellprogram", ["./shellprogram"], [/* 73 vars */]) = 0
        brk(0)                                  = 0x602000
        access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
        mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7ff8000
        access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
        open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
        fstat(3, {st_mode=S_IFREG|0644, st_size=134914, ...}) = 0
        mmap(NULL, 134914, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7fd7000
        close(3)                                = 0
        access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
        open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
        read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
        fstat(3, {st_mode=S_IFREG|0755, st_size=1845024, ...}) = 0
        mmap(NULL, 3953344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff7a14000
        mprotect(0x7ffff7bcf000, 2097152, PROT_NONE) = 0
        mmap(0x7ffff7dcf000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bb000) = 0x7ffff7dcf000
        mmap(0x7ffff7dd5000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dd5000
        close(3)                                = 0
        mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fd6000
        mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fd4000
        arch_prctl(ARCH_SET_FS, 0x7ffff7fd4740) = 0
        mprotect(0x7ffff7dcf000, 16384, PROT_READ) = 0
        mprotect(0x600000, 4096, PROT_READ)     = 0
        mprotect(0x7ffff7ffc000, 4096, PROT_READ) = 0
        munmap(0x7ffff7fd7000, 134914)          = 0
        --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x601038} ---
        +++ killed by SIGSEGV (core dumped) +++
        Segmentation fault (core dumped)

有没有人知道我做错了什么。我的策略是将二进制elf64文件转换为shellcode字符串错误,还是原始的asm不兼容64位?

我在某处读到,为了生成shellcode,我可以使用以下 xxd linux命令:

# xxd -i exitcall

    unsigned char exitcall[] = {
      0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
      0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x40, 0x00,
      0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xdb, 0xb0, 0x01,
      0xcd, 0x80, 0x00, 0x2e, 0x73, 0x79, 0x6d, 0x74, 0x61, 0x62, 0x00, 0x2e,
      0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x73, 0x68, 0x73, 0x74,
      0x72, 0x74, 0x61, 0x62, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
      0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
      0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0xe8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
      0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x03, 0x00, 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
      0x04, 0x00, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x04, 0x00, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
      0x10, 0x00, 0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
      0x10, 0x00, 0x01, 0x00, 0x86, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
      0x10, 0x00, 0x01, 0x00, 0x86, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
      0x10, 0x00, 0x01, 0x00, 0x88, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x78, 0x69,
      0x74, 0x63, 0x61, 0x6c, 0x6c, 0x2e, 0x61, 0x73, 0x6d, 0x00, 0x5f, 0x73,
      0x74, 0x61, 0x72, 0x74, 0x00, 0x5f, 0x5f, 0x62, 0x73, 0x73, 0x5f, 0x73,
      0x74, 0x61, 0x72, 0x74, 0x00, 0x5f, 0x65, 0x64, 0x61, 0x74, 0x61, 0x00,
      0x5f, 0x65, 0x6e, 0x64, 0x00
    };
    unsigned int exitcall_len = 725;

# objdump -d exitcall

        exitcall:     file format elf64-x86-64

        Disassembly of section .text:

        0000000000400080 <_start>:
          400080:   31 db                   xor    %ebx,%ebx
          400082:   b0 01                   mov    $0x1,%al
          400084:   cd 80                   int    $0x80

这个数组比objdump(显示可执行部分的汇编程序内容)的数组长得多,并且还包含很多空字节,这在shell代码中是不可取的,因为null(00)之后的shellcode赢了&#39执行。

我尝试使用示例Hello World.asm执行相同的策略,尝试使其与x86-64兼容并使用shellprogram进行测试...也失败了。有没有人有一些关于如何编写shellcode兼容asm的好材料(即不使用字符串的数据部分并使地址独立)?

任何帮助真的很感激, Boeboe。

2 个答案:

答案 0 :(得分:4)

问题是测试程序 shellprogram.c 对于我想用它的目的是不正确的,如@Iwillnotexist Idonotexist所述。由于操作系统强制执行内存保护,您无法执行数据。

最终结果有效(使包含char [] shellcode的数据部分可读和可执行)正在调用:

mprotect((void*)((intptr_t)code & ~0xFFF), 8192, PROT_READ|PROT_EXEC);  

简单 exitcall 示例的最终结果:

#include <unistd.h>
#include <sys/mman.h>

unsigned char code[] = {
  0x31, 0xdb, 0xb0, 0x01, 0xcd, 0x80
};

int main(int argc, char **argv) {

    mprotect((void*)((intptr_t)code & ~0xFFF), 8192, PROT_READ|PROT_EXEC);  

    int (*exeshell)();
    exeshell = (int (*)()) code;
    (int)(*exeshell)();

    printf("Failed to execute shellcode");

}

打印的最终结果&#34;您赢了!\ r \ n&#34;到控制台:

#include <unistd.h>
#include <sys/mman.h>

unsigned char code[] = {
  0xeb, 0x19, 0x31, 0xc0, 0x31, 0xdb, 0x31, 0xd2, 0x31, 0xc9, 0xb0, 0x04,
  0xb3, 0x01, 0x59, 0xb2, 0x0a, 0xcd, 0x80, 0x31, 0xc0, 0xb0, 0x01, 0x31,
  0xdb, 0xcd, 0x80, 0xe8, 0xe2, 0xff, 0xff, 0xff, 0x79, 0x6f, 0x75, 0x20,
  0x77, 0x69, 0x6e, 0x21, 0x0d, 0x0a
};


int main(int argc, char **argv) {

    mprotect((void*)((intptr_t)code & ~0xFFF), 8192, PROT_READ|PROT_EXEC);  

    int (*exeshell)();
    exeshell = (int (*)()) code;
    (int)(*exeshell)();

    printf("Failed to execute shellcode");

}   

再次感谢您展示解决方案!

答案 1 :(得分:0)

如果它有助于您使用32位应用程序的内存寄存器指针 - 您需要将64位的RAX和RBX替换为EAX和EBX。

迟到了一年,我知道,无疑你已经离开了,但我想我会提到它!