逆向学习 堆栈图

逆向代码

跟着视频学的,这里的例子并没有提供正向代码不过很简单不影响,重点是为了理解堆栈。

0040118E    |.  6A 09                    PUSH 9
00401190    |.  6A 0C                    PUSH 0C
00401192    |.  6A 05                    PUSH 5
00401194    |.  E8 85FEFFFF              CALL HelloWor.0040101E
00401199    |.  83C4 0C                  ADD ESP,0C

00401100    /> \55                       PUSH EBP
00401101    |.  8BEC                     MOV EBP,ESP
00401103    |.  83EC 40                  SUB ESP,40
00401106    |.  53                       PUSH EBX
00401107    |.  56                       PUSH ESI
00401108    |.  57                       PUSH EDI
00401109    |.  8D7D C0                  LEA EDI,DWORD PTR SS:[EBP-40]
0040110C    |.  B9 10000000              MOV ECX,10
00401111    |.  B8 CCCCCCCC              MOV EAX,CCCCCCCC
00401116    |.  F3:AB                    REP STOS DWORD PTR ES:[EDI]
00401118    |.  8B45 08                  MOV EAX,DWORD PTR SS:[EBP+8]     
0040111B    |.  3B45 0C                  CMP EAX,DWORD PTR SS:[EBP+C]  
0040111E    |.  7E 12                    JLE SHORT HelloWor.00401132
00401120    |.  8B4D 08                  MOV ECX,DWORD PTR SS:[EBP+8] 
00401123    |.  3B4D 10                  CMP ECX,DWORD PTR SS:[EBP+10]
00401126    |.  7E 05                    JLE SHORT HelloWor.0040112D
00401128    |.  8B45 08                  MOV EAX,DWORD PTR SS:[EBP+8]
0040112B    |.  EB 15                    JMP SHORT HelloWor.00401142
0040112D    |>  8B45 10                  MOV EAX,DWORD PTR SS:[EBP+10]
00401130    |.  EB 10                    JMP SHORT HelloWor.00401142
00401132    |>  8B55 0C                  MOV EDX,DWORD PTR SS:[EBP+C]
00401135    |.  3B55 10                  CMP EDX,DWORD PTR SS:[EBP+10]
00401138    |.  7E 05                    JLE SHORT HelloWor.0040113F
0040113A    |.  8B45 0C                  MOV EAX,DWORD PTR SS:[EBP+C]
0040113D    |.  EB 03                    JMP SHORT HelloWor.00401142
0040113F    |>  8B45 10                  MOV EAX,DWORD PTR SS:[EBP+10]
00401142    |>  5F                       POP EDI
00401143    |.  5E                       POP ESI
00401144    |.  5B                       POP EBX
00401145    |.  8BE5                     MOV ESP,EBP
00401147    |.  5D                       POP EBP
00401148    \.  C3                       RETN

分析

原始ESP 0019FEF4
EBP 0019FF40
EBP作栈底,ESP为栈顶
①在传参之前有个ADD ESP,8 是保持原始的堆栈(上层传入两个参数)

②传参 c中参数在前的后push 顺序相反

push 9
push 0C
PUSH 5

实际为int 5, int 0c, int 9;
ESP-C = 0019FEE8

③CALL 函数
PUSH EIP
JMP
ESP-4 = 0019FEE4

④进入函数内部 PUSH EBP
ESP-4 = 0019FEE0

⑤MOV EBP,ESP
EBP = ESP = 0019FEE0
逆向学习 堆栈图_第1张图片
⑥开辟40h的空间作为函数临时内存
此时在子函数里EBP又变为当前函数栈底,ESP栈顶
SUP ESP,40
ESP-40 = 0019FEA0

⑧保留寄存器原始值 防止对原函数造成影响

PUSH EBX
PUSH ESI
PUSH EDI

ESP-C = 0019FE94

⑨初始化内存空间 防止不相干数据影响

LEA EDI,DWORD PTR SS:[EBP-40]
MOV ECX,10
MOV EAX,CCCCCCCC
REP STOS DWORD PTR ES:[EDI]
将开辟空间的栈顶值给EDI 利用STOS函数进行赋值
	STOS DWORD PTR ES:[EDI] 默认将EAX中的值赋值给EDI代表的内存中
REP ECX作为循环次数

ps:在od中可以F7步进REP EDI会自增DWORD

逆向学习 堆栈图_第2张图片

⑩函数操作
伪代码

int x = 0x5, y = 0xc, z = 0x9;
void func(int x, int y, int z)
{
	if(x < y)
		if(y < z)
			return z;
		else
			return y;
	else if(x < z)
		return z;
	else
		return x;			
}
func(a,b,c);

⑪还原寄存器值

POP EDI
POP ESI
POP EBX

ESP+C = 0019FEA0

⑫还原被调用函数栈顶

MOV ESP,EBP

ESP = EBP = 0019FEE0

⑬还原调用函数栈底

POP EBP

⑭返回调用函数

RETN

POP EIP
JMP
ESP+4 = 0019FEA8

⑮还原调用函数栈顶

ADD ESP,0C

因为传了三个参数
结束调用堆栈保持不变
逆向学习 堆栈图_第3张图片

总结

重点就是在ESP EBP每一步的含义,被调用CALL中的EBP+4 +8…是什么意思
汇编中一个完整CALL最精简的过程总结为
1 传参(与C中顺序相反,)
2 保留栈底push ebp
3 开辟空间
sub esp
mov ebp,esp
4 保护原有寄存器值
5 初始化内存
6 函数操作
7 还原寄存器
8 还原堆栈
其中在执行CALL的时候相当于PUSH EIP ,JMP
ESP先作为主函数的栈顶然后把值赋给EBP让其充当被调用的栈底说起来比较绕,务必理解图。
所以到了函数操作部分EBP作为子函数栈底(原本的ESP),EBP+4即主函数的EIP
EBP+8为子函数的第一个参数 EBP+C为第二个

你可能感兴趣的:(逆向学习 堆栈图)