第22节: 什么是推栈平衡
如果要返回一个程序,则当我们在推栈中进行推栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入的栈中的地址。
怎么理解这句话呢?我们看一下错误的例子:
CALL 0041840D
0041840D MOV EAX,1
PUSH ECX
RET
以上这样的例子返回的EIP的值是0,这样的程序就会出错了,当我们执行RET的时候意味着函数结束了,那么堆栈平衡的意思是什么?指的是你这个函数执行前和执行后整个中间的这个过程堆栈是一致的,什么是一致?一致就是你往堆栈压入一个值当你的函数执行完后,你因该把堆栈恢复成原来的样子(原来一开始栈顶指针指向的地址什么样子,就恢复成什么样子)
例子:
PUSH 1
PUSH 2
CALL 004184DF
004184DF MOV EAX,DWORD PTR DS:[ESP+8]
ADD EAX,DWORD PTR DS:[ESP+4]
RET
以上的这个例子,也是没有恢复成原栈顶指针指向的地址,这个例子只是指向了最后参数的地址。如果通过堆栈传递参数了,那么在函数执行它的时候,也要平衡参数。
那如何堆栈平衡呢?看下面的例子:
什么是外平栈
例子:
PUSH 1
PUSH 2
CALL 004184DF
ADD ESP , 8
004184DF MOV EAX,DWORD PTR DS:[ESP+8]
ADD EAX,DWORD PTR DS:[ESP+4]
RET
什么是内平栈
例子:
PUSH 1
PUSH 2
CALL 004184DF
004184DF MOV EAX,DWORD PTR DS:[ESP+8]
ADD EAX,DWORD PTR DS:[ESP+4]
RET 8
如果要返回一个程序,则当我们在推栈中进行推栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入的栈中的地址。
怎么理解这句话呢?我们看一下错误的例子:
CALL 0041840D
0041840D MOV EAX,1
PUSH ECX
RET
以上这样的例子返回的EIP的值是0,这样的程序就会出错了,当我们执行RET的时候意味着函数结束了,那么堆栈平衡的意思是什么?指的是你这个函数执行前和执行后整个中间的这个过程堆栈是一致的,什么是一致?一致就是你往堆栈压入一个值当你的函数执行完后,你因该把堆栈恢复成原来的样子(原来一开始栈顶指针指向的地址什么样子,就恢复成什么样子)
例子:
PUSH 1
PUSH 2
CALL 004184DF
004184DF MOV EAX,DWORD PTR DS:[ESP+8]
ADD EAX,DWORD PTR DS:[ESP+4]
RET
以上的这个例子,也是没有恢复成原栈顶指针指向的地址,这个例子只是指向了最后参数的地址。如果通过堆栈传递参数了,那么在函数执行它的时候,也要平衡参数。
那如何堆栈平衡呢?看下面的例子:
什么是外平栈
例子:
PUSH 1
PUSH 2
CALL 004184DF
ADD ESP , 8
004184DF MOV EAX,DWORD PTR DS:[ESP+8]
ADD EAX,DWORD PTR DS:[ESP+4]
RET
什么是内平栈
例子:
PUSH 1
PUSH 2
CALL 004184DF
004184DF MOV EAX,DWORD PTR DS:[ESP+8]
ADD EAX,DWORD PTR DS:[ESP+4]
RET 8