• 157阅读
  • 0回复

任鸟飞谈逆向----逆向基础之堆栈详解 [复制链接]

上一主题 下一主题
在线任鸟飞
 


堆栈一直是新手学习逆向的第一个大难点
那么我们今天就来详细的讲解一下堆栈的知识

1.什么是堆栈?
堆栈就是一种数据项按序排列的数据结构,只能在栈顶对数据项进行插入和删除,其他的位置只能改变数值
特点是先进后出  (像是一个杯子)
例如以下代码
push  1
push  2
push  3
push  4
pop   eax
pop   ecx
pop   ebx
pop   edx
最后 eax=4  ecx=3 ebx=2 edx=1


2.堆栈指针寄存器
ESP  栈顶指针  永远指向栈顶
EBP  栈底指针,这里所谓的栈底是本层函数的栈底,而不是整个堆栈的栈底,更直观的作用是为了能够在CALL直接结束的时候,顺利的返回调用的位置。当然他并不是像ESP那样永远的指向栈底,而是有一些情况当成普通寄存器来使用,这里要值得注意,在用到ebp的时候要学会分辨是否是栈底指针还是普通寄存器使用,方法很简单,我们时候ESP是永远指向栈顶的,那么只要看EBP和ESP相差是否接近就可以了,因为栈顶和栈底不会相差巨大。


3.改变堆栈的指令
PUSH EAX    等价于  sub esp,4    mov [esp],eax
POP  eax   等价于   mov eax,[esp]    add esp,4
call 1234 等价于    push eip   jmp 1234
retn 8  等价于   POP eip   ADD ESP,8
add esp,xxx
sub esp,xxx

我们发现以上指令多对ESP进行了改变,那么就是对堆栈进行了改变


4 堆栈中储存的都是参数,局部变量和操作中间数
那么我们怎么去找他的来源呢?
例如 追数据追到[EBP-4] , [EBP+8] ,  [ESP+20]
他们的来源怎么追呢?
首先他们是堆栈中的一个成员,要整体去追,而-4,+8,+20并不是偏移
这和mov ecx,[eax+20]  这种是不相同的。 要区分开

①.通过EBP  来传递参数 和局部变量
一般函数具有以下特征
push    ebp
mov     ebp, esp
...
...
mov     esp, ebp
pop     ebp


在进入CALL的时候我们观察堆栈 ,如果观察力不强的话可以在进入CALL的时候F7单步观察堆栈,发现如下特点
。。。
[ebp-8]  第二个局部变量
[ebp-4]  第一个局部变量
[ebp]    保存上一层的EBP值
[ebp+4]  CALL返回
[ebp+8]  第一参数
[ebp+C]  第二个参数
。。。
例如上面提到的
[EBP-4] 局部变量, [EBP+8]  上一层第一个参数
我们直接就可以锁定要追踪的位置了



②.通过ESP  来传递参数 和局部变量

头部没有 push    ebp
mov     ebp, esp  这样的代码   往往是用ESP来表示
SUB esp,xxxx开辟局部变量

算到头部 如果是[esp+] 那么是参数
如果是[esp-] 那么是局部变量 是在本层找来源
原因很简单,esp已经是堆栈顶端了,哪还来的- ,一定是本层产生的,那么一定是局部变量了
但是不用全部计算   往往一个call 都是自身堆栈平衡的
我们往往只需要计算 头部的一些堆栈处理    中间完整的CALL  可以看成平衡体

更简单的方法是  直接断下看堆栈  看看这个堆栈指针 指向的位置是  上一层返回到的上面还是下面




局部变量本层找不到来源的时候
只有一种情况,那么就是本层CALL赋值的情况  
本层内部CALL想要修改局部变量的值 就必须有变量指针作为参数传递进CALL,才能修改变量的值

举例如下:

lea ecx,[esp+10]
push  ecx
push  eax
call  XXXX
mov eax,[esp+10]
参数二  就是局部变量指针,在这个CALL内部可以对局部变量进行赋值

1条评分小风币+5
啊冲 小风币 +5 - 04-23
快速回复
限100 字节
批量上传需要先选择文件,再选择上传
 
上一个 下一个