0

I am trying to understand, how an execve system call works and the underlying assembly. Here is my sample program:

// p1.c
#include <stdio.h>
void main() {
   char *name[2];
   name[0] = "/bin/sh";
   name[1] = NULL;
   execve(name[0], name, NULL);
}

My system is x86_64. I compiled it using gcc -ggdb -static -fno-stack-protector p1.c. Gcc version was 7.3.0

Here is the objdump -d ./a.out for main only

0000000000400b4d <main>:
  400b4d:   55                      push   %rbp
  400b4e:   48 89 e5                mov    %rsp,%rbp
  400b51:   48 83 ec 10             sub    $0x10,%rsp
  400b55:   48 8d 05 08 14 09 00    lea    0x91408(%rip),%rax        # 491f64 <_IO_stdin_used+0x4>
  400b5c:   48 89 45 f0             mov    %rax,-0x10(%rbp)
  400b60:   48 c7 45 f8 00 00 00    movq   $0x0,-0x8(%rbp)
  400b67:   00 
  400b68:   48 8b 45 f0             mov    -0x10(%rbp),%rax
  400b6c:   48 8d 4d f0             lea    -0x10(%rbp),%rcx
  400b70:   ba 00 00 00 00          mov    $0x0,%edx
  400b75:   48 89 ce                mov    %rcx,%rsi
  400b78:   48 89 c7                mov    %rax,%rdi
  400b7b:   e8 50 7f 04 00          callq  448ad0 <__execve>
  400b80:   90                      nop
  400b81:   c9                      leaveq 
  400b82:   c3                      retq   
  400b83:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  400b8a:   00 00 00 
  400b8d:   0f 1f 00                nopl   (%rax)

I understood every line till callq 448ad0 <__execve> call. Then I checked the __execve assembly from the objdump ooutput.

0000000000448ad0 <__execve>:
  448ad0:   b8 3b 00 00 00          mov    $0x3b,%eax
  448ad5:   0f 05                   syscall 
  448ad7:   48 3d 01 f0 ff ff       cmp    $0xfffffffffffff001,%rax
  448add:   73 01                   jae    448ae0 <__execve+0x10>
  448adf:   c3                      retq   
  448ae0:   48 c7 c1 c0 ff ff ff    mov    $0xffffffffffffffc0,%rcx
  448ae7:   f7 d8                   neg    %eax
  448ae9:   64 89 01                mov    %eax,%fs:(%rcx)
  448aec:   48 83 c8 ff             or     $0xffffffffffffffff,%rax
  448af0:   c3                      retq   
  448af1:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  448af8:   00 00 00 
  448afb:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

I understood that edx,rsi,rdi registers are used to pass the execve arguments form the main function. But I can't find any assembly code to process these arguments inside __execve code.

What I guess $0x3b may the syscall number and syscall instruction hides most of the implementation. If I do interactive gdb forward steps, then after the syscall instruction at 448ad5: shell prompt starts.

Can I get to know(if yes how ?), what other registers and are used to process the arguments and execute __execve system call ? Or, does the syscall instruction at address 448ad5: directly takes argument values from edx,rsi,rdi registers?

James Z
  • 12,209
  • 10
  • 24
  • 44
Debashish
  • 1,155
  • 19
  • 34
  • 1
    See https://stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-on-i386-and-x86-6 – Andrew Sun Dec 28 '18 at 16:39
  • 2
    The `syscall` instruction does a system call. The `execve` instruction is just a thin wrapper around that. All the argument processing and related stuff happens in the kernel. – fuz Dec 28 '18 at 16:41

0 Answers0