title: shellcode: pass arguments to execve in x86_64 assembly
body: <p>I'm trying to write a shellcode that runs execve. The equivalent c program looks like this:</p>
  
  <pre><code>int main ()
  {
  
    char *argv[3] = {"/bin/sh","-i", "/dev/tty", NULL};
    execve("/bin/sh", argv, NULL);
  
    return 0;
  }
  </code></pre>
  
  <p>The c program runs fine. Then I tries to write my test program like this(revised to push null):</p>
  
  <pre><code>#include&lt;stdio.h&gt;
  int main(){
      __asm__(
              "xor    %rdx,%rdx\n\t"   //rdx is the third argument for execve, null in this case.
              "push   %rdx\n\t"
              "mov    -8(%rbp),%rdx\n\t"
              "mov    $0x692d,%rdi\n\t" //$0x6924 is 'i-'
              "push   %rdi\n\t"         //push '-i' to the stack
              "lea    -16(%rbp),%rax\n\t"    //now rax points to '-i'
              "mov    $0x31b7f54a83,%rdi\n\t" //the address of /bin/sh
              "push   %rdi\n\t"                //push it to the stack              
              "push   %rdx\n\t"                //end the array with null
              "mov    $0x31b7e43bb3,%rdi\n\t"  //the address of "/bin/sh"
              "push   %rdi\n\t"              //push the address of "/dev/tty to the stack
              "push   %rax\n\t"              //push the address of '-i' to the stack
              "mov    $0x31b7f54a83,%rdi\n\t"
              "push   %rdi\n\t"              //push the address of /bin/sh again to the stack
              "mov    %rsp,%rsi\n\t"         //rsi now points to the beginning of the array
              "mov    -24(%rbp),%rdi\n\t"   //rdi now points to the addresss of "/bin/sh"
              "mov    $0x3b,%rax\n\t"               // syscall number = 59
              "syscall\n\t"
      );
      }
  </code></pre>
  
  <p>I have the addresses of the strings in the memory here and we can assume they won't change. But we don't have the address of string '-i'. So what I'm doing here is pushing the arguments into the stack like this:</p>
  
  <hr>
  
  <pre><code>Low                  ------------------------------------------------------------------             High
  
  |addressof"/bin/sh"(rsi points to here)|addressof"-i"|addressof"/dev/ssh"|addressof"/bin/sh"(rdi points to here)|-i|
  </code></pre>
  
  <hr>
  
  <p>It didn't work. The program compiled ok but when I ran the program, nothing happened.</p>
  
  <p>I'm not familiar with assembly and I have some concerns about the way arguments are passed, for example, how does the compiler know when the argv argument ends in the memory?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Thanks to the suggestion below by Niklas B, I used trace to see if execve actually runs. And I got <code>execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3, 0x31b7f54a83, 0x692d], [/* 0 vars */]) = -1 EFAULT (Bad address)</code>, which means the second argument is passed wrong. Everything that I pushed into the stack is considered part of the argv argument!</p>
  
  <p>After I push nulls into the stack, the strace gives <code>execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3], [/* 0 vars */]) = -1 EFAULT (Bad address)</code>. This is quite close to the right answer only if the addresses are strings...</p>
  
  <p>Thanks to Brian, I now see where the problem lies now. The hardcoded addresses are in the share libary of another program. So this program shouldn't run until it's actually fed into that program. Thanks everyone, I'll update this as soon as I can. Id the problem's solved, I'll mark it as solved.</p>