Reputation: 12381
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
:
func
:
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
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.
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
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