title: Create and test x86-64 ELF executable shellcode on a Linux machine
body: <p>I am creating a training on buffer overflows and stack/heap attacks. I am working on an Ubuntu 12.04 <strong>x86_64</strong> machine and want to show some sample buggy programs and the ways you could exploit those vulnerabilities.</p>
  
  <p>I am trying to start with the most basic shellcode I have found so far, the simple exit call, which should exit the program being overflowed.</p>
  
  <p>Hereby the <strong>exitcall.asm</strong>:</p>
  
  <pre><code>;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
  </code></pre>
  
  <p>I've got this asm file from other tutorials, written for <strong>i386</strong> architectures however. Next thing to do is generate an object file and make it a binary executable:</p>
  
  <pre><code># 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 &lt;unfinished ...&gt;
          +++ exited with 0 +++
  
  # objdump -d exitcall
  
          exitcall:     file format elf64-x86-64
  
  
          Disassembly of section .text:
  
          0000000000400080 &lt;_start&gt;:
            400080:   31 db                   xor    %ebx,%ebx
            400082:   b0 01                   mov    $0x1,%al
            400084:   cd 80                   int    $0x80
  </code></pre>
  
  <p>As you can see the binary result executes well (exit 0 verified with strace), somehow giving me the confidence that the asm file is correct as well. So what I am supposed to do now is to create a shellcode character array from it, so I can test is in the following sample shellprogram.c executor. I just took the HEX values from <strong>objdump</strong> and started reading left to right, top to bottom, resulting in the following test:</p>
  
  <pre><code>char code[] = "\x31\xdb\xb0\x01\xcd\x80";
  
  int main(int argc, char **argv) {
  
      int (*exeshell)();
      exeshell = (int (*)()) code;
      (int)(*exeshell)();
  
  }
  </code></pre>
  
  <p>When I compile this file and execute it, I get a <strong>segmentation fault</strong>, however:</p>
  
  <pre><code># 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&gt;\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)
  </code></pre>
  
  <p>Does anyone have an idea where I am doing things wrong. Is my strategy to convert the binary elf64 file to shellcode string wrong, or is the original asm not 64 bit compatible as well?</p>
  
  <p>I read somewhere that in order to generate the shellcode I could use the following <strong>xxd</strong> linux command:</p>
  
  <pre><code># 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 &lt;_start&gt;:
            400080:   31 db                   xor    %ebx,%ebx
            400082:   b0 01                   mov    $0x1,%al
            400084:   cd 80                   int    $0x80
  </code></pre>
  
  <p>This array is considerably longer then the one from objdump (display assembler contents of executable sections) and also contains a lot of null bytes, which is not desirable in shell code, since the shellcode after a null (00) won't get executed.</p>
  
  <p>I tried the same strategy with a sample Hello World.asm, trying to make it x86-64 compatible and testing it with shellprogram... failed as well. Does anyone have some good material on how to write shellcode compatible asm (i.e. not using the data sections for strings and making your addresses independant)? </p>
  
  <p>Any help really appreciated,
  Boeboe.</p>