Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 404 Vote(s) - 3.62 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Linux 64 command line parameters in Assembly

#1
This description is valid for Linux 32 bit:
When a Linux program begins, all pointers to command-line arguments are stored on the stack. The number of arguments is stored at 0(%ebp), the name of the program is stored at 4(%ebp), and the arguments are stored from 8(%ebp).

I need the same information for 64 bit.

Edit:
I have working code sample which shows how to use argc, argv[0] and argv[1]:

[To see links please register here]


<pre>
.globl _start
_start:
popq %rcx # this is argc, must be 2 for one argument
cmpq $2,%rcx
jne usage_exit
addq $8,%rsp # skip argv[0]
popq %rsi # get argv[1]
call ...
...
}
</pre>

It looks like parameters are on the stack. Since this code is not clear, I ask this question. My guess that I can keep rsp in rbp, and then access these parameters using 0(%rbp), 8(%rbp), 16(%rbp) etc. It this correct?
Reply

#2
I do believe what you need to do is check out the [x86-64 ABI][1]. Specifically, I think you need to look at section 3.2.3 Parameter Passing.


[1]:
Reply

#3
Despite the accepted answer being more than sufficient, I would like to give an explicit answer, as there are some other answers which might confuse.

Most important (for more information see examples below): in x86-64 the command line arguments are passed via stack:

(%rsp) -> number of arguments
8(%rsp) -> address of the name of the executable
16(%rsp) -> address of the first command line argument (if exists)
... so on ...

It is different from the function parameter passing in x86-64, which uses `%rdi`, `%rsi` and so on.

One more thing: one should not deduce the behavior from reverse engineering of the C `main`-function. C runtime provides the entry point `_start`, wraps the command line arguments and calls `main` as a common function. To see it, let's consider the following example.

**No C runtime/GCC with -nostdlib**

Let's check this simple x86-64 assembler program, which do nothing but returns 42:

.section .text
.globl _start
_start:
movq $60, %rax #60 -> exit
movq $42, %rdi #return 42
syscall #run kernel

We build it with:

as --64 exit64.s -o exit64.o
ld -m elf_x86_64 exit64.o -o exit64

or with

gcc -nostdlib exit64.s -o exit64

run in gdb with

./exit64 first second third

and stop at the breakpoint at `_start`. Let's check the registers:

(gdb) info registers
...
rsi 0x0 0
rdi 0x0 0
...
Nothing there. What about the stack?

(gdb) x/5g $sp
0x7fffffffde40: 4 140737488347650
0x7fffffffde50: 140737488347711 140737488347717
0x7fffffffde60: 140737488347724

So the first element on the stack is `4` - the expected `argc`. The next 4 values look a lot like pointers. Let's look at the second pointer:

(gdb) print (char[5])*(140737488347711)
$1 = "first"

As expected it is the first command line argument.

So there is experimental evidence, that the command line arguments are passed via stack in x86-64. However only by reading the [ABI][1] (as the accepted answer suggested) we can be sure, that this is really the case.

**With C runtime**

We have to change the program slightly, renaming `_start` into `main`, because the entry point `_start` is provided by the C runtime.

.section .text
.globl main
main:
movq $60, %rax #60 -> exit
movq $42, %rdi #return 42
syscall #run kernel

We build it with (C runtime is used per default):

gcc exit64gcc.s -o exit64gcc

run in gdb with

./exit64gcc first second third

and stop at the breakpoint at `main`. What is at the stack?

(gdb) x/5g $sp
0x7fffffffdd58: 0x00007ffff7a36f45 0x0000000000000000
0x7fffffffdd68: 0x00007fffffffde38 0x0000000400000000
0x7fffffffdd78: 0x00000000004004ed

It does not look familiar. And registers?

(gdb) info registers
...
rsi 0x7fffffffde38 140737488346680
rdi 0x4 4
...


We can see that `rdi` contains the `argc` value. But if we now inspect the pointer in `rsi` strange things happen:

(gdb) print (char[5])*($rsi)
$1 = "\211\307???"

But wait, the second argument of the `main` function in C is not `char *`, but `char **` also:

(gdb) print (unsigned long long [4])*($rsi)
$8 = {140737488347644, 140737488347708, 140737488347714, 140737488347721}
(gdb) print (char[5])*(140737488347708)
$9 = "first"

And now we found our arguments, which are passed via registers as it would be for a normal function in x86-64.

**Conclusion:**
As we can see, the is a difference concerning passing of command line arguments between code using C runtime and code which doesn't.


[1]:
Reply

#4
It looks like section 3.4 *Process Initialization*, and specifically figure 3.9, in the already mentioned [System V AMD64 ABI][1] describes precisely what you want to know.


[1]:
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through