滴水逆向三期—堆栈图
什么叫逆向?
比如说有一块内存,内存里面存储的就是数据,那我们所谓的逆向就是来分析这个数据到底是什么
堆栈图:
比如给个地址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 位区别