Don't like this style? Click here to change it! blue.css

LOGIN:
Welcome .... Click here to logout

Calling Conventions cont.: Parameters

Of course when you call a function you want to pass arguments too, right?

So let's look at how that works in the 2 different paradigms:

The first 6 parameters in a 64-bit program

This is actually pretty easy.

If your function needs arguments it knows to find them in the registers

  1. RDI holds arg1
  2. RSI holds arg2
  3. RDX holds arg3
  4. RCX holds arg4
  5. R8 holds arg5
  6. R9 holds arg6

That's it. I don't even really memorize these, just remember that it's registers and google/wikipedia until I find the list. OK maybe I know the first 3 by memory, RDI, RSI, RDX isn't so hard to just know.

If you have more than 6 arguments then they are stored in the stack just like the 32-bit case (coming next).

Step through this 64-bit binary: addme

Parameters in the 32-bit case

In the 32-bit case (or 64-bit for arguments over 6) it checks the stack:

  1. arg1 is at [rbp + 8]
  2. arg2 is at [rbp + 12] (or just after arg1)
  3. etc.

So if you imagine the stack, the arguments live TO THE RIGHT OF the return address.

In practice that means that the calling convention looks like this:

  1. push arg3
  2. push arg2
  3. push arg1
  4. call .somefunc
  5. pop rbx (or some other temp location)
  6. pop rbx (or whatever register)
  7. pop rbx (just cleaning the stack up)

Let's play

Now to make 32-bit binaries you'll want to do some installing:

Make a 32-bit binary: install apt-get install gcc-multilib then add the -m32 flag to your compilation: gcc -m32 -o bin_name source_code.c

OK let's make programs with parameters that call each other and trace what happens and make predictions and such.

Step through this 32-bit binary: addme32

Some Other Conventions: command line, syscalls, and sigint

I won't dive into these just yet but you should just be aware that a couple other calling conventions exist out there for other situations.

Command Line Arguments

These are passed in the stack but offset by a little, so inspect and test. This is just for main.

syscalls

I'm going to do a whole lecture or two on syscalls, but for now you can summarize it like this: anything that is operating system/kernel level you do through a syscall. That is, access to the filesystem, making new memory segments, starting/stopping processes, etc.

The syscall is it's own instruction that uses the rax register to dictate what type of syscall you're doing and the other registers hold the other params.

In the 32-bit case it's the interrupt instruction int 0x80 then a similar structure.

sigint

When there is an interrupt sometimes the entire register set is stored on the stack to let you resume after calling the error handler or what have you. We will exploit this later (it's called SROP).

Practice (Mastery B and C):

Here are some calling convention and reversing examples: