画堆栈图1

滴水逆向三期—堆栈

什么叫逆向?
比如说有一块内存,内存里面存储的就是数据,那我们所谓的逆向就是来分析这个数据到底是什么
堆栈图:
比如给个地址0x401168
打开DTDebug:在这里插入图片描述
ctrl+g 将地址打上后 ok:
在这里插入图片描述
看到定位到了这个位置,从这个位置开始画堆栈图,不能直接按F8因为cpu还没有走到这里,我们在这个位置先按F2(让cpu走到这个位置停下来),先让程序走到这里,然后就可以开始画堆栈图了,画堆栈图之前应该记录现在的堆栈是什么样子的,需要看ESP和EBP这两个寄存器,一个栈顶一个栈底
在这里插入图片描述
这个黄色就代表了,在我们调用之前,你原始的堆栈就是这样的,这里面的数据是在我的程序在执行之前就已经被占用的了
在这里插入图片描述
按一下F8单步执行,发现现在栈顶是30,栈底是80,发现栈底没有变化而栈顶发生了变化
在这里插入图片描述
在这里插入图片描述
在堆栈的窗口可以看到ESP的值减了4,push2一运行完事的时候,发现2的值已经写在了堆栈里面,我们把这个过程叫做压栈
在这里插入图片描述
这是我们第一步执行完事看到的堆栈图
再次F8:
在这里插入图片描述
在这里插入图片描述
再回来看在这里插入图片描述
走到这一行的时候不能再按F8了,如果按的话,就直接跑到下一行了,整个程序就都执行完了,就看不到堆栈的变化了,我们现在画的堆栈图就是再画当前这段程序的堆栈图,所以在这里我们要按F7,CALL函数最后肯定会对应一个ret,CALL这个函数不光是修改EIP的值,还会这行指令后面的地址给他压到栈里面,地址怎么知道多少,当前EIP+指令长度
在这里插入图片描述
F7:
在这里插入图片描述
发现ESP分析的一样 -4变成了28 堆栈的值也是正确的,当我们再提函数的返回地址,说的就是CALL调用的时候,他往栈里面压的值,我们称为函数的返回地址
然后我们看到JMP指令,JMP是不影响堆栈的,JMP指令是跳转,所以直接回车就可以了
在这里插入图片描述
回车后,我们可以看到ESP EBP的值没有变化,因为JMP就相当于mov值到EIP 所以EIP的值变了
在这里插入图片描述
F8:
在这里插入图片描述
可以看到跟刚才堆栈图的时候想的一样 ESP变化,堆栈里面的值变了也就是当前EBP的值存入其中了
在这里插入图片描述
看一下mov EBP,ESP 是EBP变了,变成了ESP的值,本质的意义就是EBP栈底提高了
在这里插入图片描述
在这里插入图片描述
可以看到EBP变成了和ESP一样的值
然后看SUN ESP,40 SUB是- 就是ESP- 4 0个
在这里插入图片描述
SUB ESP,40 这里的40是16进制的,所以要上升16个格
缓冲区的概念:任何一段程序在执行都需要一点空间,不给我一块内存怎么执行,所以需要一块空间叫做缓冲区,缓冲区的大小时不确定的,他会根据你需要的多少来分
在这里插入图片描述
看见ESP变成了EE4
在这里插入图片描述
在这里插入图片描述

PUSH EBX
为什么程序要这么设计:因为你让CPU干活,让他去执行一段功能,我们需要给他分一块内存,所以上面为什么有一条SUB ESP,40这个原因,为什么还有一堆PUSH EBX ESI EDI这些东西,我们要执行一段程序,如果说我们现在在玩游戏,一共30关现在玩到了29关,现在突然想起来我要去吃饭,吃饭就相当于我要执行另外一段程序,如果你吃完饭回来发现你要从第一关开始你干不干,所以一样的道理,所以这些寄存器一共就这些个,在我们用之前是不是我们需要把他保留起来,等我们执行完了,我们再还原回来,所以PUSH 那三个寄存器的步骤我们可以理解为保存现场,寄存器里面存的值保存在哪里去,我们再编程的时候,就两个地方可以保存进去,一个是寄存器,一个是内存,那保存到哪个内存里面,那么正好是我们现在用的堆栈
在这里插入图片描述
PUSH ESI EDI 后的堆栈图,这样我们就把ESI EDI EBX的值压到了栈里面
在这里插入图片描述
可以看到分析的是正确的
在这里插入图片描述
LEA是取地址编号的 取EBP-40这块的地址编号然后放到EDI里面
在这里插入图片描述
在这里插入图片描述
可以看到堆栈的那个寄存器没有变化,说明LEA这个对堆栈来说没有变化,只改变了EDI的值
看到后面的那个SOTS的作用是将EAX的值辅给EDI这个地址编号指向的内存 这个里面的EDI会自动加4或者减4 由D位决定的,D位为0就是加 REP是重复执行,执行ECX的值16次(10是16进制)这三个MOV ECX,10 MOV EAX,CCCCCCCC REP STOS DWORD PTR SS:[EDI]指令的意思就是,每次都把EAX的一串C放到EDI这个内存地址,指向后EDI的值会自动加4,加4后ECX会自动减1
CC相当于int 3 相当于断点 防止缓冲区溢出
记住10 完事是F 不是9 因为是16进制的
在这里插入图片描述
只有这一串都变成了CC
在这里插入图片描述
观察,在这里面来看,存入CC数据之前,这里面的数据都有值,这里面的数据我们都可以看为是垃圾数据,可以想成是上个函数对此的遗留数据
在这里插入图片描述
F8后看到这里面的数据都变成了CC

MOV EAX,DWORD PTR SS:[EBP+8]
参数,我们在调用前用了两个push,因为我们这个程序要用到这两个值,所以我们把这两个值叫做参数,我们这段程序有个名字叫做函数,函数就是一段程序,要实行一段东西,在CALL执行前,这个参数就已经放到堆栈里面了,没有改变堆栈的栈顶和栈底
ADD EAX,DWORD PTR SS:[EBP+C]
EAX变成了3:1+2
在这里插入图片描述
可以看到EAX的值变成了3

POP EDI ESI EBX POP就是把栈顶的值放进寄存器里 (恢复现场)
在这里插入图片描述
在这里插入图片描述
可以看到变成了E4 我们把这个叫做恢复现场
函数执行完在堆栈里面的值就不要了,所以就会产生数据垃圾
在这里插入图片描述
在这里插入图片描述
可以看到那些CC的值根本没有管你的,就直接在那里放着,观察栈顶和栈底的时候发现,都变成了一样的值,过程叫恢复堆栈,程序执行完事需要恢复
在这里插入图片描述
在这里插入图片描述
恢复了原来的栈底
RETN:pop eip
在这里插入图片描述
在这里插入图片描述
这个地址相当于返回的地址

堆栈平衡:调用函数之前和调用函数之后你的堆栈应该是一样的,是没有变化的,我们叫做堆栈平衡
在这里插入图片描述
ADD ESP,8 我们在外面维持了堆栈平衡,我们把这个叫做外平栈

逆向并还原为C代码
插图一张,cf 位与of 位区别
插图一张




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值