堆栈的性质
假如有以下需求
1.主要存储一些数据,如果数量少就放入寄存器
2.能够记录有多少个数据
3.能够非常快速找到数据
如图
windows利用这种结构存储的时候,会往小地址方向移动
对于2需求,只需要用base减去top即可
用base加上一个便宜就是地址,如图,B地址就是base - 5,也可以表示成top+1
可以存很多数据,我们也知道存了多少的数据,也方便读写数据
掌握两种读数据方法,可能有的RE会从top寻址
删除数据,top减去删去的个数,即可以删除
模拟堆栈
压入数据
base叫栈底,top叫栈顶
mov EBX,12FFE0//base
mov EDX,12FFE0//top
这个时候没有存数据,base和top的值一样,从现在开始,栈底不变,存值的时候top往上偏移
然后再存四个字节
mov dword ptr ds:[edx-4],0x12345678
sub edx,4
存数进去,然后top-4
或者
lea edx,dword ptr ds:[edx-4]
mov dword ptr ds:[edx],0x23456789
或者
mov dword ptr DS:[edx-4],0x3456789A
sub edx,4
读数据
mov esi,dword ptr ds:[ebx-8]
只把值取出来,对于栈底和栈顶的值不改变
或者用顶来取
mov esi,dword ptr ds:[edx+4]
删除数据
mov eax dword ptr ds:[edx]
add edx,4
或者
lea edx dword ptr ds:[edx+4]
mov edx dword ptr ds:[edx-4]
或者
mov ecx dword ptr ds:[edx]
lea edx dword ptr ds:[edx+4]
操作系统和CPU达成某种协议,CPU给操作系统留下两个寄存器,平时存啥都行,但是到关键时候(用堆栈的时候),一个用来存栈顶,一个存栈底。
EBP通常是栈底,ESP是栈顶
栈堆指令
写入指令
push指令,把一个值写入ESP-4的地址
push 0x12345678
就是上面我们模拟的写入过程
读出数值
就是我们刚刚模拟的,那些指令,可以用EBP-,可以用ESP+
弹出数据
pop指令,把当前ESP的值弹出到一个寄存器或者内存
pop eax
tips:模拟push esp的时候,只能先写值再偏移
一些补充
如果push后面跟一个立即数,输入push ax,esp上面只减去2,不能push8位内存
push一个内存DWORD是ESP减去4,push一个word是减去2
pop同理
pushad指令
把八个通用寄存器EAX等存入堆栈,EAX存入高编号
popad指令
把8个堆栈里的值存入八个通用寄存器,高编号的存EAX