Common

1. Function calls

General overview of steps

  1. Push function (to call) arguments to the stack

  2. Load function address in the EIP

  • Save current EIP before updating it to point to new function address

  1. Move EBP to the top of new stack frame

  • Save current EBP before updating it to point to current value in ESP

  1. Allocate space for the new stack frame

  • Move ESP down (to lower address)

  1. Execute function

  2. Erase the stack frame used by the function

  • Increment ESP to point to the top of the stack frame (EBP)

  1. Restore EBP

  2. Restore EIP

  • Return from function

  1. Remove arguments from stack

  • Increment ESP

Following the steps outlined in the textbook above regarding function calls, I will list out the corresponding x86 (32-bit) assembly codes.

Important!!

Note that for this example, we will draw the memory layout with the highest address at the top, while the lower addresses appear at the bottom visually. However, the EBP and ESP will still point to the higher and lower addresses of the stack frame respectively.

This means that the EBP will point to the "top" of the stack frame, while the ESP will point to the "bottom"

1.1 Push arguments on the stack

Remember that x86 passes arguments by pushing them onto the stack

push arg1 ; push first arg1 to stack
push arg2 ; push second arg2 to stack
  • As we can see from the stack content after the instruction, arg2 is pushed first before arg1. This is because arguments are pushed onto the stack in reverse order

1.2 Call the function

  • This step can be broken down into 2 separate assembly commands: push and jmp

1.2.1 Push the old EIP on the stack

  • Since the value in the EIP register will be changed to point to the function address, we need to save its current value onto the stack before we overwrite it with a new value

push eip

1.2.2 jmp to the function address

jmp <func_addr>

State of the memory AFTER instruction

The above jmp instruction simply points the EIP to the address given as argument. In this case, it will be the address of the "test" function.

1.3 Save current EBP value, before updating to point to new stack frame

  • This step can be broken down into 2 steps, first we push the EBP to the stack, before copying the value of the current ESP to the EBP

1.3.1 Push current EBP to stack

push ebp

1.3.2 Copy value of ESP to EBP

mov ebp, esp

Now, the EBP will point to the same address referenced by the ESP :

This will allow the EBP to point to the bottom (or top if seen visually from this diagram — remember the drawing convention in this example) of the (higher address) of the new stack frame of the "test" function.

1.4 Allocate new space for the new stack

  • This is performed by growing the stack (moving the ESP to the lower address). The compiler will decide how far the ESP should be decremented, based on the complexity of the function to be called. In this example, we will assume the ESP is decremented by 8 bytes:

sub esp, 0x8

1.5 Execute the function

  • Now, any local variables and any other necessary data can be saved in the new stack frame

  • The EBP (pointing to the top of the stack frame) can be used as a point of reference to find other variables on the stack

1.6 Erase the stack frame used by the function

  • After the function is complete, the variables will be erased/removed by incrementing the ESP to point to the value stored in the EBP

mov esp, ebp

Note that the local variables are actually still present physically on the stack. However, it is treated as "removed" due to the position of the ESP

1.7 Restore value of the old EBP

pop ebp
  • This instruction restores the value of the EBP to point to the stack frame before the function call ("main")

  • The ESP will also be incremented to remove the stored EBP value from the stack

1.8 Return from function

This step can be broken down into 2 separate assembly commands: pop and jmp

1.8.1 Pop stored value of EIP

pop eip
  • This restores the value of the EIP of the calling function

1.8.2 jmp back to the calling function

jmp <func_addr>

1.9 Remove arguments from the stack

add esp, 0x8

Last updated