In the previous article (http://www.bkjia.com/Article/201307/224727.html), the output of the last piece of code is shown in (1:
Figure (1)
For analysis, why is there such a result?
Figure (2)
Figure 2 state diagram of function stack Frames
Explanation:
1. The addresses of parameters c, B, And a are 0X0012FF24, 0X0012FF20, and 0X0012FF1C, respectively. There is a difference of 4 between two adjacent addresses, because in win32, int storage occupies four bytes.
2 because ret is the returned address and ebp is the pointer, both occupy four bytes. Therefore, the first address of the storage unit for ret storage is 0x0012FF18, and the first address of the storage unit for ebp is 0x0012FF14. Because the buffer array space is four bytes, the value of buffer1 should be 0x0012FF10, consistent with the value of buffer1 output by the program.
3 Why buffer2 array only five bytes, according to the direction of stack growth, buffer2 = bufeer1-5 = 0X0012FF0B, while the program output is 0X0012FF08 it.
This is because the allocated space is allocated by words (as mentioned above). One word in win32 is four bytes, while buffer5 is five bytes, because eight bytes are allocated (memory alignment ), so buffer2 = buffer1-8 = 0X0012FF08, the calculation result is consistent with the program output result.
The returned address RET is the return address after the function is called, that is, the address of the command to be executed after the function is called. The verification code is as follows:
# Include <stdio. h> void fun () {char buffer [4]; unsigned * p = (unsigned *) (buffer + 8 ); /* define an unsigned pointer pointing to RET */printf ("this is a fun \ n"); printf ("the return address is: 0X % 08x", * p ); /* calculate the RET value in hexadecimal notation */} void main () {fun (); printf ("\ n **************** \ n ");}
Buffer: 4 bytes |
EBP: 4 bytes |
RET: 4 bytes |
Figure (3) RET
The program runs as follows:
The returned RET value is 0X: 0040108D;
We can add a breakpoint before the printf (); Statement and decompile it to get the address of the pritnf () command:
We can find that the output return address is consistent with the instruction address of the first action of printf.
Therefore, the return process after function call is as follows:
1. Save the return value: Generally, the return value of the function is stored in the register eax.
2. The current stack frame is displayed and the previous stack frame is restored.
A) On the basis of stack balancing, add the size of the stack frame to ESP, reduce the stack top, and reclaim the space of the current stack frame.
B) Let's talk about the value of EBP at the bottom of the current stack frame (the address of the base stack of the primary function) to pop into the EBP register, so that ebp points to the base of the primary function stack.
C) load the return address of the function into the EIP register.
3. Jump to the new EIP and execute the command (the master function has been returned ).
Original article: http://niuyuanwu.blog.51cto.com/6732782/1236089