- UID
- 66114
注册时间2010-4-1
阅读权限30
最后登录1970-1-1
龙战于野
TA的每日心情 | 慵懒 2019-3-12 17:25 |
---|
签到天数: 3 天 [LV.2]偶尔看看I
|
1.堆栈知识
2.c语言的函数初探
3.例子
1.堆栈知识
1.1栈是一种数据结构,有着各种操作比如(push(压栈),pop(弹栈),top(栈顶相当于汇编里的esp),base(栈底相当于汇编里的ebp),好比一摞扑克牌。
PUSH:为栈增加一个元素的操作叫做PUSH,相当于在这摞扑克牌的最上面再放上一张。
POP:从栈中取出一个元素的操作叫做POP,相当于从这摞扑克牌取出最上面的一张。
TOP(栈顶相当于汇编里的esp):标识栈顶位置,并且是动态变化的,栈顶元素相当于扑克牌最上面一张,只有这张牌的花色是我们当前可以看到的。
BASE(栈底相当于汇编里的ebp):标识栈底位置,它记录着扑克牌最下面一张的位置。BASE用于防止栈空后继续弹栈(牌发完时就不能再去揭牌了)。很明显,一般情况下,BASE是不会变动的。
内存的栈区实际上指的就是系统栈。系统栈由系统自动维护,它用于实现高级语言中函数的调用。对于类似C语言这样的高级语言,系统栈的PUSH、POP等堆栈平衡细节是透明的。一般说来,只有在使用汇编语言开发程序的时候,才需要和它直接打交道。举个例子:我们去饭馆里吃饭,只管点菜(push)、付钱(esp)、你有多少钱(ebp)、吃饭(pop),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
请看图用od载入记事本后的栈图:
然后我push(压栈)一次再看图:
如果不明白的话就跟帖询问吧。
1.2 堆------留着以后学习
2.c语言的函数初探- int function1(int a,int b){
- return (a+b);
- }
- int function(int a,int b){
- return function1(a,b);
- }
- int main(int argc, char* argv[])
- {
- int i=1,j=0;
- function(i,j);
- return 0;
- }
复制代码 函数调用顺序是 main()---->function--->function1,下面看看汇编,他们是怎么传的参数(也就是栈操作),还有函数顺序如何改变。
15: int main(int argc, char* argv[])<------main()主函数
16: {
004010B0 push ebp
004010B1 mov ebp,esp
004010B3 sub esp,48h
004010B6 push ebx
004010B7 push esi
004010B8 push edi
004010B9 lea edi,[ebp-48h]
004010BC mov ecx,12h
004010C1 mov eax,0CCCCCCCCh
004010C6 rep stos dword ptr [edi]
17:
18: int i=1,j=0;
004010C8 mov dword ptr [ebp-4],1
004010CF mov dword ptr [ebp-8],0
19:
20:
21: function(i,j);
004010D6 mov eax,dword ptr [ebp-8]
004010D9 push eax <------------- 参数0
004010DA mov ecx,dword ptr [ebp-4]
004010DD push ecx <------------- 参数1
004010DE call @ILT+10(function) (0040100f)<------ 调用函数function
004010E3 add esp,8
现在我们看看function调用前堆栈的情况:
EAX = 00000000 EBX = 7FFDF000
ECX = 00000001 EDX = 003811A8
ESI = 00000000 EDI = 0012FF80
EIP = 004010DE ESP = 0012FF24
EBP = 0012FF80 EFL = 00000212
22:
23:
24:
25: return 0;
004010E6 xor eax,eax
26: }
004010E8 pop edi
004010E9 pop esi
004010EA pop ebx
004010EB add esp,48h
004010EE cmp ebp,esp
004010F0 call __chkesp (00401200)
004010F5 mov esp,ebp
004010F7 pop ebp
004010F8 ret
我们进入函数function后堆栈情况:
EAX = 00000000 EBX = 7FFDF000
ECX = 00000001 EDX = 003811A8
ESI = 00000000 EDI = 0012FF80
EIP = 00401070 ESP = 0012FF20
EBP = 0012FF80 EFL = 00000212
10: int function(int a,int b){
00401070 push ebp
00401071 mov ebp,esp
00401073 sub esp,40h
00401076 push ebx
00401077 push esi
00401078 push edi
00401079 lea edi,[ebp-40h]
0040107C mov ecx,10h
00401081 mov eax,0CCCCCCCCh
00401086 rep stos dword ptr [edi]
11:
我们进入函数function1前堆栈情况:
EAX = 00000000 EBX = 7FFDF000
ECX = 00000001 EDX = 003811A8
ESI = 00000000 EDI = 0012FF1C
EIP = 00401020 ESP = 0012FEC4
EBP = 0012FF1C EFL = 00000202
12: return function1(a,b);
00401088 mov eax,dword ptr [ebp+0Ch]
0040108B push eax
0040108C mov ecx,dword ptr [ebp+8]
0040108F push ecx
00401090 call @ILT+15(function) (00401014)
00401095 add esp,8
13: }
00401098 pop edi
00401099 pop esi
0040109A pop ebx
0040109B add esp,40h
0040109E cmp ebp,esp
004010A0 call __chkesp (00401200)
004010A5 mov esp,ebp
004010A7 pop ebp
004010A8 ret
我们进入函数function1后堆栈情况:
EAX = 00000000 EBX = 7FFDF000
ECX = 00000001 EDX = 003811A8
ESI = 00000000 EDI = 0012FF1C
EIP = 00401020 ESP = 0012FEC4
EBP = 0012FF1C EFL = 00000202
7: int function1(int a,int b){
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,40h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-40h]
0040102C mov ecx,10h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
8: return (a+b);
00401038 mov eax,dword ptr [ebp+8]
0040103B add eax,dword ptr [ebp+0Ch]
9: }
0040103E pop edi
0040103F pop esi
00401040 pop ebx
00401041 mov esp,ebp
00401043 pop ebp
00401044 ret <----------我们单步走到这里,然后观察堆栈情况:
EAX = 00000001 EBX = 7FFDE000
ECX = 00000000 EDX = 003811A8
ESI = 00000009 EDI = 0012FF1C
EIP = 00401044 ESP = 0012FEC4
EBP = 0012FF1C EFL = 00000202
现在我们想返回main()函数内应开怎么办呢?
答案就是更改esp;因为ret等于pop IP.
吧esp的内容改成004010E3
004010DE call @ILT+10(function) (0040100f)
004010E3 add esp,8
好了看看效果。
等一下再改一下这里把esp改成00000000
在看图:
好了如果把esp的内容改成我们所希望执行的代码,\(^o^)/~!!!!
最后大家看的头都晕了,楼主你在说什么呀?
我发个整体流程的图:
修改esp内容后,的流程图
3.例子- #include "string.h"
- void function(char *str){
- char buffer[10];
- strcpy(buffer,str);
- }
- int main(int argc, char* argv[])
- {
- char large_str[]={"abcdefghijklmnoprstu"};
- function(large_str);//有问题的函数
- return 0;
- }
复制代码 编译运行后出现提示如图:
论坛中缓冲区溢出蚊帐比较少,还请各位大侠指教,未完待续。
[ 本帖最后由 whypro 于 2010-5-12 09:48 编辑 ] |
评分
-
查看全部评分
|