Skip to content

The stack & function calls

2.2 The stack & function calls (x86-64 SysV)

When a function foo() is called, roughly this happens:

  1. Caller pushes arguments (in registers like RDI, RSI, RDX… first, but also stack for extra).
  2. call foo pushes the return address (address of instruction after call) onto the stack and jumps to foo.
  3. Inside foo, the prologue usually:
    push rbp       ; save old base pointer
    mov rbp, rsp   ; set new base pointer
    sub rsp, X     ; reserve space for local variables
    
  4. Local variables are stored below rbp on the stack.
  5. When foo returns, epilogue:
    leave          ; mov rsp, rbp ; pop rbp
    ret            ; pops return address into RIP
    

On x86–64, there are a few key registers:

  • RIP: the Register Instruction Pointer – it tells the CPU which instruction to execute next.
  • RSP: the Register Stack Pointer – it points to the top of the stack.
  • RBP: the Register Base Pointer – it’s a fixed reference point used to access local variables.

The crucial idea is this:

[!important] If you can overwrite the saved return address on the stack, you can control where the ret instruction sends the program next. That means you control RIP, the instruction pointer.

This is the heart of many classic exploits.