【逆向】第九章 堆栈图

案例

打开OD,点option,debuging options,选中winmain,打开

找指令

选中一条,鼠标左键点一下,ctrl+G,把地址输入进去,点OK在这里插入图片描述
然后就可以定位了,这时候不能按F8,因为CPU还没有跑到这一行
用鼠标左键点一下,F2下断点,CPU还在程序打开OD那,点播放键到这个断点位

画堆栈

这个时候画堆栈图要关注ESP和EBP
在这里插入图片描述

画出初始的堆栈图,如下图所示,黄色代表的是初始堆栈,而ESP和EBP之间还有很多内存地址,这里用一块来表示
在这里插入图片描述
按下F8
在这里插入图片描述
栈底没有变化,但是栈顶变化了,如图为执行push 2后的堆栈图在这里插入图片描述
再往下F8,执行了push 1,而ESP减4在这里插入图片描述
这个时候不能按下F8,,按下以后程序就执行完了
在这里插入图片描述
这个时候,我们按下F7

call指令相当于 mov dword ptr ds:[esp-4],[eip + 当前call指令字节数]
在这里插入图片描述
执行后如下:
在这里插入图片描述
jmp指令不影响堆栈图,直接按下enter
在这里插入图片描述
此时如图
在这里插入图片描述
下一个指令,EBP变化,变成ESP
在这里插入图片描述
。。。(此处写错了,是EBP=ESP)
下一步在这里插入图片描述
此处,深蓝色的区域为缓冲区,这一块空间是给程序执行内存,缓冲区大小不确定,但是肯定比程序需要多一些,编译器对缓冲区设置不一样
如图为这一步OD实验结果
在这里插入图片描述
PUSH ebx、 push ESI、 push EDI,保存现场:执行另一个程序时,把这些寄存器的值保存下来,等那个程序执行完后再拿出来
在这里插入图片描述
其他两行也是一样的道理在这里插入图片描述
lea edi,dword ptr ss:[EBP-40],取地址操作,之前ESP也减过40在这里插入图片描述
此时堆栈图无变化
前面有mov ecx,10
mov eax,CCCCCCCC
下一步rep stos dword ptr es:[edi]
将eax的值传给EDI这个地址指向的内存,此时EDI自动加4或者减4,看DF位,D位为0加,D位为1减
重复执行16次,执行一次ecx减1,往EDI里存一个CCCCCCCC,ecx减到0时就停止
在这里插入图片描述
如图为执行一次后的堆栈图,此时ECX=F,EDI+4(往下移)
执行完后如图在这里插入图片描述
用CCCCCCCC填满缓冲区,防止缓冲区溢出,未填满前缓冲区不是0,是一堆垃圾数据
如果写递归时,截止条件没有写好会导致栈溢出

mov eax,dword ptr ss:[EBP+8]
此时EBP+4是函数的返回地址,如上图
之前push两个值,就是这个函数的参数,因为这个程序要用到这两个值,这个程序就叫函数
此时EBP+8就用这个参数,不会改变栈底栈顶,也就是把ebp+8的值,就是之前的push 1,即1,放到eax里面

add eax,dword ptr ss:[EBP+C]
即之前的push 2 此处就执行的是1+2,此时,函数的功能已经完成,实际上真正干活的就这两行。
在这里插入图片描述
pop edi,pop esi ,pop ebx ,这三个寄存器的值都在栈顶,把他们依次打出来,刚好保存到对应的寄存器:恢复现场,但是这三个数还在内存,所以这就是垃圾数据
在这里插入图片描述
mov ebp,esp
在这里插入图片描述
此时,叫恢复堆栈

pop ebp
此时ebp就是最开始的那个在这里插入图片描述
RETN:相当于pop,eip
在这里插入图片描述
此时eip是返回地址,这个地址是必争之地
回到之前在这里插入图片描述
上图的call就是函数的调用,此时2和1就是参数,此时和调用前的堆栈图进行对比在这里插入图片描述
此时,两边堆栈不一样
堆栈平衡:调用一个函数之前,和调用一个函数之后,它的堆栈应该是一样的,是没有变化的,栈顶指针和栈底指针应该一样
我们看上面的OD图,下面还有一个add esp,8,就是让esp+8在这里插入图片描述
此时平衡,在函数执行完后平衡堆栈,这种堆栈平衡叫外平栈,即谁调用函数,谁平衡堆栈

海哥的总结

堆栈作用在这里插入图片描述

函数

在这里插入图片描述
传参数不一定通过堆栈,也可以通过寄存器
在这里插入图片描述
返回值我们可以存入寄存器,也可以通过内存,eax值叫做返回值,一个函数可以没有参数也没有返回值

3性质

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46441427/article/details/112851398
今日推荐