游戏安全实验室 首页 游戏漏洞 查看内容

【游戏漏洞】逆向基础之堆栈详解

发布于:2018-4-13 15:58   |    59726次阅读 作者: 外部投稿    |   原作者: 通化程序员

堆栈一直是新手学习逆向的第一个大难点

那么我们今天就来详细的讲解一下堆栈的知识

 

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内部可以对局部变量进行赋值

 

 

 

 

 来源:通化程序员-公众号投稿

*转载请注明来自游戏安全实验室(GSLAB.QQ.COM)

分享到:
踩0 赞0

收藏

最新评论
B Color Image Link Quote Code Smilies

发表评论

top 问题反馈

返回顶部