2

edi is argc, rsi is argv

   0x0000000000400535 <+8>: mov    %edi,-0x4(%rbp)
   0x0000000000400538 <+11>:    mov    %rsi,-0x10(%rbp)

here I get argv pointer

(gdb) x/8x $rbp-0x10
0x7ffdb7cac380: 0xb7cac478  0x00007ffd  0x00000000  0x00000003
0x7ffdb7cac390: 0x00000000  0x00000000  0x1f130b45  0x00007ff3

Pointer 0x7ffdb7cac478

So my argv[2] is here:

(gdb) x/8x 0x7ffdb7cac478+16
0x7ffdb7cac488: 0xb7cacd8a  0x00007ffd  0x00000000  0x00000000

At address 0x7ffdb7cacd8a

I need to get the address of argv[2], so I want to write this assembler code:

Pseudocode:

x - load 8 bytes from address $rbp-0x10 // (pointer to argv)

y - load 8 bytes from x value+16 // (pointer to argv[2])

I need later to jmp to y.

How do I write in assembler x64? Which register I can use to for x and y?

I hope it is understandable. I am a beginner.

I ask here since I don't know where to start doing my research.

UPDATE:

Tried with this:

bits 64
ldr r8, rbp, #0x10
ldr r9, r8, #0x10
jmp r9

But it doesn't even compile .... I am using nasm.

I guess above was for ARM arch, for amd64 (x64) below should do this. Is it correct?

UPDATE 2:

bits 64
lea r8, [rbp-0x10]
lea r9, [r8+0x10]
jmp r9

UPDATE 3:

Also doesn't work ...

bits 64
lea r8, [rbp-0x10]
mov r9, [r8]
mov r10, [r9+0x10]
jmp r10
dev
  • 1,119
  • 1
  • 11
  • 34
  • Nothing beats reading about registers and program flow from your favorite assembler reference. For which registers to use for `x and y` you could use any two general purpose registers. For "How do I do this", the answer is try and then post your progress if you get stuck. – Frank C. Mar 08 '16 at 10:10
  • These are my first assembler steps, dont have any favorite reference. Can you point to any? A big help would be to at least tell which instruction load x bytes to an address ? Is it ldr, ldi ? What should I search for? – dev Mar 08 '16 at 10:27
  • Added my code I tried ... doesn't even compile :/ – dev Mar 08 '16 at 10:39
  • added another code ... this compiles, but not sure if it is correct – dev Mar 08 '16 at 11:10
  • Try http://www.nasm.us/doc/ – Frank C. Mar 08 '16 at 14:59

1 Answers1

5

Are you writing main() or _start?

If you're writing main, it's a normal function with its args in rdi, rsi, following the normal calling convention. See tag wiki for links to the x86-64 ABI.

If you're writing _start, then data is on the stack, as documented in process startup section of the ABI: [rsp] = argc, and above that an array of pointers, char *arg[] starting at rsp+8. It's an actual array right there on the stack, not a pointer to an array like main gets.

rbp is meaningless unless you initialize it. It has whatever the caller left in it.


Your code fragment is silly, too: you never initialize rbp. You should assume it holds garbage on process entry. Only rsp is guaranteed to be useful.

lea is just a shift & add instruction that uses effective-address syntax / encoding. mov is the mnemonic for load / store.

    ;; your code with comments, also assuming that RBP was initialized
    bits 64
    lea r8, [rbp-0x10]      ; r8 = rbp-0x10
    mov r9, [r8]            ; should have just done mov r9, [rbp-0x10]
    mov r10, [r9+0x10]
    jmp r10                 ; jump to argv[2]???

Did you put machine code bytes in argv[2]? Jumping to a string is not normally useful.

Of course, since rbp isn't initialized, it's not actually accessing argv[2].


Working example

single-step this in a debugger if you want to see what's going on.

; get argc and argv from the stack, for x86-64 SysV ABI
global _start
_start:
    mov   ecx,  [rsp]             ;   load argc (assuming it's smaller than 2^32)

    cmp   ecx, 3
    jb  .argc_below_3
                                  ;   argv[0] is at rsp+8
    mov   rsi,  [rsp+8 +  8*2]    ;   argv[2]  (the 3rd element)
    movzx eax,  byte [rsi]        ;   first char of argv[2]

    ; if you stop here in a debugger, you can see the character from the second arg.

    ; fall through and exit
.argc_below_3:
    xor edi, edi
    mov eax, 231                  ;  exit_group(0)
    syscall
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Can you add how to access the `char** argv` params if we are writing for `main()` linux 64. or if it is possible to point me to some documentation where I can get this info? thank you for your time. – Nasreddine Galfout Apr 28 '20 at 23:54
  • @NasreddineGalfout: on entry to `main`, RSI = argv like I mention in this answer. See also [What are the calling conventions for UNIX & Linux system calls on i386 and x86-64](https://stackoverflow.com/q/2535989) which covers the function-calling convention as well. Or look at compiler-generated code for a C `main` if you aren't sure how to use it in some specific way: [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116) – Peter Cordes Apr 29 '20 at 00:18
  • thank you Peter for your response. I have been looking for four hours now for this (second day). I have managed to find a way to convert a c prog to nasm readable format using objconv lib. how ever I really do not see it. All I need is a way to read the cmmand line passed to my main() that are stored in argv. I know that they are in RSI but I'm failing to get them. I would kindly ask you to point me to an easy way to understand how to retrieve that info from RSI in 64 linux. – Nasreddine Galfout Apr 29 '20 at 07:32
  • I think I found it. thank you so much for your help. If you have any info (pitfalls that I might encounter) please share. again thank so much for your help. for any one that having the same problem see [this post](https://sinister.ly/Thread-ASM-How-to-get-command-line-arguments) your first argv[1] is at qword [rsi+8] (linux 64) – Nasreddine Galfout Apr 29 '20 at 07:56
  • 1
    @NasreddineGalfout: Yup, that's right. There's an FAQ section in https://stackoverflow.com/tags/x86/info where I've already covered various common pitfalls that people often post questions about. By far the most important skill is using a debugger like GDB to single-step and watch registers / memory change. With that and an instruction set reference, you're all set to figure out how / why anything else works. (And `strace ./my_program` to trace system calls and make sure you got the args right.) – Peter Cordes Apr 29 '20 at 08:07