title: execve syscall returning EFAULT using 32bit call conventions on 64bit AMD
body: <p>I'm playing with manual syscalls in assembly. I was able to make it launch properly before, but after removing the nulls I'm not able to get the syscall to execute <code>/bin/date</code>. Here is the code I wrote in AT&amp;T syntax.</p>
  
  <pre><code>.global main
  main:
      jmp     two
  
  one:
      # zero rax and rdx
      xor     %rax,%rax 
      mov     %rax,%rdx
  
      # save string location
      mov     (%rsp),%rbx
  
      # push argv array onto the stack
      add     $16, %rsp
      push    %rax
      push    %rbx
      # assign argv pointer
      mov     %rsp,%rcx
  
      # execve call
      mov     $0xb, %al 
      int     $0x80
  
      # exit on failure
      xor     %rax,%rax
      xor     %rbx,%rbx
      movb    $0x1,%al
      int     $0x80
  
  two:
      # get address of the string
      call    one
      .string "/bin/date"
  </code></pre>
  
  <p>If I'm right, <code>%rbx</code> should point directly to the string which names the program to launch. <code>%rcx</code> should point to a null-terminated array of pointers representing the program's <code>argv</code>, and <code>%rdx</code> would point to the environment, so I've left it null here. And, of course, <code>%rax</code> holds the syscall number (<code>0x0b</code> in this case).</p>
  
  <pre><code>(gdb) info registers 
  rax            0xb  11
  rbx            0x4000a0 4194464
  rcx            0x7fffffffe968   140737488349544
  rdx            0x0  0
  
  (gdb) x/s $rbx
  0x4000a0:    "/bin/date"
  
  (gdb) x/s *$rcx
  0x4000a0:    "/bin/date"
  </code></pre>
  
  <p>Despite this, the syscall doesn't execute the program, and returns -14, which translates to <code>EFAULT</code> (segfault). I'm not sure what I'm overlooking, any help would be appreciated.</p>
  
  <hr>
  
  <p>So, a perceptive reader might have noticed that the above code is using 32bit syscall conventions (using <code>%ebx</code>, <code>int $0x80</code> and friends) on a 64bit system. This was an error, as the 32bit convention is supported only to enable executing 32bit code. In code written for 64bit systems, syscalls use <code>%rdi</code>,<code>%rsi</code>, <code>%rdx</code>, <code>%r10</code>, <code>%r8</code> and <code>%r9</code> as well as the <code>syscall</code> instruction. Here is the corrected code for 64bit systems (nullfree):</p>
  
  <pre><code>.global main
  main:
      jmp     two
  
  one:
      # zero rax and rdx
      xor     %rax,%rax 
      mov     %rax,%rdx
  
      # save string location, note that %rdi is used instead of %rbx
      pop     %rdi
  
      # push argv array onto the stack
      add     $16, %rsp
      push    %rax
      push    %rdi
      # assign argv pointer, using %rsi instead of %rcx
      mov     %rsp,%rsi
  
      # execve call, note that the syscall number is different than in 32bit
      mov     $0x3b, %al 
      syscall
  
  two:
      # get address of the string
      call    one
      .string "/bin/date"
  </code></pre>
  
  <p>However, the 32bit syscall convention <em>is</em> supported on 64bit systems (hence 32bit executables can be run), and I have also successfully <code>execve</code>d other commands using the 32bit call convention on this system. In fact, a large majority of the "shellcode" I examined for x86_64 systems used the 32bit conventions. So, my question still stands: <strong>why didn't the 32bit calling conventions work in the above code?</strong></p>