Yves
Yves

Reputation: 12381

Does function stack save the return address?

I'm learning things about function stack based on assembly using the system Linux x86.

I've read some article, which told me that a function stack (callee) would save the return address where it is called by the caller so that the computer could know the point where to continue when the function returns.

This is why there is a kind of attack: stack smashing. The stack smashing means that if we can overflow a function stack, especially overflow the return address with a designed address, the program will execute the codes of hackers.

However, today I'm trying to use gdb to check a simple c++ program as below but I can't find any saved return address in any function stack. Here is the code:

void func(int x)
{
    int a = x;
    int b = 0;  // set a breakpoint
}

int main()
{
    func(10);  // set a breakpoint
    return 0;
}

Then I use gdb to get its assembly:

main:

enter image description here

func:

enter image description here

Now we can see that there is no return address being saved in the two function stacks (at least this is my view).

If a hacker wants to hack this program with stack smashing, which address in the function stack will be edited illegally by him?

Upvotes: 8

Views: 6066

Answers (2)

jfMR
jfMR

Reputation: 24768

Now we can see that there is no return address being saved in the two function stacks (at least this is my view).

What you are actually showing is the disassembled code, not the stack.

The return address is pushed on the stack by the caller by means of the callq instruction. At the moment of entering the callee function it is at the top of the stack, i.e.: at that moment, rsp contains the address where the return address is stored.


Inspecting the stack with GDB

  • p/x $rsp displays the value of the rsp register, i.e.: the address of the top of the stack, since rsp points to the top of the stack.

  • x/x $rsp displays the memory contents located at the top of stack (i.e.: the contents located at the address pointed by rsp).

With this information in mind you can run the command x/x $rsp at the moment of entering the callee function (before anything else is pushed onto the stack) to obtain the return address.

You can also use the command info frame to inspect the current stack frame. The displayed field with the name saved rip corresponds to the current function's return address. However, you need to run this command after the stack frame for the current function has been created and before it is destroyed (i.e.: after mov %rsp,%rbp but before pop %rbp inside the callee).

Upvotes: 6

David Hoelzer
David Hoelzer

Reputation: 16361

Yes there is. Examine the stack immediately before the callq and immediately after it. You will find that the address of the instruction following the callq now appears on the top of the stack and RSP has decremented by 8.

The callq instruction causes the address of the following instruction to be pushed onto the stack. Inversely, the retq instruction at the end of the function causes the address on the stack to be popped into the RIP.

Upvotes: 6

Related Questions