内存破坏之——栈内存
来源:互联网 发布:手机隐形录音软件 编辑:程序博客网 时间:2024/05/03 10:56
本文结合Mario Hewardt和Daniel Pravat写的《Advanced Windows Debugging》第五章所讲的内容稍微进行整合总结而成。
1、 栈简介
堆栈(英语:stack),也可直接称栈。台湾作堆叠,在计算机科学中,是一种特殊的串行形式的数据结构,它的特殊之处在于只能允许在链结串行或阵列的一端(称为堆栈顶端指标,英语:top)进行加入资料(英语:push)和输出资料(英语:pop)的运算[1]。
栈内存则是在计算机中具有上述属性的动态内存区域,程序可以将数据压入栈中,也可以将数据从栈中弹出,在I386的机器中,栈顶位置由寄存器ESP进行定位。
2、 栈内存破坏情形
2.1 栈溢出
很简单的一个操作:
tcscpy(pDest, pSource);
上述操作对于编程人员来说是正常不过的事情,一般的字符串拷贝过程,但是如果放在下面这个例子(也可以参考书中第五章overrun的例子)中,则有可能会造成栈溢出的情况。
如果输入的参数字符串长度小于10,该程序则会正常执行,但是如果输入一个长度大于10的字符串,则会出现程序崩溃的情况,而这种情况则是由栈溢出造成的。
在Windbg中执行程序,并输入一个较长长度的字符串。会发现Windbg直接给出一个STATUS_STACK_BUFFER_OVERRUN的错误状态字。
void Fun(TCHAR *szData);int _tmain(int argc, _TCHAR* argv[]){ if(argc>1) { Fun(argv[1]); } return 0;}void Fun(TCHAR *szData){ TCHAR szStr[10]; _tcscpy(szStr, szData); // do sth else}
OK,为什么在这种情况下产生栈溢出呢,参考文章函数调用过程堆栈变化分析可以知道局部变量时存放在栈中,而在上述执行字符串拷贝的操作时,是对栈内存进行拷贝,而且使用了没有分配空间的栈内存,从而出现栈溢出的错误。
2.2 使用已释放的栈内存
这种错误比较容易出现在多线程操作过程中对于共享的内存区域进行操作。
2.3 函数调用约定不匹配
__stdcall和__cdecl分别是两种函数调用约定,它们不一样的地方就是在参数堆栈恢复时,__stdcall是自动恢复,但是__cdecl是手动恢复。
例如:
int __stdcall func1(int a, int b, int c){ int d = a + b + c; return d;}int __cdecl func2(int a, int b, int c){ int d = a + b + c; return d;}int _tmain(int argc, _TCHAR* argv[]){ int a, b; a = func1(1, 2, 3); b = func2(1, 2, 3); return 0;}
反汇编之后的汇编代码是:
int a, b; a = func1(1, 2, 3);013D1A8E push 3 013D1A90 push 2 013D1A92 push 1 013D1A94 call func1 (13D11EAh) 013D1A99 mov dword ptr [a],eax b = func2(1, 2, 3);013D1A9C push 3 013D1A9E push 2 013D1AA0 push 1 013D1AA2 call func2 (13D11EFh) 013D1AA7 add esp,0Ch 013D1AAA mov dword ptr [b],eax return 0;
可以看见调用结束后对堆栈的处理上,__cdecl需要在调用结束后进行堆栈的平衡。那如果在使用函数时没有使用正确的调用约定也会导致栈出问题。例如dll中的函数使用的是__stdcall,但是在实际使用时使用__cdecl进行声明,那么就会出现堆栈不平衡的情况,出现栈内存错误。
参考资料
[1] 维基百科 http://zh.wikipedia.org/wiki/%E5%A0%86%E6%A0%88
- 内存破坏之——栈内存
- windbg-内存破坏实例分析
- Linux下数组非法访问导致内存破坏 —— 引发segmentation fault的原因
- FreeBSD OPIE "__opiereadrec()" 单字节栈内存破坏漏洞
- 27.windbg-内存破坏实例分析
- Java内存机制——栈内存与堆内存
- IPC之—共享内存
- 关于内存思考之二——动态分配内存
- 内存监控方法之——Jstat内存监控
- OC基础—内存管理之set方法内存管理
- OC内存管理之—内存释放原则
- Apple iPhone和iPod Touch Foundation参数内存破坏漏洞
- IE7.0 异常CSS导致内存破坏漏洞
- vc6程序异常崩溃 - stl的basic_string内存破坏
- 内存泄露,缓冲区溢出,堆破坏 的问题
- 堆内存破坏检测实战--附完整调试过程
- JAVA之栈内存与堆内存
- C内存—>内存分配
- 【Spring】Spring下配置注解事务学习笔记
- ionic项目之ngcordova插件
- Dynamics NAVAX Refresh caller form[AX 2012]
- 设计模式实例(Lua)笔记之四(Builder 模式)
- Swift学习笔记(四)函数
- 内存破坏之——栈内存
- [leetcode] Longest Valid Parentheses
- 堆排序
- iOS 苹果地图 MKMapView总结
- c函数调用的堆栈变化
- SPFA算法的基础变形应用
- java.lang.UnsatisfiedLinkError: no snappyjava in java.library.path
- POJ 3259 Wormholes (最短路 SPFA 判断负环)
- HDU 2519 新生晚会 (组合数学)